Browse Source

fix: 补充添加提交

master
张立 7 months ago
parent
commit
92cb96f242
  1. 11
      .env.hella13
  2. 11
      .env.hella14
  3. 11
      .env.hella15
  4. 11
      .env.hella16
  5. 12
      .env.hella8
  6. 11
      .env.hella9
  7. 9
      src/common/config.js
  8. 44
      src/common/noclick.js
  9. BIN
      src/components/kk-printer/empty-icon.png
  10. 416
      src/components/kk-printer/index.vue
  11. 402
      src/components/kk-printer/utils/barcode.js
  12. 723
      src/components/kk-printer/utils/bluetoolth.js
  13. 23
      src/components/kk-printer/utils/index.js
  14. 14633
      src/components/kk-printer/utils/mqtt.js
  15. 1
      src/components/kk-printer/utils/mqtt.min.js
  16. 285
      src/components/kk-printer/utils/printUtil-GBK.js
  17. 778
      src/components/kk-printer/utils/qrcode.js
  18. 171
      src/components/kk-printer/utils/util.js
  19. 95
      src/hybrid/html/point.html
  20. 67
      src/hybrid/html/pointPutawayJob.html
  21. 67
      src/hybrid/html/purchaseReceiptJob.html
  22. 24
      src/libs/versionUpdate.js
  23. 64
      src/mycomponents/balance/handleBalanceBatch.vue
  24. 27
      src/mycomponents/balance/level.vue
  25. 21
      src/mycomponents/balance/light.vue
  26. 55
      src/mycomponents/balance/recommendBalanceBatch.vue
  27. 40
      src/mycomponents/button/comCheckAll.vue
  28. 173
      src/mycomponents/detail/comDetailCardBatch.vue
  29. 138
      src/mycomponents/detail/comJobDetailCard.vue
  30. 151
      src/mycomponents/detail/comJobDetailCardBatch.vue
  31. 178
      src/mycomponents/detail/comLableDetailCard.vue
  32. 185
      src/mycomponents/detail/comRecommendDetailCard.vue
  33. 229
      src/mycomponents/detail/comRecommendDetailCardBatch.vue
  34. 146
      src/mycomponents/detail/detailList.vue
  35. 127
      src/mycomponents/item/itemFilter.vue
  36. 31
      src/mycomponents/job/jobAccept.vue
  37. 24
      src/mycomponents/job/jobComMainCardAsn.vue
  38. 66
      src/mycomponents/job/jobComMainDetailCard.vue
  39. 28
      src/mycomponents/job/jobTopAsn.vue
  40. 68
      src/mycomponents/jobList/jobList.vue
  41. 91
      src/mycomponents/location/locationCompare.vue
  42. 33
      src/mycomponents/package/PackageAndItemCard.vue
  43. 128
      src/mycomponents/package/packageCard.vue
  44. 208
      src/mycomponents/package/packageList.vue
  45. 118
      src/mycomponents/package/packageRecordCard.vue
  46. 163
      src/mycomponents/package/packageRecordList.vue
  47. 144
      src/mycomponents/print/print.vue
  48. 213
      src/mycomponents/qty/numbeIntegerrBox.vue
  49. 205
      src/mycomponents/qty/numberBox.vue
  50. 26
      src/mycomponents/qty/packQty.vue
  51. 40
      src/mycomponents/qty/packUnit.vue
  52. 151
      src/mycomponents/qty/qtyEdit.vue
  53. 86
      src/mycomponents/qty/recommendHandleQty.vue
  54. 205
      src/mycomponents/query/balanceQuery.vue
  55. 293
      src/mycomponents/query/fifoQuery.vue
  56. 68
      src/mycomponents/query/showListItem.vue
  57. 31
      src/mycomponents/receive/receiveBottom.vue
  58. 22
      src/mycomponents/receive/receiveNumber.vue
  59. 30
      src/mycomponents/receive/receiveStatus.vue
  60. 27
      src/mycomponents/receive/receiveTop.vue
  61. 72
      src/mycomponents/receive/recordComDetailCard.vue
  62. 27
      src/mycomponents/receive/recordComMainCard.vue
  63. 141
      src/mycomponents/recommend/recommendBatch.vue
  64. 207
      src/mycomponents/record/recordComDetailCardBatch.vue
  65. 26
      src/mycomponents/record/recordComMainCard.vue
  66. 132
      src/mycomponents/record/recordDetailCard.vue
  67. 243
      src/mycomponents/scan/winCheckFgLabel.vue
  68. 318
      src/mycomponents/scan/winComScanBalance.vue
  69. 295
      src/mycomponents/scan/winComScanBalanceLocation.vue
  70. 198
      src/mycomponents/scan/winComScanCustomerLabel.vue
  71. 299
      src/mycomponents/scan/winComScanFg.vue
  72. 100
      src/mycomponents/scan/winScanFgLabel.vue
  73. 271
      src/mycomponents/scan/winScanPackAndLocationNoBalance.vue
  74. 110
      src/mycomponents/scan/winScanPackJob.vue
  75. 156
      src/mycomponents/scan/winScanPackLevel.vue
  76. 265
      src/mycomponents/scan/winScanPackage.vue
  77. 224
      src/mycomponents/scan/winScanParentPackage.vue
  78. 195
      src/pages/check/checkFgLabel.vue
  79. 96
      src/pages/count/coms/comCountDetailcards.vue
  80. 43
      src/pages/count/coms/comFuzzyCountJobCard.vue
  81. 528
      src/pages/count/job/countBlindDetail.vue
  82. 525
      src/pages/count/job/countDetail1.vue
  83. 662
      src/pages/count/job/countLightDetail.vue
  84. 524
      src/pages/count/job/fuzzyCountDetail.vue
  85. 438
      src/pages/count/job/fuzzyCountJob.vue
  86. 21
      src/pages/customerReturn/coms/comReturnRecordCard.vue
  87. 306
      src/pages/customerReturn/record/recordList.vue
  88. 401
      src/pages/customerReturn/record/recordListDetail.vue
  89. 150
      src/pages/deliver/coms/comDeliverDetailCardBatch.vue
  90. 780
      src/pages/deliver/coms/comScanDeliverPackBatch.vue
  91. 554
      src/pages/deliver/coms/comScanDeliverPackss.vue
  92. 727
      src/pages/deliver/job/deliverDetailBatch.vue
  93. 522
      src/pages/fg/coms/comNoReceiptPopup.vue
  94. 524
      src/pages/fg/coms/comReceiptPopup.vue
  95. 397
      src/pages/fg/fgChange.vue
  96. 506
      src/pages/fg/receiptByPlan.vue
  97. 510
      src/pages/fg/receiptNoPlan.vue
  98. 184
      src/pages/inventoryMove/coms/comInventoryDetailCardBatch.vue
  99. 261
      src/pages/inventoryMove/coms/okToHoldRecordPack.vue
  100. 42
      src/pages/inventoryMove/job/holdToWipMoveJob.vue

11
.env.hella13

@ -0,0 +1,11 @@
VITE_BASE_URL=http://172.21.32.13:81/api/admin-api
VITE_BASE_URL_IMAGE=http://172.21.32.13:81/admin-api
# 租户配置
VITE_TENANT='[{"text":"长春","value":1}]'
# 是否是测试环境
VITE_isDevelopment=false
# 积木报表请求路径
VITE_JMREPORT_BASE_URL='http://172.21.32.13:90'

11
.env.hella14

@ -0,0 +1,11 @@
VITE_BASE_URL=http://172.21.32.14:81/api/admin-api
VITE_BASE_URL_IMAGE=http://172.21.32.14:81/admin-api
# 租户配置
VITE_TENANT='[{"text":"长春","value":1}]'
# 是否是测试环境
VITE_isDevelopment=false
# 积木报表请求路径
VITE_JMREPORT_BASE_URL='http://172.21.32.14:90'

11
.env.hella15

@ -0,0 +1,11 @@
VITE_BASE_URL=https://scp.faway-hella.com:81/api/admin-api
VITE_BASE_URL_IMAGE=https://scp.faway-hella.com:81/admin-api
# 租户配置
VITE_TENANT='[{"text":"长春","value":1}]'
# 是否是测试环境
VITE_isDevelopment=false
# 积木报表请求路径
VITE_JMREPORT_BASE_URL='https://scp.faway-hella.com'

11
.env.hella16

@ -0,0 +1,11 @@
VITE_BASE_URL=https://scptest.faway-hella.com:81/api/admin-api
VITE_BASE_URL_IMAGE=https://scptest.faway-hella.com:81/admin-api
# 租户配置
VITE_TENANT='[{"text":"长春","value":1},{"text":"成都","value":2}]'
# 是否是测试环境
VITE_isDevelopment=false
# 积木报表请求路径
VITE_JMREPORT_BASE_URL='https://scptest.faway-hella.com'

12
.env.hella8

@ -0,0 +1,12 @@
VITE_BASE_URL=http://172.22.32.8:81/api/admin-api
VITE_BASE_URL_IMAGE=http://172.22.32.8:81/admin-api
# 租户配置
VITE_TENANT='[{"text":"成都","value":2}]'
# 是否是测试环境
VITE_isDevelopment=false
# 积木报表请求路径
VITE_JMREPORT_BASE_URL='http://172.22.32.8:90'

11
.env.hella9

@ -0,0 +1,11 @@
VITE_BASE_URL=http://172.22.32.9:81/api/admin-api
VITE_BASE_URL_IMAGE=http://172.22.32.9:81/admin-api
# 租户配置
VITE_TENANT='[{"text":"成都","value":2}]'
# 是否是测试环境
VITE_isDevelopment=false
# 积木报表请求路径
VITE_JMREPORT_BASE_URL='http://172.22.32.9:90'

9
src/common/config.js

@ -0,0 +1,9 @@
export const overPagePrint="overPage_print"
export const overPageTemplate="overPage_Template"
//3分钟刷新
export const planRefreshTime=3*60*1000
export const issueJobFilter="issue_job_filter"
export const repleinshJobFilter="repleinsh_job_filter"
export const overPackageJobFilter="over_package_job_filter"
export const productionReceiptJobFilter="production_receipt_job_filter"

44
src/common/noclick.js

@ -0,0 +1,44 @@
// 防止处理多次点击
function noMultipleClicks(methods, info) {
// methods是需要点击后需要执行的函数, info是点击需要传的参数
let that = this;
if (that.noClick) {
// 第一次点击
that.noClick= false;
if(info && info !== '') {
// info是执行函数需要传的参数
methods(info);
} else {
methods();
}
let timer = setTimeout(()=> {
that.noClick= true;
clearTimeout(timer)
}, 2000)
} else {
// 这里是重复点击的判断
}
}
// 节流函数
const throttle = (fn, t,_this) => {
console.log('throttle')
return ()=> {
if (!_this.timer) {
_this.timer = setTimeout(()=>{
console.log('fn')
//·清空定时器
_this.timer = null
}, t)
fn()
}
}
}
//导出
export default {
noMultipleClicks,//禁止多次点击
throttle
}

BIN
src/components/kk-printer/empty-icon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

416
src/components/kk-printer/index.vue

@ -0,0 +1,416 @@
<template>
<view class="kk-printer">
<view class="kk-printer-btn" @tap="handlePrintTap">
{{isPrinting?printingText:defaultText}}
</view>
<view class="kk-shadow" :class="isShowSearch?'show':''" @tap="handleSearchClose">
<view class="kk-modal" @tap.stop="doNothing">
<view class="kk-search-device">
<view class="kk-filter-wrap">
<view class="filter-title">根据SRRI过滤设备</view>
<slider @change="handleSRRIChange" max='-20' min='-100' value="-95" show-value/>
</view>
<view class="kk-filter-wrap">
<view class="filter-title">根据蓝牙名过滤</view>
<input type="text" placeholder-class="kk-placeholder-class" placeholder="请输入蓝牙名字或设备ID搜索" v-model="filterName" />
</view>
<view class="kk-btn-wrap">
<view class="kk-btn-item confirm-btn" @tap="searchBtnTap" v-if="!isSearching">
搜索设备
</view>
<view class="kk-btn-item confirm-btn" v-else>
搜索中...
</view>
<view class="kk-btn-item" @tap="stopSearchBtnTap">
停止搜索
</view>
</view>
<view class="kk-devices-wrap">
<view class="empty-wrap" v-if="filterDeviceList.length <= 0">
<view class="empty-icon"></view>
<view class="empty-text">~ 无可搜索到的设备 ~</view>
</view>
<view class="" v-else>
<view class="kk-devices-item" v-for="(item,index) in filterDeviceList" :key="index" @tap="handleConnectDevice(item)">
<view class="name">
<text>设备名称</text>
<text>{{item.name?item.name:'未命名'}}</text>
</view>
<view class="rssi">
<text>信号强度</text>
<text>({{Math.max(0, item.RSSI + 100)}}%)</text>
</view>
<view class="deviceid">
<text>设备ID</text>
<text>{{item.deviceId}}</text>
</view>
<view class="advmac" v-if="item.advMac">
<text>advMac</text>
<text>{{item.advMac}}</text>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import * as gbk from '@/components/kk-printer/utils/printUtil-GBK.js';
import * as blesdk from './utils/bluetoolth';
import * as util from './utils/util.js';
export default {
data(){
return{
//
isPrinting:false,
//
isSearching:false,
//
isShowSearch:false,
//
filterName:'',
//
filterRSSI:-95,
//
devicesList:[],
//ID
deviceId:'',
//ID
services:'',
//
serviceId: '',
writeId: '',
readId: ''
}
},
props:{
//
defaultText:{
type:String,
default:'打印'
},
//
printingText:{
type:String,
default:'打印中...'
},
bufferData:{
type:String,
require:true
}
},
computed:{
mapFilterRSSI(){
return (0 - this.filterRSSI)
},
filterDeviceList(){
let devices = this.devicesList;
let name = this.filterName;
let rssi = this.filterRSSI;
console.log(devices,name,rssi)
//RSSI
let filterDevices1 = devices.filter((item)=>{
return item.RSSI > rssi
})
console.log(filterDevices1)
//
let filterDevices2
if(name!=''){
filterDevices2 = filterDevices1.filter((item)=>{
return (item.name.indexOf(name) >= 0 || item.deviceId.indexOf(name) >= 0)
})
}else{
filterDevices2 = filterDevices1
}
// 广MAC
for (let i = 0; i < filterDevices2.length;i++) {
if (filterDevices2[i].hasOwnProperty('advertisData')){
if (filterDevices2[i].advertisData.byteLength == 8) {
filterDevices2[i].advMac = util.buf2hex(filterDevices2[i].advertisData.slice(2, 7));
}
}
}
return filterDevices2
}
},
mounted() {
},
beforeDestroy(){
this.stopSearchBtnTap();
},
methods:{
doNothing(){
return;
},
//
handlePrintTap(){
console.log(11)
//
blesdk.openBlue().then((res)=>{
console.log(99,res)
//
blesdk.getConnectedBluetoothDevices().then((res)=>{
//
console.log(66,res,this.deviceId,this.serviceId,this.writeId,this.bufferData,this.onPrintSuccess)
if(res.devices.length == 0){
this.isShowSearch = true
}else{
let datalen=20;
if (plus.os.name != 'Android')
{
datalen=180;
}
this.isPrinting = true;
this.$emit('onPrint');
this.$nextTick(()=>{
console.log(1,this.bufferData)
if(this.bufferData!=''){
let buffer = gbk.strToGBKByte(this.bufferData)
console.log(2,buffer)
let opt = {
deviceId: this.deviceId,
serviceId: this.serviceId,
characteristicId: this.writeId,
value:buffer,
lasterSuccess: this.onPrintSuccess,
onceLength:datalen
}
console.log(3,opt)
blesdk.sendDataToDevice(opt);
this.isPrinting = false;
}
})
}
}).catch((err)=>{
console.log(88,err)
blesdk.catchToast(err);
})
}).catch((err)=>{
console.log(77,err)
blesdk.catchToast(err);
})
},
onGetDevice(res){
this.devicesList = res;
},
handleSearchClose(){
this.isShowSearch = false
},
handleSRRIChange(e){
this.filterRSSI = e.detail.value
},
//
searchBtnTap(){
blesdk.startBluetoothDevicesDiscovery();
this.isSearching = true;
blesdk.onfindBlueDevices(this.onGetDevice)
},
//
stopSearchBtnTap(){
blesdk.stopBlueDevicesDiscovery();
this.isSearching = false;
},
//
handleConnectDevice(device){
let deviceId = device.deviceId;
let name = device.name;
this.deviceId = deviceId;
console.log('deviceId',this.deviceId)
// uni.setStorageSync('k_curDeviceID',deviceId);
// uni.setStorageSync('k_curDeviceName',name);
uni.onBLEConnectionStateChange((res)=>{
console.log('连接',res)
if(res.connected){
plus.nativeUI.toast('设备'+ res.deviceId + '已连接',{
verticalAlign:'center'
})
}else{
plus.nativeUI.toast('设备'+ res.deviceId + '已断开连接',{
verticalAlign:'center'
})
}
})
blesdk.createBLEConnection(deviceId, this.onConnectSuccess, this.onConnectFail);
},
onConnectSuccess(res){
this.stopSearchBtnTap()
blesdk.getBLEDeviceServices(this.deviceId, this.onGetServicesSuccess, this.onGetServicesFail);
},
onConnectFail(err){
console.log('链接失败',err)
},
onGetServicesSuccess(res){
console.log('获取服务',res)
this.services = res.serviceId;
blesdk.getDeviceCharacteristics(this.deviceId, this.services, this.onGetCharacterSuccess, this.onGetCharacterFail);
},
onGetServicesFail(err){
console.log('获取服务失败')
},
onGetCharacterSuccess(res){
console.log('获取特征值成功',res)
this.serviceId = res.serviceId;
this.writeId = res.writeId;
this.readId = res.readId;
this.isShowSearch = false;
},
onGetCharacterFail(err){
console.log('特征值获取失败')
},
onPrintSuccess(){
this.isPrinting = false;
console.log('打印成功')
this.$emit('onPrintSuccess')
},
onPrintFail(){
console.log('打印失败')
this.isPrinting = false;
}
}
}
</script>
<style lang="scss" scoped>
.kk-printer{
width:100%;
height:100%;
&-btn{
width:100%;
height:100%;
text-align: center;
line-height: 50px;
}
.kk-shadow{
display: none;
&.show{
display: block;
width:100vw;
height:100vh;
background: rgba(0,0,0,0.4);
position: fixed;
top: 0;
left: 0;
display: flex;
justify-content: center;
align-items: center;
.kk-modal{
width:680upx;
height: 80%;
padding:24upx;
box-sizing: border-box;
overflow-y: auto;
border-radius: 20upx;
background: #ffffff;
display: flex;
justify-content: center;
align-items: center;
.kk-search-device{
width:100%;
height: 100%;
.kk-filter-wrap{
width:100%;
height: 160upx;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: flex-start;
.filter-title{
line-height: 70upx;
font-size: 30upx;
color: #999999;
}
&>slider{
width:90%;
height: 90upx;
}
&>input{
padding:0 20upx;
box-sizing: border-box;
border-radius: 10upx;
height: 90upx;
width:100%;
border: 1upx solid #ebebeb;
}
}
.kk-btn-wrap{
width:100%;
height: 140upx;
display: flex;
justify-content: space-between;
align-items: center;
&>view{
flex:1 1 auto;
height: 100upx;
line-height: 100upx;
border-radius: 16upx;
text-align: center;
color:#ffffff;
&.confirm-btn{
background: #007AFF;
margin-right:30upx;
}
&:nth-last-child(1){
background: #DD524D;
}
}
}
.kk-devices-wrap{
height: calc(100% - 460upx);
overflow-y:auto;
padding:10upx 20upx;
box-sizing: border-box;
border: 1upx solid #ebebeb;
box-sizing: border-box;
border-radius: 20upx;
.empty-wrap{
width:100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.empty-icon{
width:268upx;
height: 240upx;
background: url('./empty-icon.png') no-repeat;
background-size:100% 100%;
margin-bottom: 26upx;
}
.empty-text{
width: 100%;
line-height: 50upx;
font-size: 30upx;
text-align: center;
color: #999999;
}
}
.kk-devices-item{
width:100%;
border-bottom: 1upx solid #ebebeb;
padding:10upx 0;
box-sizing: border-box;
&:nth-last-child(1){
border-bottom: none;
}
&>view{
width:100%;
font-size: 30upx;
}
}
}
}
}
}
}
}
.kk-placeholder-class{
font-size: 30upx;
color:#999999;
}
</style>

402
src/components/kk-printer/utils/barcode.js

@ -0,0 +1,402 @@
var CHAR_TILDE = 126;
var CODE_FNC1 = 102;
var SET_STARTA = 103;
var SET_STARTB = 104;
var SET_STARTC = 105;
var SET_SHIFT = 98;
var SET_CODEA = 101;
var SET_CODEB = 100;
var SET_STOP = 106;
var REPLACE_CODES = {
CHAR_TILDE: CODE_FNC1 //~ corresponds to FNC1 in GS1-128 standard
}
var CODESET = {
ANY: 1,
AB: 2,
A: 3,
B: 4,
C: 5
};
function getBytes(str) {
var bytes = [];
for (var i = 0; i < str.length; i++) {
bytes.push(str.charCodeAt(i));
}
return bytes;
}
exports.code128 = function (ctx, text, width, height) {
width = parseInt(width);
height = parseInt(height);
var codes = stringToCode128(text);
var g = new Graphics(ctx, width, height);
var barWeight = g.area.width / ((codes.length - 3) * 11 + 35);
var x = g.area.left;
var y = g.area.top;
for (var i = 0; i < codes.length; i++) {
var c = codes[i];
//two bars at a time: 1 black and 1 white
for (var bar = 0; bar < 8; bar += 2) {
var barW = PATTERNS[c][bar] * barWeight;
// var barH = height - y - this.border;
var barH = height - y;
var spcW = PATTERNS[c][bar + 1] * barWeight;
//no need to draw if 0 width
if (barW > 0) {
g.fillFgRect(x, y, barW, barH);
}
x += barW + spcW;
}
}
ctx.draw();
}
function stringToCode128(text) {
var barc = {
currcs: CODESET.C
};
var bytes = getBytes(text);
//decide starting codeset
var index = bytes[0] == CHAR_TILDE ? 1 : 0;
var csa1 = bytes.length > 0 ? codeSetAllowedFor(bytes[index++]) : CODESET.AB;
var csa2 = bytes.length > 0 ? codeSetAllowedFor(bytes[index++]) : CODESET.AB;
barc.currcs = getBestStartSet(csa1, csa2);
barc.currcs = perhapsCodeC(bytes, barc.currcs);
//if no codeset changes this will end up with bytes.length+3
//start, checksum and stop
var codes = new Array();
switch (barc.currcs) {
case CODESET.A:
codes.push(SET_STARTA);
break;
case CODESET.B:
codes.push(SET_STARTB);
break;
default:
codes.push(SET_STARTC);
break;
}
for (var i = 0; i < bytes.length; i++) {
var b1 = bytes[i]; //get the first of a pair
//should we translate/replace
if (b1 in REPLACE_CODES) {
codes.push(REPLACE_CODES[b1]);
i++ //jump to next
b1 = bytes[i];
}
//get the next in the pair if possible
var b2 = bytes.length > (i + 1) ? bytes[i + 1] : -1;
codes = codes.concat(codesForChar(b1, b2, barc.currcs));
//code C takes 2 chars each time
if (barc.currcs == CODESET.C) i++;
}
//calculate checksum according to Code 128 standards
var checksum = codes[0];
for (var weight = 1; weight < codes.length; weight++) {
checksum += (weight * codes[weight]);
}
codes.push(checksum % 103);
codes.push(SET_STOP);
//encoding should now be complete
return codes;
function getBestStartSet(csa1, csa2) {
//tries to figure out the best codeset
//to start with to get the most compact code
var vote = 0;
vote += csa1 == CODESET.A ? 1 : 0;
vote += csa1 == CODESET.B ? -1 : 0;
vote += csa2 == CODESET.A ? 1 : 0;
vote += csa2 == CODESET.B ? -1 : 0;
//tie goes to B due to my own predudices
return vote > 0 ? CODESET.A : CODESET.B;
}
function perhapsCodeC(bytes, codeset) {
for (var i = 0; i < bytes.length; i++) {
var b = bytes[i]
if ((b < 48 || b > 57) && b != CHAR_TILDE)
return codeset;
}
return CODESET.C;
}
//chr1 is current byte
//chr2 is the next byte to process. looks ahead.
function codesForChar(chr1, chr2, currcs) {
var result = [];
var shifter = -1;
if (charCompatible(chr1, currcs)) {
if (currcs == CODESET.C) {
if (chr2 == -1) {
shifter = SET_CODEB;
currcs = CODESET.B;
}
else if ((chr2 != -1) && !charCompatible(chr2, currcs)) {
//need to check ahead as well
if (charCompatible(chr2, CODESET.A)) {
shifter = SET_CODEA;
currcs = CODESET.A;
}
else {
shifter = SET_CODEB;
currcs = CODESET.B;
}
}
}
}
else {
//if there is a next char AND that next char is also not compatible
if ((chr2 != -1) && !charCompatible(chr2, currcs)) {
//need to switch code sets
switch (currcs) {
case CODESET.A:
shifter = SET_CODEB;
currcs = CODESET.B;
break;
case CODESET.B:
shifter = SET_CODEA;
currcs = CODESET.A;
break;
}
}
else {
//no need to shift code sets, a temporary SHIFT will suffice
shifter = SET_SHIFT;
}
}
//ok some type of shift is nessecary
if (shifter != -1) {
result.push(shifter);
result.push(codeValue(chr2));
}
else {
if (currcs == CODESET.C) {
//include next as well
result.push(codeValue(chr1, chr2));
}
else {
result.push(codeValue(chr1));
}
}
barc.currcs = currcs;
return result;
}
}
//reduce the ascii code to fit into the Code128 char table
function codeValue(chr1, chr2) {
if (typeof chr2 == "undefined") {
return chr1 >= 32 ? chr1 - 32 : chr1 + 64;
}
else {
return parseInt(String.fromCharCode(chr1) + String.fromCharCode(chr2));
}
}
function charCompatible(chr, codeset) {
var csa = codeSetAllowedFor(chr);
if (csa == CODESET.ANY) return true;
//if we need to change from current
if (csa == CODESET.AB) return true;
if (csa == CODESET.A && codeset == CODESET.A) return true;
if (csa == CODESET.B && codeset == CODESET.B) return true;
return false;
}
function codeSetAllowedFor(chr) {
if (chr >= 48 && chr <= 57) {
//0-9
return CODESET.ANY;
}
else if (chr >= 32 && chr <= 95) {
//0-9 A-Z
return CODESET.AB;
}
else {
//if non printable
return chr < 32 ? CODESET.A : CODESET.B;
}
}
var Graphics = function(ctx, width, height) {
this.width = width;
this.height = height;
this.quiet = Math.round(this.width / 40);
this.border_size = 0;
this.padding_width = 0;
this.area = {
width : width - this.padding_width * 2 - this.quiet * 2,
height: height - this.border_size * 2,
top : this.border_size - 4,
left : this.padding_width + this.quiet
};
this.ctx = ctx;
this.fg = "#000000";
this.bg = "#ffffff";
// fill background
this.fillBgRect(0,0, width, height);
// fill center to create border
this.fillBgRect(0, this.border_size, width, height - this.border_size * 2);
}
//use native color
Graphics.prototype._fillRect = function(x, y, width, height, color) {
this.ctx.setFillStyle(color)
this.ctx.fillRect(x, y, width, height)
}
Graphics.prototype.fillFgRect = function(x,y, width, height) {
this._fillRect(x, y, width, height, this.fg);
}
Graphics.prototype.fillBgRect = function(x,y, width, height) {
this._fillRect(x, y, width, height, this.bg);
}
var PATTERNS = [
[2, 1, 2, 2, 2, 2, 0, 0], // 0
[2, 2, 2, 1, 2, 2, 0, 0], // 1
[2, 2, 2, 2, 2, 1, 0, 0], // 2
[1, 2, 1, 2, 2, 3, 0, 0], // 3
[1, 2, 1, 3, 2, 2, 0, 0], // 4
[1, 3, 1, 2, 2, 2, 0, 0], // 5
[1, 2, 2, 2, 1, 3, 0, 0], // 6
[1, 2, 2, 3, 1, 2, 0, 0], // 7
[1, 3, 2, 2, 1, 2, 0, 0], // 8
[2, 2, 1, 2, 1, 3, 0, 0], // 9
[2, 2, 1, 3, 1, 2, 0, 0], // 10
[2, 3, 1, 2, 1, 2, 0, 0], // 11
[1, 1, 2, 2, 3, 2, 0, 0], // 12
[1, 2, 2, 1, 3, 2, 0, 0], // 13
[1, 2, 2, 2, 3, 1, 0, 0], // 14
[1, 1, 3, 2, 2, 2, 0, 0], // 15
[1, 2, 3, 1, 2, 2, 0, 0], // 16
[1, 2, 3, 2, 2, 1, 0, 0], // 17
[2, 2, 3, 2, 1, 1, 0, 0], // 18
[2, 2, 1, 1, 3, 2, 0, 0], // 19
[2, 2, 1, 2, 3, 1, 0, 0], // 20
[2, 1, 3, 2, 1, 2, 0, 0], // 21
[2, 2, 3, 1, 1, 2, 0, 0], // 22
[3, 1, 2, 1, 3, 1, 0, 0], // 23
[3, 1, 1, 2, 2, 2, 0, 0], // 24
[3, 2, 1, 1, 2, 2, 0, 0], // 25
[3, 2, 1, 2, 2, 1, 0, 0], // 26
[3, 1, 2, 2, 1, 2, 0, 0], // 27
[3, 2, 2, 1, 1, 2, 0, 0], // 28
[3, 2, 2, 2, 1, 1, 0, 0], // 29
[2, 1, 2, 1, 2, 3, 0, 0], // 30
[2, 1, 2, 3, 2, 1, 0, 0], // 31
[2, 3, 2, 1, 2, 1, 0, 0], // 32
[1, 1, 1, 3, 2, 3, 0, 0], // 33
[1, 3, 1, 1, 2, 3, 0, 0], // 34
[1, 3, 1, 3, 2, 1, 0, 0], // 35
[1, 1, 2, 3, 1, 3, 0, 0], // 36
[1, 3, 2, 1, 1, 3, 0, 0], // 37
[1, 3, 2, 3, 1, 1, 0, 0], // 38
[2, 1, 1, 3, 1, 3, 0, 0], // 39
[2, 3, 1, 1, 1, 3, 0, 0], // 40
[2, 3, 1, 3, 1, 1, 0, 0], // 41
[1, 1, 2, 1, 3, 3, 0, 0], // 42
[1, 1, 2, 3, 3, 1, 0, 0], // 43
[1, 3, 2, 1, 3, 1, 0, 0], // 44
[1, 1, 3, 1, 2, 3, 0, 0], // 45
[1, 1, 3, 3, 2, 1, 0, 0], // 46
[1, 3, 3, 1, 2, 1, 0, 0], // 47
[3, 1, 3, 1, 2, 1, 0, 0], // 48
[2, 1, 1, 3, 3, 1, 0, 0], // 49
[2, 3, 1, 1, 3, 1, 0, 0], // 50
[2, 1, 3, 1, 1, 3, 0, 0], // 51
[2, 1, 3, 3, 1, 1, 0, 0], // 52
[2, 1, 3, 1, 3, 1, 0, 0], // 53
[3, 1, 1, 1, 2, 3, 0, 0], // 54
[3, 1, 1, 3, 2, 1, 0, 0], // 55
[3, 3, 1, 1, 2, 1, 0, 0], // 56
[3, 1, 2, 1, 1, 3, 0, 0], // 57
[3, 1, 2, 3, 1, 1, 0, 0], // 58
[3, 3, 2, 1, 1, 1, 0, 0], // 59
[3, 1, 4, 1, 1, 1, 0, 0], // 60
[2, 2, 1, 4, 1, 1, 0, 0], // 61
[4, 3, 1, 1, 1, 1, 0, 0], // 62
[1, 1, 1, 2, 2, 4, 0, 0], // 63
[1, 1, 1, 4, 2, 2, 0, 0], // 64
[1, 2, 1, 1, 2, 4, 0, 0], // 65
[1, 2, 1, 4, 2, 1, 0, 0], // 66
[1, 4, 1, 1, 2, 2, 0, 0], // 67
[1, 4, 1, 2, 2, 1, 0, 0], // 68
[1, 1, 2, 2, 1, 4, 0, 0], // 69
[1, 1, 2, 4, 1, 2, 0, 0], // 70
[1, 2, 2, 1, 1, 4, 0, 0], // 71
[1, 2, 2, 4, 1, 1, 0, 0], // 72
[1, 4, 2, 1, 1, 2, 0, 0], // 73
[1, 4, 2, 2, 1, 1, 0, 0], // 74
[2, 4, 1, 2, 1, 1, 0, 0], // 75
[2, 2, 1, 1, 1, 4, 0, 0], // 76
[4, 1, 3, 1, 1, 1, 0, 0], // 77
[2, 4, 1, 1, 1, 2, 0, 0], // 78
[1, 3, 4, 1, 1, 1, 0, 0], // 79
[1, 1, 1, 2, 4, 2, 0, 0], // 80
[1, 2, 1, 1, 4, 2, 0, 0], // 81
[1, 2, 1, 2, 4, 1, 0, 0], // 82
[1, 1, 4, 2, 1, 2, 0, 0], // 83
[1, 2, 4, 1, 1, 2, 0, 0], // 84
[1, 2, 4, 2, 1, 1, 0, 0], // 85
[4, 1, 1, 2, 1, 2, 0, 0], // 86
[4, 2, 1, 1, 1, 2, 0, 0], // 87
[4, 2, 1, 2, 1, 1, 0, 0], // 88
[2, 1, 2, 1, 4, 1, 0, 0], // 89
[2, 1, 4, 1, 2, 1, 0, 0], // 90
[4, 1, 2, 1, 2, 1, 0, 0], // 91
[1, 1, 1, 1, 4, 3, 0, 0], // 92
[1, 1, 1, 3, 4, 1, 0, 0], // 93
[1, 3, 1, 1, 4, 1, 0, 0], // 94
[1, 1, 4, 1, 1, 3, 0, 0], // 95
[1, 1, 4, 3, 1, 1, 0, 0], // 96
[4, 1, 1, 1, 1, 3, 0, 0], // 97
[4, 1, 1, 3, 1, 1, 0, 0], // 98
[1, 1, 3, 1, 4, 1, 0, 0], // 99
[1, 1, 4, 1, 3, 1, 0, 0], // 100
[3, 1, 1, 1, 4, 1, 0, 0], // 101
[4, 1, 1, 1, 3, 1, 0, 0], // 102
[2, 1, 1, 4, 1, 2, 0, 0], // 103
[2, 1, 1, 2, 1, 4, 0, 0], // 104
[2, 1, 1, 2, 3, 2, 0, 0], // 105
[2, 3, 3, 1, 1, 1, 2, 0] // 106
]

723
src/components/kk-printer/utils/bluetoolth.js

@ -0,0 +1,723 @@
/**
* @export
* @param {string} name 微信api的名称 uniAsyncPromise("getSystemInfo",options)
* @param {object} options 除了success fail 的其他参数
* @returns
*/
export function uniAsyncPromise(name, options) {
return new Promise((resolve, reject) => {
uni[name]({
...(options || {}),
// ...options,
success: (res) => {
resolve(res);
},
fail: (err) => {
reject(err);
}
});
});
}
//微信小程序向蓝牙打印机发送数据进行打印的坑:
//小程序api向蓝牙打印机发送数据打印,发送的任何内容都应该要转成二进制数据,而且蓝牙打印的文本编码是GBK的,发送中文需转成GBK编码再转成二进制数据发送
//发送打印机指令也要转成二进制数据发送
//蓝牙打印机一次接收的二级制数据有限制,不同的系统不同的蓝牙设备限制可能不同,微信建议一次20个字节,需做递归分包发送
//发送完要打印的内容后,一定要发送一个打印的指令才能顺利打印 (有些指令就不需要)
//一、初始化蓝牙、开始检索蓝牙设备
// { allowDuplicatesKey: true, interval: 500}
export function openBlue() {
return uniAsyncPromise('openBluetoothAdapter')
}
export function startBluetoothDevicesDiscovery(option) {
console.log('开始蓝牙扫描');
uniAsyncPromise('startBluetoothDevicesDiscovery', option).then((res) => {
console.log('正在搜寻蓝牙设备', res);
});
}
export function getConnectedBluetoothDevices(option) {
console.log('开始获取已连接设备');
return uniAsyncPromise('getConnectedBluetoothDevices', option)
}
//二、
/**
*
*
* @export
* @param {function} getDevices uni.getBluetoothDevices的监听回调函数
*/
export function onfindBlueDevices(getDevices) {
//监听寻找到新设备的事件
uni.onBluetoothDeviceFound((devices)=>{
//获取在蓝牙模块生效期间所有已发现的蓝牙设备
uniAsyncPromise('getBluetoothDevices').then((res) => {
getDevices && getDevices(res.devices);
});
});
}
/**
* @export
* @param {function} stopBlueDevicesDiscovery 关闭蓝牙扫描
*/
export function stopBlueDevicesDiscovery() {
//监听寻找到新设备的事件
console.log('停止蓝牙扫描');
return uniAsyncPromise('stopBluetoothDevicesDiscovery').then((res) => {
console.log('停止搜寻蓝牙设备', res);
});
}
//三、连接蓝牙设备
/**
* @export
* @param {function} createBLEConnection
* @param {number} deviceId 蓝牙设备id
*/
export function createBLEConnection(deviceId, sucess, fail) {
//连接蓝牙设备
console.log('连接蓝牙设备', deviceId);
uniAsyncPromise("createBLEConnection", {
deviceId
})
.then(res => {
//连接成功可选择停止搜索蓝牙
//stopBlueDevicesDiscovery();
console.log('连接成功');
sucess && sucess({
res: res,
});
})
.catch(res => {
console.log('连接设备异常' + res);
fail && fail({
res: res,
});
})
/*.finally(res=>{
console.log('连接成功');
sucess && sucess({
res: res,
});
});*/
}
export function closeBLEConnection(deviceId) {
console.log('断开蓝牙设备', deviceId);
uniAsyncPromise("closeBLEConnection", {
deviceId
})
.then(res => {
console.log('BLEDisconnect complete', res);
})
.catch(res => {
console.log('断开设备异常' + res);
})
/*.finally(res=>{
console.log('BLEDisconnect complete', res);
}); */
}
//四、连接成功后, 获取蓝牙设备的service服务
// uniAsyncPromise("getBLEDeviceServices",{deviceId:""}).then(res=>{})
export function getBLEDeviceServices(deviceId, success, fail) {
console.log('获取ServiceId', deviceId);
//加延迟避免取不到service
setTimeout(()=>{
uniAsyncPromise("getBLEDeviceServices", {
deviceId:deviceId
})
.then(res => {
console.log('服务', res);
success && success({
serviceId: res.services,
});
})
.catch((res) => {
//getBLEDeviceServices(deviceId, success, fail);
console.log('获取ServiceId异常' + res);
fail && fail({
res: res,
});
});
},1000)
}
//五、获取的service服务可能有多个,递归获取特征值(最后要用的是能读,能写,能监听的那个值的uuid作为特征值id)
/**
*
*
* @export
* @param {number} deviceId 蓝牙设备id
* @param {array} services uniAsyncPromise("getBLEDeviceServices",{deviceId:""}).then(res=>{})获取的res.services
* @param {function} success 成功取得有用特征值uuid的回调函数
*/
export function getDeviceCharacteristics(deviceId, services, success, fail) {
//services = services.slice(0);
console.log('获取Characteristics', deviceId, services);
if (services.length) {
const serviceId = services.shift().uuid;
console.log('ServceID ', serviceId);
uniAsyncPromise('getBLEDeviceCharacteristics', {
deviceId,
serviceId,
})
.then((res) => {
console.log('getBLEDeviceCharacteristics', deviceId, serviceId, res);
let finished = false;
let write = false;
let notify = false;
let indicate = false;
var readId;
var writeId;
//有斑马品牌的一款打印机中res.characteristics的所有uuid都是相同的,找所有的properties存在(notify || indicate) && write这种情况就说明这个uuid是可用的(不确保所有的打印机都能用这种方式取得uuid,在主要测试得凯盛诺打印机res.characteristic只有一个uuid,所以也能用这个方式)
for (var i = 0; i < res.characteristics.length; i++) {
if (!notify) {
notify = res.characteristics[i].properties.notify;
if (notify) readId = res.characteristics[i].uuid;
}
if (!indicate) {
indicate = res.characteristics[i].properties.indicate;
if (indicate) readId = res.characteristics[i].uuid;
}
if (!write) {
write = res.characteristics[i].properties.write;
writeId = res.characteristics[i].uuid;
}
if ((notify || indicate) && write) {
/* 获取蓝牙特征值uuid */
success &&
success({
serviceId,
writeId: writeId,
readId: readId,
});
finished = true;
break;
}
}
if (!finished) {
getDeviceCharacteristics(deviceId, services, success, fail);
}
})
.catch((res) => {
getDeviceCharacteristics(deviceId, services, success, fail);
});
} else {
fail && fail();
}
}
//六、启动notify 蓝牙监听功能 然后使用 uni.onBLECharacteristicValueChange用来监听蓝牙设备传递数据
/**
* @export
* @param {object} options
* {
deviceId,//蓝牙设备id
serviceId,//服务id
characteristicId,//可用特征值uuid
}
* @param {function} onChange 监听蓝牙设备传递数据回调函数
*/
export function onGetBLECharacteristicValueChange(options, onChange = function() {}) {
console.log('deviceId ', options.deviceId);
console.log('serviceId ', options.serviceId);
console.log('characteristicId ', options.characteristicId);
uniAsyncPromise('notifyBLECharacteristicValueChange', {
state: true,
...options,
}).then((res) => {
console.log('onBLECharacteristicValueChange ');
uni.onBLECharacteristicValueChange(onChange);
});
}
//七、发送数据(递归分包发送)
/**
* @export
* @param {object} options
* {
deviceId,
serviceId,
characteristicId,
value [ArrayBuffer],
lasterSuccess,
onceLength
}
*/
export function sendDataToDevice(options) {
let byteLength = options.value.byteLength;
//这里默认一次20个字节发送
const speed = options.onceLength; //20;
console.log("send data 20");
console.log(options);
if (byteLength > 0) {
uniAsyncPromise('writeBLECharacteristicValue', {
...options,
value: options.value.slice(0, byteLength > speed ? speed : byteLength),
})
.then((res) => {
if (byteLength > speed) {
sendDataToDevice({
...options,
value: options.value.slice(speed, byteLength),
});
} else {
options.lasterSuccess && options.lasterSuccess();
}
})
.catch((res) => {
console.log(res);
});
}
}
export function charToArrayBuffer(str) {
var out = new ArrayBuffer(str.length);
var uint8 = new Uint8Array(out);
var strs = str.split('');
for (var i = 0; i < strs.length; i++) {
uint8[i] = strs[i].charCodeAt();
}
return uint8;
}
export function charToArray(str) {
var arr = [];
var strs = str.split('');
for (var i = 0; i < strs.length; i++) {
arr[i] = strs[i].charCodeAt();
}
return arr;
}
//打印二维码
/**
* @export
* @param {object} options
* {
deviceId,
serviceId,
characteristicId,
value,//ArrayBuffer:二维码的数据
}
*/
export function printQR(options) {
//打印二维码的十进制指令data:
let data = [29, 107, 97, 7, 4, options.value.byteLength, 0];
sendDataToDevice({
...options,
value: new Uint8Array(data).buffer,
lasterSuccess: () => {
//指令发送成功后,发送二维码的数据
sendDataToDevice(options);
},
});
}
function grayPixle(pix) {
return pix[0] * 0.299 + pix[1] * 0.587 + pix[2] * 0.114;
}
export function overwriteImageData(data) {
let sendWidth = data.width,
sendHeight = data.height;
const threshold = data.threshold || 180;
let sendImageData = new ArrayBuffer((sendWidth * sendHeight) / 8);
sendImageData = new Uint8Array(sendImageData);
let pix = data.imageData;
const part = [];
let index = 0;
for (let i = 0; i < pix.length; i += 32) {
//横向每8个像素点组成一个字节(8位二进制数)。
for (let k = 0; k < 8; k++) {
const grayPixle1 = grayPixle(pix.slice(i + k * 4, i + k * 4 + (4 - 1)));
//阈值调整
if (grayPixle1 > threshold) {
//灰度值大于threshold位 白色 为第k位0不打印
part[k] = 0;
} else {
part[k] = 1;
}
}
let temp = 0;
for (let a = 0; a < part.length; a++) {
temp += part[a] * Math.pow(2, part.length - 1 - a);
}
//开始不明白以下算法什么意思,了解了字节才知道,一个字节是8位的二进制数,part这个数组存的0和1就是二进制的0和1,传输到打印的位图数据的一个字节是0-255之间的十进制数,以下是用权相加法转十进制数,理解了这个就用上面的for循环替代了
// const temp =
// part[0] * 128 +
// part[1] * 64 +
// part[2] * 32 +
// part[3] * 16 +
// part[4] * 8 +
// part[5] * 4 +
// part[6] * 2 +
// part[7] * 1;
sendImageData[index++] = temp;
}
return {
array: Array.from(sendImageData),
width: sendWidth / 8,
height: sendHeight,
};
}
/**
* printImage
* @param {object} opt
* {
deviceId,//蓝牙设备id
serviceId,//服务id
characteristicId,//可用特征值uuid
lasterSuccess , //最后完成的回调
}
*/
export function printImage(opt = {}, imageInfo = {}) {
let arr = imageInfo.array,
width = imageInfo.width;
const writeArray = [];
const xl = width % 256;
const xh = width / 256;
//分行发送图片数据,用的十进制指令
const command = [29, 118, 48, 0, xl, xh, 1, 0]; //1D 76 30 00 w h
const enter = [13, 10];
for (let i = 0; i < arr.length / width; i++) {
const subArr = arr.slice(i * width, i * width + width);
const tempArr = command.concat(subArr);
writeArray.push(new Uint8Array(tempArr));
}
writeArray.push(new Uint8Array(enter));
//console.log(writeArray);
const print = (options, writeArray) => {
if (writeArray.length) {
console.log("send");
sendDataToDevice({
...options,
value: writeArray.shift().buffer,
lasterSuccess: () => {
if (writeArray.length) {
print(options, writeArray);
} else {
options.lasterSuccess && options.lasterSuccess();
}
},
});
}
};
console.log("start print");
print(opt, writeArray);
}
/* 16hex insert 0 */
function Hex2Str(num) {
if (num.toString(16).length < 2) return "0" + num.toString(16);
else
return num.toString(16);
}
/*****CPCL指令接口****/
/**
* 配置项如下
*
* width: 标签纸的宽度单位像素點
* height: 标签纸的高度单位像素點
* 8像素=1mm
* printNum: 打印张数默认为1
* rotation页面整体旋转 1-90 2-180 3-270 其他-不旋转
*/
export function CreatCPCLPage(width, height, printNum, rotation = 0, offset = 0) {
var strCmd = '! ' + offset + ' 200 200 ' + height + ' ' + printNum + '\n';
strCmd += "PAGE-WIDTH " + width + '\n';
if (rotation == 1)
strCmd += "ZPROTATE90\n";
else if (rotation == 2)
strCmd += "ZPROTATE180\n";
else if (rotation == 3)
strCmd += "ZPROTATE270\n";
else
strCmd += "ZPROTATE0\n";
return strCmd;
}
/**
* 打印文字
* x: 文字方块左上角X座标单位dot
* y: 文字方块左上角Y座标单位dot
* fontName,fontSize: 字体取值 參考文檔
* rotation: 旋转 1-90 2-180 3-270 其他-不旋转
* content: 文字内容
*/
export function addCPCLText(x, y, fontName, fontSize, rotation, content) {
//console.log(fontName,fontSize,rotation, content);
var strCmd = '';
if (rotation == 1) {
strCmd += 'T90 ';
}
if (rotation == 2) {
strCmd += 'T180 ';
}
if (rotation == 3) {
strCmd += 'T270 ';
} else {
strCmd += 'T ';
}
strCmd += fontName + ' ' + fontSize + ' ' + x + ' ' + y + ' ' + content + '\n';
return strCmd;
};
/**
* 打印一维码
*
* x: 文字方块左上角X座标单位dot
* y: 文字方块左上角Y座标单位dot
* codeType: 条码类型取值为128UPCAUPCA2UPCA5UPCEUPCE2UPC5EAN13EAN13+2EAN13+5
* EAN8EAN8+2EAN8+53939CF39F39C93CODABARCODABAR16ITFI2OF5
* h: 条码高度单位dot
* rotation: 顺时针旋转角度取值如下
* - 0 不旋转
* - 1 顺时针旋转90度
*
* narrow: 窄条码比例因子(dot) 取值 參考文檔
* wide: 宽条码比例因子(dot) 取值 參考文檔
* content: 文字内容
*
*/
export function addCPCLBarCode(x, y, codeType, h, rotation, narrow, wide, content) {
var strCmd = '';
if (rotation == 0)
strCmd += 'B ';
else
strCmd += 'VB ';
strCmd += codeType + ' ' + narrow + ' ' + wide + ' ' + h + ' ' + x + ' ' + y + ' ' + content + '\n'
return strCmd;
};
/**
* 打印二维码
*
* x: 文字方块左上角X座标单位dot
* y: 文字方块左上角Y座标单位dot
* level: 错误纠正能力等级取值为L(7%)M(15%)Q(25%)H(30%)
* ver: 1-10 版本根据内容调整以获取合适容量
* scale: 1-10 放大倍数
* content: 文字内容
*
*/
export function addCPCLQRCode(x, y, level, ver, scale, content) {
var strCmd = 'B QR ' + x + ' ' + y + ' M ' + ver + ' U ' + scale + '\n' + level + 'A,' + content + '\n';
strCmd += 'ENDQR\n';
return strCmd;
};
/**
* 放大指令
* scaleX: 横向放大倍数 123等整数
* scaleY: 纵向放大倍数 123等整数
*/
export function addCPCLSETMAG(scaleX, scaleY) {
var strCmd = 'SETMAG ' + scaleX + ' ' + scaleY + '\n';
return strCmd;
};
/**
* 对齐指令 0-左对齐 1-右对齐 2-居中
*/
export function addCPCLLocation(set) {
var strCmd = '';
if (set == 1) {
strCmd += 'RIGHT\n';
} else if (set == 2) {
strCmd += 'CENTER\n';
} else {
strCmd += 'LEFT\n';
}
return strCmd;
};
/**
* 反白线 x0,y0,x1,y1,width
*/
export function addCPCLInverseLine(x0, y0, x1, y1, width) {
var strCmd = 'IL ' + x0 + ' ' + y0 + ' ' + x1 + ' ' + y1 + ' ' + width + '\n';
return strCmd;
};
/**
* 画线 x0,y0,x1,y1,width
*/
export function addCPCLLine(x0, y0, x1, y1, width) {
var strCmd = 'L ' + x0 + ' ' + y0 + ' ' + x1 + ' ' + y1 + ' ' + width + '\n';
return strCmd;
};
/**
* 画框 x0,y0,x1,y1,width
*/
export function addCPCLBox(x0, y0, x1, y1, width) {
var strCmd = 'BOX ' + x0 + ' ' + y0 + ' ' + x1 + ' ' + y1 + ' ' + width + '\n';
return strCmd;
};
/**
* 字体加粗
*/
export function addCPCLSETBOLD(bold) {
var strCmd = 'SETBOLD ' + bold + '\n';
return strCmd;
};
/**
* 字体下划线
*/
export function addCPCLUNDERLINE(c) {
var strCmd = 'UNDERLINE ';
if (c) strCmd += 'ON\n';
else if (c) strCmd += 'OFF\n';
return strCmd;
};
/**
* 水印打印灰度等级 0-255
*/
export function addCPCLBACKGROUND(level) {
var strCmd = 'BACKGROUND ';
if (level > 255 || level < 0) level = 255;
strCmd += level + '\n';
return strCmd;
};
/**
* 打印水印文字
* x: 文字方块左上角X座标单位dot
* y: 文字方块左上角Y座标单位dot
* fontName,fontSize: 字体取值 參考文檔
* rotation: 旋转 1-90 2-180 3-270 其他-不旋转
* content: 文字内容
*/
export function addCPCLBKVText(x, y, fontName, fontSize, rotation, content) {
//console.log(fontName,fontSize,rotation, content);
var strCmd = '';
if (rotation == 1) {
strCmd += 'BKT90 ';
}
if (rotation == 2) {
strCmd += 'BKT180 ';
}
if (rotation == 3) {
strCmd += 'BKT270 ';
} else {
strCmd += 'BKT ';
}
strCmd += fontName + ' ' + fontSize + ' ' + x + ' ' + y + ' ' + content + '\n';
return strCmd;
};
/**
* 标签缝隙定位指令
*/
export function addCPCLGAP() {
var strCmd = 'GAP-SENSE\nFORM\n';
return strCmd;
};
/**
* 标签右黑标检测指令
*/
export function addCPCLSENSE() {
var strCmd = 'BAR-SENSE\nFORM\n';
return strCmd;
};
/**
* 标签左黑标检测指令
*/
export function addCPCLSENSELEFT() {
var strCmd = 'BAR-SENSE LEFT\nFORM\n';
return strCmd;
};
/**
* 打印指令
*/
export function addCPCLPrint() {
var strCmd = 'PRINT\n';
return strCmd;
};
/**
* 图片打印指令
* x: 文字方块左上角X座标单位dot
* y: 文字方块左上角Y座标单位dot
* data{
threshold,//0/1提取的灰度级
width,//图像宽度
height,//图像高度
imageData , //图像数据
}
*/
export function addCPCLImageCmd(x, y, data) {
var strImgCmd = '';
const threshold = data.threshold || 180;
let myBitmapWidth = data.width,
myBitmapHeight = data.height;
let len = parseInt((myBitmapWidth + 7) / 8); //一行的数据长度
//console.log('len=',len);
//console.log('myBitmapWidth=',myBitmapWidth);
//console.log('myBitmapHeight=',myBitmapHeight);
let ndata = 0;
let i = 0;
let j = 0;
let sendImageData = new ArrayBuffer(len * myBitmapHeight);
sendImageData = new Uint8Array(sendImageData);
let pix = data.imageData;
console.log('pix=', pix);
for (i = 0; i < myBitmapHeight; i++) {
for (j = 0; j < len; j++) {
sendImageData[ndata + j] = 0;
}
for (j = 0; j < myBitmapWidth; j++) {
const grayPixle1 = grayPixle(pix.slice((i * myBitmapWidth + j) * 4, (i * myBitmapWidth + j) * 4 + 3));
if (grayPixle1 < threshold)
sendImageData[ndata + parseInt(j / 8)] |= (0x80 >> (j % 8));
}
ndata += len;
}
//console.log('sendImageData=',sendImageData);
//CPCL指令图片数据
strImgCmd += 'EG ' + len + ' ' + myBitmapHeight + ' ' + x + ' ' + y + ' ';
for (i = 0; i < sendImageData.length; i++) {
strImgCmd += Hex2Str(sendImageData[i]);
}
strImgCmd += '\n';
//console.log(strImgCmd);
return strImgCmd;
}
/**
* toast显示捕获的蓝牙异常
*/
export function catchToast(err) {
const errMsg = {
10000: '未初始化蓝牙模块',
10001: '蓝牙未打开',
10002: '没有找到指定设备',
10003: '连接失败',
10004: '没有找到指定服务',
10005: '没有找到指定特征值',
10006: '当前连接已断开',
10007: '当前特征值不支持此操作',
10008: '系统上报异常',
10009: '系统版本低于 4.3 不支持BLE'
};
let coode = err.errCode ? err.errCode.toString() : '';
let msg = errMsg[coode];
plus.nativeUI.toast(msg || coode, {
align: 'center',
verticalAlign: 'center'
});
}

23
src/components/kk-printer/utils/index.js

@ -0,0 +1,23 @@
var barcode = require('./barcode');
var qrcode = require('./qrcode');
function convert_length(length) {
return Math.round(wx.getSystemInfoSync().windowWidth * length / 750);
}
function barc(id, code, width, height) {
barcode.code128(wx.createCanvasContext(id), code, convert_length(width), convert_length(height))
}
function qrc(id, code, width, height) {
qrcode.api.draw(code, {
ctx: wx.createCanvasContext(id),
width: convert_length(width),
height: convert_length(height)
})
}
module.exports = {
barcode: barc,
qrcode: qrc
}

14633
src/components/kk-printer/utils/mqtt.js

File diff suppressed because it is too large

1
src/components/kk-printer/utils/mqtt.min.js

File diff suppressed because one or more lines are too long

285
src/components/kk-printer/utils/printUtil-GBK.js

File diff suppressed because one or more lines are too long

778
src/components/kk-printer/utils/qrcode.js

@ -0,0 +1,778 @@
var QR = (function () {
// alignment pattern
var adelta = [
0, 11, 15, 19, 23, 27, 31, // force 1 pat
16, 18, 20, 22, 24, 26, 28, 20, 22, 24, 24, 26, 28, 28, 22, 24, 24,
26, 26, 28, 28, 24, 24, 26, 26, 26, 28, 28, 24, 26, 26, 26, 28, 28
];
// version block
var vpat = [
0xc94, 0x5bc, 0xa99, 0x4d3, 0xbf6, 0x762, 0x847, 0x60d,
0x928, 0xb78, 0x45d, 0xa17, 0x532, 0x9a6, 0x683, 0x8c9,
0x7ec, 0xec4, 0x1e1, 0xfab, 0x08e, 0xc1a, 0x33f, 0xd75,
0x250, 0x9d5, 0x6f0, 0x8ba, 0x79f, 0xb0b, 0x42e, 0xa64,
0x541, 0xc69
];
// final format bits with mask: level << 3 | mask
var fmtword = [
0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976, //L
0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0, //M
0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed, //Q
0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b //H
];
// 4 per version: number of blocks 1,2; data width; ecc width
var eccblocks = [
1, 0, 19, 7, 1, 0, 16, 10, 1, 0, 13, 13, 1, 0, 9, 17,
1, 0, 34, 10, 1, 0, 28, 16, 1, 0, 22, 22, 1, 0, 16, 28,
1, 0, 55, 15, 1, 0, 44, 26, 2, 0, 17, 18, 2, 0, 13, 22,
1, 0, 80, 20, 2, 0, 32, 18, 2, 0, 24, 26, 4, 0, 9, 16,
1, 0, 108, 26, 2, 0, 43, 24, 2, 2, 15, 18, 2, 2, 11, 22,
2, 0, 68, 18, 4, 0, 27, 16, 4, 0, 19, 24, 4, 0, 15, 28,
2, 0, 78, 20, 4, 0, 31, 18, 2, 4, 14, 18, 4, 1, 13, 26,
2, 0, 97, 24, 2, 2, 38, 22, 4, 2, 18, 22, 4, 2, 14, 26,
2, 0, 116, 30, 3, 2, 36, 22, 4, 4, 16, 20, 4, 4, 12, 24,
2, 2, 68, 18, 4, 1, 43, 26, 6, 2, 19, 24, 6, 2, 15, 28,
4, 0, 81, 20, 1, 4, 50, 30, 4, 4, 22, 28, 3, 8, 12, 24,
2, 2, 92, 24, 6, 2, 36, 22, 4, 6, 20, 26, 7, 4, 14, 28,
4, 0, 107, 26, 8, 1, 37, 22, 8, 4, 20, 24, 12, 4, 11, 22,
3, 1, 115, 30, 4, 5, 40, 24, 11, 5, 16, 20, 11, 5, 12, 24,
5, 1, 87, 22, 5, 5, 41, 24, 5, 7, 24, 30, 11, 7, 12, 24,
5, 1, 98, 24, 7, 3, 45, 28, 15, 2, 19, 24, 3, 13, 15, 30,
1, 5, 107, 28, 10, 1, 46, 28, 1, 15, 22, 28, 2, 17, 14, 28,
5, 1, 120, 30, 9, 4, 43, 26, 17, 1, 22, 28, 2, 19, 14, 28,
3, 4, 113, 28, 3, 11, 44, 26, 17, 4, 21, 26, 9, 16, 13, 26,
3, 5, 107, 28, 3, 13, 41, 26, 15, 5, 24, 30, 15, 10, 15, 28,
4, 4, 116, 28, 17, 0, 42, 26, 17, 6, 22, 28, 19, 6, 16, 30,
2, 7, 111, 28, 17, 0, 46, 28, 7, 16, 24, 30, 34, 0, 13, 24,
4, 5, 121, 30, 4, 14, 47, 28, 11, 14, 24, 30, 16, 14, 15, 30,
6, 4, 117, 30, 6, 14, 45, 28, 11, 16, 24, 30, 30, 2, 16, 30,
8, 4, 106, 26, 8, 13, 47, 28, 7, 22, 24, 30, 22, 13, 15, 30,
10, 2, 114, 28, 19, 4, 46, 28, 28, 6, 22, 28, 33, 4, 16, 30,
8, 4, 122, 30, 22, 3, 45, 28, 8, 26, 23, 30, 12, 28, 15, 30,
3, 10, 117, 30, 3, 23, 45, 28, 4, 31, 24, 30, 11, 31, 15, 30,
7, 7, 116, 30, 21, 7, 45, 28, 1, 37, 23, 30, 19, 26, 15, 30,
5, 10, 115, 30, 19, 10, 47, 28, 15, 25, 24, 30, 23, 25, 15, 30,
13, 3, 115, 30, 2, 29, 46, 28, 42, 1, 24, 30, 23, 28, 15, 30,
17, 0, 115, 30, 10, 23, 46, 28, 10, 35, 24, 30, 19, 35, 15, 30,
17, 1, 115, 30, 14, 21, 46, 28, 29, 19, 24, 30, 11, 46, 15, 30,
13, 6, 115, 30, 14, 23, 46, 28, 44, 7, 24, 30, 59, 1, 16, 30,
12, 7, 121, 30, 12, 26, 47, 28, 39, 14, 24, 30, 22, 41, 15, 30,
6, 14, 121, 30, 6, 34, 47, 28, 46, 10, 24, 30, 2, 64, 15, 30,
17, 4, 122, 30, 29, 14, 46, 28, 49, 10, 24, 30, 24, 46, 15, 30,
4, 18, 122, 30, 13, 32, 46, 28, 48, 14, 24, 30, 42, 32, 15, 30,
20, 4, 117, 30, 40, 7, 47, 28, 43, 22, 24, 30, 10, 67, 15, 30,
19, 6, 118, 30, 18, 31, 47, 28, 34, 34, 24, 30, 20, 61, 15, 30
];
// Galois field log table
var glog = [
0xff, 0x00, 0x01, 0x19, 0x02, 0x32, 0x1a, 0xc6, 0x03, 0xdf, 0x33, 0xee, 0x1b, 0x68, 0xc7, 0x4b,
0x04, 0x64, 0xe0, 0x0e, 0x34, 0x8d, 0xef, 0x81, 0x1c, 0xc1, 0x69, 0xf8, 0xc8, 0x08, 0x4c, 0x71,
0x05, 0x8a, 0x65, 0x2f, 0xe1, 0x24, 0x0f, 0x21, 0x35, 0x93, 0x8e, 0xda, 0xf0, 0x12, 0x82, 0x45,
0x1d, 0xb5, 0xc2, 0x7d, 0x6a, 0x27, 0xf9, 0xb9, 0xc9, 0x9a, 0x09, 0x78, 0x4d, 0xe4, 0x72, 0xa6,
0x06, 0xbf, 0x8b, 0x62, 0x66, 0xdd, 0x30, 0xfd, 0xe2, 0x98, 0x25, 0xb3, 0x10, 0x91, 0x22, 0x88,
0x36, 0xd0, 0x94, 0xce, 0x8f, 0x96, 0xdb, 0xbd, 0xf1, 0xd2, 0x13, 0x5c, 0x83, 0x38, 0x46, 0x40,
0x1e, 0x42, 0xb6, 0xa3, 0xc3, 0x48, 0x7e, 0x6e, 0x6b, 0x3a, 0x28, 0x54, 0xfa, 0x85, 0xba, 0x3d,
0xca, 0x5e, 0x9b, 0x9f, 0x0a, 0x15, 0x79, 0x2b, 0x4e, 0xd4, 0xe5, 0xac, 0x73, 0xf3, 0xa7, 0x57,
0x07, 0x70, 0xc0, 0xf7, 0x8c, 0x80, 0x63, 0x0d, 0x67, 0x4a, 0xde, 0xed, 0x31, 0xc5, 0xfe, 0x18,
0xe3, 0xa5, 0x99, 0x77, 0x26, 0xb8, 0xb4, 0x7c, 0x11, 0x44, 0x92, 0xd9, 0x23, 0x20, 0x89, 0x2e,
0x37, 0x3f, 0xd1, 0x5b, 0x95, 0xbc, 0xcf, 0xcd, 0x90, 0x87, 0x97, 0xb2, 0xdc, 0xfc, 0xbe, 0x61,
0xf2, 0x56, 0xd3, 0xab, 0x14, 0x2a, 0x5d, 0x9e, 0x84, 0x3c, 0x39, 0x53, 0x47, 0x6d, 0x41, 0xa2,
0x1f, 0x2d, 0x43, 0xd8, 0xb7, 0x7b, 0xa4, 0x76, 0xc4, 0x17, 0x49, 0xec, 0x7f, 0x0c, 0x6f, 0xf6,
0x6c, 0xa1, 0x3b, 0x52, 0x29, 0x9d, 0x55, 0xaa, 0xfb, 0x60, 0x86, 0xb1, 0xbb, 0xcc, 0x3e, 0x5a,
0xcb, 0x59, 0x5f, 0xb0, 0x9c, 0xa9, 0xa0, 0x51, 0x0b, 0xf5, 0x16, 0xeb, 0x7a, 0x75, 0x2c, 0xd7,
0x4f, 0xae, 0xd5, 0xe9, 0xe6, 0xe7, 0xad, 0xe8, 0x74, 0xd6, 0xf4, 0xea, 0xa8, 0x50, 0x58, 0xaf
];
// Galios field exponent table
var gexp = [
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1d, 0x3a, 0x74, 0xe8, 0xcd, 0x87, 0x13, 0x26,
0x4c, 0x98, 0x2d, 0x5a, 0xb4, 0x75, 0xea, 0xc9, 0x8f, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0,
0x9d, 0x27, 0x4e, 0x9c, 0x25, 0x4a, 0x94, 0x35, 0x6a, 0xd4, 0xb5, 0x77, 0xee, 0xc1, 0x9f, 0x23,
0x46, 0x8c, 0x05, 0x0a, 0x14, 0x28, 0x50, 0xa0, 0x5d, 0xba, 0x69, 0xd2, 0xb9, 0x6f, 0xde, 0xa1,
0x5f, 0xbe, 0x61, 0xc2, 0x99, 0x2f, 0x5e, 0xbc, 0x65, 0xca, 0x89, 0x0f, 0x1e, 0x3c, 0x78, 0xf0,
0xfd, 0xe7, 0xd3, 0xbb, 0x6b, 0xd6, 0xb1, 0x7f, 0xfe, 0xe1, 0xdf, 0xa3, 0x5b, 0xb6, 0x71, 0xe2,
0xd9, 0xaf, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88, 0x0d, 0x1a, 0x34, 0x68, 0xd0, 0xbd, 0x67, 0xce,
0x81, 0x1f, 0x3e, 0x7c, 0xf8, 0xed, 0xc7, 0x93, 0x3b, 0x76, 0xec, 0xc5, 0x97, 0x33, 0x66, 0xcc,
0x85, 0x17, 0x2e, 0x5c, 0xb8, 0x6d, 0xda, 0xa9, 0x4f, 0x9e, 0x21, 0x42, 0x84, 0x15, 0x2a, 0x54,
0xa8, 0x4d, 0x9a, 0x29, 0x52, 0xa4, 0x55, 0xaa, 0x49, 0x92, 0x39, 0x72, 0xe4, 0xd5, 0xb7, 0x73,
0xe6, 0xd1, 0xbf, 0x63, 0xc6, 0x91, 0x3f, 0x7e, 0xfc, 0xe5, 0xd7, 0xb3, 0x7b, 0xf6, 0xf1, 0xff,
0xe3, 0xdb, 0xab, 0x4b, 0x96, 0x31, 0x62, 0xc4, 0x95, 0x37, 0x6e, 0xdc, 0xa5, 0x57, 0xae, 0x41,
0x82, 0x19, 0x32, 0x64, 0xc8, 0x8d, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0xe0, 0xdd, 0xa7, 0x53, 0xa6,
0x51, 0xa2, 0x59, 0xb2, 0x79, 0xf2, 0xf9, 0xef, 0xc3, 0x9b, 0x2b, 0x56, 0xac, 0x45, 0x8a, 0x09,
0x12, 0x24, 0x48, 0x90, 0x3d, 0x7a, 0xf4, 0xf5, 0xf7, 0xf3, 0xfb, 0xeb, 0xcb, 0x8b, 0x0b, 0x16,
0x2c, 0x58, 0xb0, 0x7d, 0xfa, 0xe9, 0xcf, 0x83, 0x1b, 0x36, 0x6c, 0xd8, 0xad, 0x47, 0x8e, 0x00
];
// Working buffers:
// data input and ecc append, image working buffer, fixed part of image, run lengths for badness
var strinbuf=[], eccbuf=[], qrframe=[], framask=[], rlens=[];
// Control values - width is based on version, last 4 are from table.
var version, width, neccblk1, neccblk2, datablkw, eccblkwid;
var ecclevel = 2;
// set bit to indicate cell in qrframe is immutable. symmetric around diagonal
function setmask(x, y)
{
var bt;
if (x > y) {
bt = x;
x = y;
y = bt;
}
// y*y = 1+3+5...
bt = y;
bt *= y;
bt += y;
bt >>= 1;
bt += x;
framask[bt] = 1;
}
// enter alignment pattern - black to qrframe, white to mask (later black frame merged to mask)
function putalign(x, y)
{
var j;
qrframe[x + width * y] = 1;
for (j = -2; j < 2; j++) {
qrframe[(x + j) + width * (y - 2)] = 1;
qrframe[(x - 2) + width * (y + j + 1)] = 1;
qrframe[(x + 2) + width * (y + j)] = 1;
qrframe[(x + j + 1) + width * (y + 2)] = 1;
}
for (j = 0; j < 2; j++) {
setmask(x - 1, y + j);
setmask(x + 1, y - j);
setmask(x - j, y - 1);
setmask(x + j, y + 1);
}
}
//========================================================================
// Reed Solomon error correction
// exponentiation mod N
function modnn(x)
{
while (x >= 255) {
x -= 255;
x = (x >> 8) + (x & 255);
}
return x;
}
var genpoly = [];
// Calculate and append ECC data to data block. Block is in strinbuf, indexes to buffers given.
function appendrs(data, dlen, ecbuf, eclen)
{
var i, j, fb;
for (i = 0; i < eclen; i++)
strinbuf[ecbuf + i] = 0;
for (i = 0; i < dlen; i++) {
fb = glog[strinbuf[data + i] ^ strinbuf[ecbuf]];
if (fb != 255) /* fb term is non-zero */
for (j = 1; j < eclen; j++)
strinbuf[ecbuf + j - 1] = strinbuf[ecbuf + j] ^ gexp[modnn(fb + genpoly[eclen - j])];
else
for( j = ecbuf ; j < ecbuf + eclen; j++ )
strinbuf[j] = strinbuf[j + 1];
strinbuf[ ecbuf + eclen - 1] = fb == 255 ? 0 : gexp[modnn(fb + genpoly[0])];
}
}
//========================================================================
// Frame data insert following the path rules
// check mask - since symmetrical use half.
function ismasked(x, y)
{
var bt;
if (x > y) {
bt = x;
x = y;
y = bt;
}
bt = y;
bt += y * y;
bt >>= 1;
bt += x;
return framask[bt];
}
//========================================================================
// Apply the selected mask out of the 8.
function applymask(m)
{
var x, y, r3x, r3y;
switch (m) {
case 0:
for (y = 0; y < width; y++)
for (x = 0; x < width; x++)
if (!((x + y) & 1) && !ismasked(x, y))
qrframe[x + y * width] ^= 1;
break;
case 1:
for (y = 0; y < width; y++)
for (x = 0; x < width; x++)
if (!(y & 1) && !ismasked(x, y))
qrframe[x + y * width] ^= 1;
break;
case 2:
for (y = 0; y < width; y++)
for (r3x = 0, x = 0; x < width; x++, r3x++) {
if (r3x == 3)
r3x = 0;
if (!r3x && !ismasked(x, y))
qrframe[x + y * width] ^= 1;
}
break;
case 3:
for (r3y = 0, y = 0; y < width; y++, r3y++) {
if (r3y == 3)
r3y = 0;
for (r3x = r3y, x = 0; x < width; x++, r3x++) {
if (r3x == 3)
r3x = 0;
if (!r3x && !ismasked(x, y))
qrframe[x + y * width] ^= 1;
}
}
break;
case 4:
for (y = 0; y < width; y++)
for (r3x = 0, r3y = ((y >> 1) & 1), x = 0; x < width; x++, r3x++) {
if (r3x == 3) {
r3x = 0;
r3y = !r3y;
}
if (!r3y && !ismasked(x, y))
qrframe[x + y * width] ^= 1;
}
break;
case 5:
for (r3y = 0, y = 0; y < width; y++, r3y++) {
if (r3y == 3)
r3y = 0;
for (r3x = 0, x = 0; x < width; x++, r3x++) {
if (r3x == 3)
r3x = 0;
if (!((x & y & 1) + !(!r3x | !r3y)) && !ismasked(x, y))
qrframe[x + y * width] ^= 1;
}
}
break;
case 6:
for (r3y = 0, y = 0; y < width; y++, r3y++) {
if (r3y == 3)
r3y = 0;
for (r3x = 0, x = 0; x < width; x++, r3x++) {
if (r3x == 3)
r3x = 0;
if (!(((x & y & 1) + (r3x && (r3x == r3y))) & 1) && !ismasked(x, y))
qrframe[x + y * width] ^= 1;
}
}
break;
case 7:
for (r3y = 0, y = 0; y < width; y++, r3y++) {
if (r3y == 3)
r3y = 0;
for (r3x = 0, x = 0; x < width; x++, r3x++) {
if (r3x == 3)
r3x = 0;
if (!(((r3x && (r3x == r3y)) + ((x + y) & 1)) & 1) && !ismasked(x, y))
qrframe[x + y * width] ^= 1;
}
}
break;
}
return;
}
// Badness coefficients.
var N1 = 3, N2 = 3, N3 = 40, N4 = 10;
// Using the table of the length of each run, calculate the amount of bad image
// - long runs or those that look like finders; called twice, once each for X and Y
function badruns(length)
{
var i;
var runsbad = 0;
for (i = 0; i <= length; i++)
if (rlens[i] >= 5)
runsbad += N1 + rlens[i] - 5;
// BwBBBwB as in finder
for (i = 3; i < length - 1; i += 2)
if (rlens[i - 2] == rlens[i + 2]
&& rlens[i + 2] == rlens[i - 1]
&& rlens[i - 1] == rlens[i + 1]
&& rlens[i - 1] * 3 == rlens[i]
// white around the black pattern? Not part of spec
&& (rlens[i - 3] == 0 // beginning
|| i + 3 > length // end
|| rlens[i - 3] * 3 >= rlens[i] * 4 || rlens[i + 3] * 3 >= rlens[i] * 4)
)
runsbad += N3;
return runsbad;
}
// Calculate how bad the masked image is - blocks, imbalance, runs, or finders.
function badcheck()
{
var x, y, h, b, b1;
var thisbad = 0;
var bw = 0;
// blocks of same color.
for (y = 0; y < width - 1; y++)
for (x = 0; x < width - 1; x++)
if ((qrframe[x + width * y] && qrframe[(x + 1) + width * y]
&& qrframe[x + width * (y + 1)] && qrframe[(x + 1) + width * (y + 1)]) // all black
|| !(qrframe[x + width * y] || qrframe[(x + 1) + width * y]
|| qrframe[x + width * (y + 1)] || qrframe[(x + 1) + width * (y + 1)])) // all white
thisbad += N2;
// X runs
for (y = 0; y < width; y++) {
rlens[0] = 0;
for (h = b = x = 0; x < width; x++) {
if ((b1 = qrframe[x + width * y]) == b)
rlens[h]++;
else
rlens[++h] = 1;
b = b1;
bw += b ? 1 : -1;
}
thisbad += badruns(h);
}
// black/white imbalance
if (bw < 0)
bw = -bw;
var big = bw;
var count = 0;
big += big << 2;
big <<= 1;
while (big > width * width)
big -= width * width, count++;
thisbad += count * N4;
// Y runs
for (x = 0; x < width; x++) {
rlens[0] = 0;
for (h = b = y = 0; y < width; y++) {
if ((b1 = qrframe[x + width * y]) == b)
rlens[h]++;
else
rlens[++h] = 1;
b = b1;
}
thisbad += badruns(h);
}
return thisbad;
}
function genframe(instring)
{
var x, y, k, t, v, i, j, m;
// find the smallest version that fits the string
t = instring.length;
version = 0;
do {
version++;
k = (ecclevel - 1) * 4 + (version - 1) * 16;
neccblk1 = eccblocks[k++];
neccblk2 = eccblocks[k++];
datablkw = eccblocks[k++];
eccblkwid = eccblocks[k];
k = datablkw * (neccblk1 + neccblk2) + neccblk2 - 3 + (version <= 9);
if (t <= k)
break;
} while (version < 40);
// FIXME - insure that it fits insted of being truncated
width = 17 + 4 * version;
// allocate, clear and setup data structures
v = datablkw + (datablkw + eccblkwid) * (neccblk1 + neccblk2) + neccblk2;
for( t = 0; t < v; t++ )
eccbuf[t] = 0;
strinbuf = instring.slice(0);
for( t = 0; t < width * width; t++ )
qrframe[t] = 0;
for( t = 0 ; t < (width * (width + 1) + 1) / 2; t++)
framask[t] = 0;
// insert finders - black to frame, white to mask
for (t = 0; t < 3; t++) {
k = 0;
y = 0;
if (t == 1)
k = (width - 7);
if (t == 2)
y = (width - 7);
qrframe[(y + 3) + width * (k + 3)] = 1;
for (x = 0; x < 6; x++) {
qrframe[(y + x) + width * k] = 1;
qrframe[y + width * (k + x + 1)] = 1;
qrframe[(y + 6) + width * (k + x)] = 1;
qrframe[(y + x + 1) + width * (k + 6)] = 1;
}
for (x = 1; x < 5; x++) {
setmask(y + x, k + 1);
setmask(y + 1, k + x + 1);
setmask(y + 5, k + x);
setmask(y + x + 1, k + 5);
}
for (x = 2; x < 4; x++) {
qrframe[(y + x) + width * (k + 2)] = 1;
qrframe[(y + 2) + width * (k + x + 1)] = 1;
qrframe[(y + 4) + width * (k + x)] = 1;
qrframe[(y + x + 1) + width * (k + 4)] = 1;
}
}
// alignment blocks
if (version > 1) {
t = adelta[version];
y = width - 7;
for (;;) {
x = width - 7;
while (x > t - 3) {
putalign(x, y);
if (x < t)
break;
x -= t;
}
if (y <= t + 9)
break;
y -= t;
putalign(6, y);
putalign(y, 6);
}
}
// single black
qrframe[8 + width * (width - 8)] = 1;
// timing gap - mask only
for (y = 0; y < 7; y++) {
setmask(7, y);
setmask(width - 8, y);
setmask(7, y + width - 7);
}
for (x = 0; x < 8; x++) {
setmask(x, 7);
setmask(x + width - 8, 7);
setmask(x, width - 8);
}
// reserve mask-format area
for (x = 0; x < 9; x++)
setmask(x, 8);
for (x = 0; x < 8; x++) {
setmask(x + width - 8, 8);
setmask(8, x);
}
for (y = 0; y < 7; y++)
setmask(8, y + width - 7);
// timing row/col
for (x = 0; x < width - 14; x++)
if (x & 1) {
setmask(8 + x, 6);
setmask(6, 8 + x);
}
else {
qrframe[(8 + x) + width * 6] = 1;
qrframe[6 + width * (8 + x)] = 1;
}
// version block
if (version > 6) {
t = vpat[version - 7];
k = 17;
for (x = 0; x < 6; x++)
for (y = 0; y < 3; y++, k--)
if (1 & (k > 11 ? version >> (k - 12) : t >> k)) {
qrframe[(5 - x) + width * (2 - y + width - 11)] = 1;
qrframe[(2 - y + width - 11) + width * (5 - x)] = 1;
}
else {
setmask(5 - x, 2 - y + width - 11);
setmask(2 - y + width - 11, 5 - x);
}
}
// sync mask bits - only set above for white spaces, so add in black bits
for (y = 0; y < width; y++)
for (x = 0; x <= y; x++)
if (qrframe[x + width * y])
setmask(x, y);
// convert string to bitstream
// 8 bit data to QR-coded 8 bit data (numeric or alphanum, or kanji not supported)
v = strinbuf.length;
// string to array
for( i = 0 ; i < v; i++ )
eccbuf[i] = strinbuf.charCodeAt(i);
strinbuf = eccbuf.slice(0);
// calculate max string length
x = datablkw * (neccblk1 + neccblk2) + neccblk2;
if (v >= x - 2) {
v = x - 2;
if (version > 9)
v--;
}
// shift and repack to insert length prefix
i = v;
if (version > 9) {
strinbuf[i + 2] = 0;
strinbuf[i + 3] = 0;
while (i--) {
t = strinbuf[i];
strinbuf[i + 3] |= 255 & (t << 4);
strinbuf[i + 2] = t >> 4;
}
strinbuf[2] |= 255 & (v << 4);
strinbuf[1] = v >> 4;
strinbuf[0] = 0x40 | (v >> 12);
}
else {
strinbuf[i + 1] = 0;
strinbuf[i + 2] = 0;
while (i--) {
t = strinbuf[i];
strinbuf[i + 2] |= 255 & (t << 4);
strinbuf[i + 1] = t >> 4;
}
strinbuf[1] |= 255 & (v << 4);
strinbuf[0] = 0x40 | (v >> 4);
}
// fill to end with pad pattern
i = v + 3 - (version < 10);
while (i < x) {
strinbuf[i++] = 0xec;
// buffer has room if (i == x) break;
strinbuf[i++] = 0x11;
}
// calculate and append ECC
// calculate generator polynomial
genpoly[0] = 1;
for (i = 0; i < eccblkwid; i++) {
genpoly[i + 1] = 1;
for (j = i; j > 0; j--)
genpoly[j] = genpoly[j]
? genpoly[j - 1] ^ gexp[modnn(glog[genpoly[j]] + i)] : genpoly[j - 1];
genpoly[0] = gexp[modnn(glog[genpoly[0]] + i)];
}
for (i = 0; i <= eccblkwid; i++)
genpoly[i] = glog[genpoly[i]]; // use logs for genpoly[] to save calc step
// append ecc to data buffer
k = x;
y = 0;
for (i = 0; i < neccblk1; i++) {
appendrs(y, datablkw, k, eccblkwid);
y += datablkw;
k += eccblkwid;
}
for (i = 0; i < neccblk2; i++) {
appendrs(y, datablkw + 1, k, eccblkwid);
y += datablkw + 1;
k += eccblkwid;
}
// interleave blocks
y = 0;
for (i = 0; i < datablkw; i++) {
for (j = 0; j < neccblk1; j++)
eccbuf[y++] = strinbuf[i + j * datablkw];
for (j = 0; j < neccblk2; j++)
eccbuf[y++] = strinbuf[(neccblk1 * datablkw) + i + (j * (datablkw + 1))];
}
for (j = 0; j < neccblk2; j++)
eccbuf[y++] = strinbuf[(neccblk1 * datablkw) + i + (j * (datablkw + 1))];
for (i = 0; i < eccblkwid; i++)
for (j = 0; j < neccblk1 + neccblk2; j++)
eccbuf[y++] = strinbuf[x + i + j * eccblkwid];
strinbuf = eccbuf;
// pack bits into frame avoiding masked area.
x = y = width - 1;
k = v = 1; // up, minus
/* inteleaved data and ecc codes */
m = (datablkw + eccblkwid) * (neccblk1 + neccblk2) + neccblk2;
for (i = 0; i < m; i++) {
t = strinbuf[i];
for (j = 0; j < 8; j++, t <<= 1) {
if (0x80 & t)
qrframe[x + width * y] = 1;
do { // find next fill position
if (v)
x--;
else {
x++;
if (k) {
if (y != 0)
y--;
else {
x -= 2;
k = !k;
if (x == 6) {
x--;
y = 9;
}
}
}
else {
if (y != width - 1)
y++;
else {
x -= 2;
k = !k;
if (x == 6) {
x--;
y -= 8;
}
}
}
}
v = !v;
} while (ismasked(x, y));
}
}
// save pre-mask copy of frame
strinbuf = qrframe.slice(0);
t = 0; // best
y = 30000; // demerit
// for instead of while since in original arduino code
// if an early mask was "good enough" it wouldn't try for a better one
// since they get more complex and take longer.
for (k = 0; k < 8; k++) {
applymask(k); // returns black-white imbalance
x = badcheck();
if (x < y) { // current mask better than previous best?
y = x;
t = k;
}
if (t == 7)
break; // don't increment i to a void redoing mask
qrframe = strinbuf.slice(0); // reset for next pass
}
if (t != k) // redo best mask - none good enough, last wasn't t
applymask(t);
// add in final mask/ecclevel bytes
y = fmtword[t + ((ecclevel - 1) << 3)];
// low byte
for (k = 0; k < 8; k++, y >>= 1)
if (y & 1) {
qrframe[(width - 1 - k) + width * 8] = 1;
if (k < 6)
qrframe[8 + width * k] = 1;
else
qrframe[8 + width * (k + 1)] = 1;
}
// high byte
for (k = 0; k < 7; k++, y >>= 1)
if (y & 1) {
qrframe[8 + width * (width - 7 + k)] = 1;
if (k)
qrframe[(6 - k) + width * 8] = 1;
else
qrframe[7 + width * 8] = 1;
}
// return image
return qrframe;
}
var _canvas = null,
_size = null;
var api = {
get ecclevel () {
return ecclevel;
},
set ecclevel (val) {
ecclevel = val;
},
get size () {
return _size;
},
set size (val) {
_size = val
},
get canvas () {
return _canvas;
},
set canvas (el) {
_canvas = el;
},
getFrame: function (string) {
return genframe(string);
},
draw: function (string, canvas, size, ecc) {
ecclevel = ecc || ecclevel;
canvas = canvas || _canvas;
if (!canvas) {
console.warn('No canvas provided to draw QR code in!')
return;
}
size = size || _size || Math.min(canvas.width, canvas.height);
var frame = genframe(string),
ctx = canvas.ctx,
px = Math.round(size / (width + 8));
var roundedSize = px * (width + 8),
offset = Math.floor((size - roundedSize) / 2);
size = roundedSize;
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.setFillStyle('#000000');
for (var i = 0; i < width; i++) {
for (var j = 0; j < width; j++) {
if (frame[j * width + i]) {
ctx.fillRect(px * (4 + i) + offset, px * (4 + j) + offset, px, px);
}
}
}
ctx.draw();
}
}
module.exports = {
api: api
}
})()

171
src/components/kk-printer/utils/util.js

@ -0,0 +1,171 @@
//const gbk = require('./gbk.js');
//console.log("sasas" + gbk);
const formatTime = date => {
const year = date.getFullYear()
const month = date.getMonth() + 1
const day = date.getDate()
const hour = date.getHours()
const minute = date.getMinutes()
const second = date.getSeconds()
return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':')
}
const formatNumber = n => {
n = n.toString()
return n[1] ? n : '0' + n
}
/*
const hexStringToBuff = str => { //str='中国:WXHSH'
const buffer = new ArrayBuffer((sumStrLength(str)) * 4)
const dataView = new DataView(buffer)
var data = str.toString();
var p = 0; //ArrayBuffer 偏移量
for (var i = 0; i < data.length; i++) {
if (isCN(data[i])) { //是中文
//调用GBK 转码
var t = gbk.encode(data[i]);
for (var j = 0; j < 2; j++) {
//var code = t[j * 2] + t[j * 2 + 1];
var code = t[j * 3 + 1] + t[j * 3 + 2];
var temp = parseInt(code, 16)
//var temp = strToHexCharCode(code);
dataView.setUint8(p++, temp)
}
} else {
var temp = data.charCodeAt(i);
dataView.setUint8(p++, temp)
}
}
return buffer;
}
*/
function toUnicode(s) {
var str = "";
for (var i = 0; i < s.length; i++) {
str += "\\u" + s.charCodeAt(i).toString(16) + "\t";
}
return str;
}
function strToHexCharCode(str) {
if (str === "")
return "";
var hexCharCode = [];
hexCharCode.push("0x");
for (var i = 0; i < str.length; i++) {
hexCharCode.push((str.charCodeAt(i)).toString(16));
}
return hexCharCode.join("");
}
function sumStrLength(str) {
var length = 0;
var data = str.toString();
for (var i = 0; i < data.length; i++) {
if (isCN(data[i])) { //是中文
length += 2;
} else {
length += 1;
}
}
return length;
}
function isCN(str) {
if (/^[\u3220-\uFA29]+$/.test(str)) {
return true;
} else {
return false;
}
}
//汉字转码
export function hexStringToArrayBuffer(str) {
const buffer = new ArrayBuffer((str.length / 2) + 1)
const dataView = new DataView(buffer)
for (var i = 0; i < str.length / 2; i++) {
var temp = parseInt(str[i * 2] + str[i * 2 + 1], 16)
dataView.setUint8(i, temp)
}
dataView.setUint8((str.length / 2), 0x0a)
return buffer;
}
//返回八位数组
function subString(str) {
var arr = [];
if (str.length > 8) { //大于8
for (var i = 0;
(i * 8) < str.length; i++) {
var temp = str.substring(i * 8, 8 * i + 8);
arr.push(temp)
}
return arr;
} else {
return str
}
}
//不带有汉字
function hexStringToArrayBufferstr(str) {
let val = ""
for (let i = 0; i < str.length; i++) {
if (val === '') {
val = str.charCodeAt(i).toString(16)
} else {
val += ',' + str.charCodeAt(i).toString(16)
}
}
val += "," + "0x0a";
console.log(val)
// 将16进制转化为ArrayBuffer
return new Uint8Array(val.match(/[\da-f]{2}/gi).map(function(h) {
return parseInt(h, 16)
})).buffer
}
export function ab2hex(buffer) {
let hexArr = Array.prototype.map.call(
new Uint8Array(buffer),
function (bit) {
return ('00' + bit.toString(16)).slice(-2)
})
return hexArr.join('');
}
// ArrayBuffer转为字符串,参数为ArrayBuffer对象
export function ab2str(buf) {
return String.fromCharCode.apply(null, new Uint8Array(buf));
}
// 字符串转为ArrayBuffer对象,参数为字符串
export function str2ab(str) {
var buf = new ArrayBuffer(str.length+1); // 补充/0
var bufView = new Uint8Array(buf);
for (var i = 0, strLen = str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}
export function send0X0A() {
const buffer = new ArrayBuffer(1)
const dataView = new DataView(buffer)
dataView.setUint8(0, 0x0a)
return buffer;
}
export function buf2hex(buffer) {
return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join('');
}
// module.exports = {
// hexStringToArrayBuffer: hexStringToArrayBuffer,
// send0X0A: send0X0A,
// ab2hex: ab2hex,
// str2ab: str2ab,
// ab2str: ab2str,
// buf2hex: buf2hex
// }

95
src/hybrid/html/point.html

@ -0,0 +1,95 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title></title>
<script src="../../api/img-to-base64.js"></script>
<script type="text/javascript">
document.addEventListener('plusready', function() {
//console.log("所有plus api都应该在此事件发生后调用,否则会出现plus is undefined。")
});
</script>
<style>
.box {
font-size: 14px;
display: flex;
margin-top: 60px;
}
.left {
border-top: 1px solid #b1b1b1;
border-left: 1px solid #b1b1b1;
flex: 1;
}
.left-item {
display: flex;
}
.bold-font {
font-weight: bold;
}
.font-30 {
font-size: 30px;
}
.font-20 {
font-size: 20px;
}
.bold-label {
font-weight: bold;
font-size: 15px;
}
.label {
border-bottom: 1px solid #b1b1b1;
border-right: 1px solid #b1b1b1;
width: 60px;
padding: 0px 5px;
height: 49px;
line-height: 49px;
}
.value {
border-bottom: 1px solid #b1b1b1;
border-right: 1px solid #b1b1b1;
padding: 0px 5px;
height: 49px;
flex: 1;
width: 0px;
display: flex;
align-items: center;
word-break: break-all;
justify-content: center;
}
.right {
width: 300px;
}
.image {
width: calc(100% - 1px);
height: 149px;
border-bottom: 1px solid #b1b1b1;
border-top: 1px solid #b1b1b1;
border-right: 1px solid #b1b1b1;
}
.image img {
width: 147px;
height: 147px;
border: 1px solid #b1b1b1;
/* width: calc(100% - 4px);
height: calc(100% - 4px); */
margin: 1px;
}
</style>
</head>
<body>
mainBody
</body>
</html>

67
src/hybrid/html/pointPutawayJob.html

@ -0,0 +1,67 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title></title>
<script src="../../api/img-to-base64.js"></script>
<script type="text/javascript">
document.addEventListener('plusready', function() {
//console.log("所有plus api都应该在此事件发生后调用,否则会出现plus is undefined。")
});
</script>
<style>
.box {
font-size: 13px;
/* padding: 10px; */
/* border: 1px solid #dedede; */
}
.left {
flex: 1;
border-bottom: 1px solid #b1b1b1;
}
.left-item {
display: flex;
border-top: 1px solid #b1b1b1;
border-left: 1px solid #b1b1b1;
border-right: 1px solid #b1b1b1;
}
.left-item div{
padding: 10px 10px;
font-size: 16px;
}
.left-item .label{
width: 100px;
padding: 10px 10px;
border-right: 1px solid #b1b1b1;
}
.relative {
margin-bottom: 10px;
position: relative;
}
.q {
position: absolute;
font-size: 15rem;
color: rgba(0, 0, 0, 0.1);
width: calc(100% - 100px);
right: 0px;
top: 0px;
text-align: center;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
</style>
</head>
<body>
mainBody
</body>
</html>

67
src/hybrid/html/purchaseReceiptJob.html

@ -0,0 +1,67 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title></title>
<script src="../../api/img-to-base64.js"></script>
<script type="text/javascript">
document.addEventListener('plusready', function() {
//console.log("所有plus api都应该在此事件发生后调用,否则会出现plus is undefined。")
});
</script>
<style>
.box {
font-size: 13px;
/* padding: 10px; */
/* border: 1px solid #dedede; */
}
.left {
flex: 1;
border-bottom: 1px solid #b1b1b1;
}
.left-item {
display: flex;
border-top: 1px solid #b1b1b1;
border-left: 1px solid #b1b1b1;
border-right: 1px solid #b1b1b1;
}
.left-item div{
padding: 10px 10px;
font-size: 16px;
}
.left-item .label{
width: 100px;
padding: 10px 10px;
border-right: 1px solid #b1b1b1;
}
.relative {
margin-bottom: 10px;
position: relative;
}
.q {
position: absolute;
font-size: 15rem;
color: rgba(0, 0, 0, 0.1);
width: calc(100% - 100px);
right: 0px;
top: 0px;
text-align: center;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
</style>
</head>
<body>
mainBody
</body>
</html>

24
src/libs/versionUpdate.js

@ -0,0 +1,24 @@
import axios from 'axios'
const isNewVersion = () => {
let updae_url=""
// let updae_url = getApp().globalData.text;
let url = updae_url+ `/static/version.json?t=${new Date().getTime()}`
axios.get(url).then(res => {
if (res.status === 200) {
let vueVersion = res.data.version;
let localVueVersion = localStorage.getItem('vueVersion');
if (localVueVersion && localVueVersion != vueVersion) {
localStorage.setItem('vueVersion', vueVersion);
window.location.reload();
return;
} else {
localStorage.setItem('vueVersion', vueVersion);
}
}
})
}
export default {
isNewVersion
}

64
src/mycomponents/balance/handleBalanceBatch.vue

@ -0,0 +1,64 @@
<template>
<view :class="detail.scaned?'scan_view':''" style="background-color: #ffffff;">
<view class="space_between center">
<view style="word-break: break-all;width: 60%;">
<pack title='外包装' v-if="detail.parentPackingNumber"
:packingCode="detail.parentPackingNumber"></pack>
<pack v-if="isShowPack" :packingCode="detail.packingNumber"></pack>
<batch v-if="isShowBatch" :batch="detail.batch"></batch>
<location v-if="isShowLocation" :locationCode="detail.fromLocationCode"></location>
</view>
<view style="word-break: break-all;">
<recommend-qty v-if="detail.record==null || detail.record==undefined" :dataContent="detail"
:isShowStatus='isShowStatus' :isShowStdPack="true" :isShowCount='false'></recommend-qty>
<compare-qty v-else :dataContent="detail" :recommendQty="detail.qty" :handleQty="detail.record.qty"
:isShowStatus='isShowStatus' :isShowStdPack="true">
</compare-qty>
</view>
</view>
</view>
</template>
<script setup lang="ts">
import pack from '@/mycomponents/balance/pack.vue'
import location from '@/mycomponents/balance/location.vue'
import batch from '@/mycomponents/balance/batch.vue'
import recommendQty from '@/mycomponents/qty/recommendQty.vue'
import compareQty from '@/mycomponents/qty/compareQty.vue'
const props = defineProps({
detail: {
type: Object,
default: {}
},
isShowPack: {
type: Boolean,
default: true
},
isShowBatch: {
type: Boolean,
default: true
},
isShowLocation: {
type: Boolean,
default: true
},
isShowStatus: {
type: Boolean,
default: true
},
})
</script>
<style>
.recommend {
position: absolute;
left: 25px;
top: 70px;
width: 10px;
height: 30px;
opacity: 1;
}
</style>

27
src/mycomponents/balance/level.vue

@ -0,0 +1,27 @@
<template>
<view class="card_view">
<text class="card_level">{{ title }}</text>
<text class="card_big_content" style="font-size: 40rpx">{{ getPriorityName1() }}</text>
</view>
</template>
<script setup lang="ts">
import { getPriorityName } from '@/common/directory.js'
const props = defineProps({
priority: {
type: Number,
default: 2
},
title: {
type: String,
default: '优先级'
}
})
const getPriorityName1 = () => {
return getPriorityName(props.priority)
}
</script>
<style></style>

21
src/mycomponents/balance/light.vue

@ -0,0 +1,21 @@
<template>
<view class="card_view">
<text class="card_light">{{ title }}</text>
<text class="card_content">{{ lightCode }}</text>
</view>
</template>
<script setup lang="ts">
const props = defineProps({
lightCode: {
type: String,
default: ''
},
title: {
type: String,
default: '灯码'
}
})
</script>
<style></style>

55
src/mycomponents/balance/recommendBalanceBatch.vue

@ -0,0 +1,55 @@
<template>
<view>
<view class="uni-flex uni-row space-between center ">
<view class="uni-flex uni-row " style="width: 60%;" >
<view style=" width: 25rpx;color: #32C1E8;">
推荐
</view>
<view style="word-break: break-all">
<pack v-if="isShowPack&&detail.packingNumber" :packingCode="detail.packingNumber"></pack>
<batch v-if="isShowBatch&&detail.batch" :batch="detail.batch"></batch>
<location v-if="isShowLocation" :locationCode="detail.fromLocationCode"></location>
</view>
</view>
</view>
</view>
</template>
<script setup lang="ts">
import pack from '@/mycomponents/balance/pack.vue'
import location from '@/mycomponents/balance/location.vue'
import batch from '@/mycomponents/balance/batch.vue'
import recommendQty from '@/mycomponents/qty/recommendQty.vue'
import compareQty from '@/mycomponents/qty/compareQty.vue'
const props = defineProps({
detail: {
type: Object,
default: {}
},
isShowPack: {
type: Boolean,
default: true
},
isShowBatch: {
type: Boolean,
default: true
},
isShowLocation: {
type: Boolean,
default: true
},
})
</script>
<style>
.recommend {
position: absolute;
left: 25px;
top: 70px;
width: 10px;
height: 30px;
opacity: 1;
}
</style>

40
src/mycomponents/button/comCheckAll.vue

@ -0,0 +1,40 @@
<template>
<view class="flex uni-row">
<view class="" >
<u-checkbox size="50" v-model="checkAll" @change="checkAllItems" >
</u-checkbox>
</view>
<view>
<text style="margin-left: 10rpx; font-size: 35rpx;font-weight: bold;">全选({{checkCount}}/{{allCount}})</text>
</view>
</view>
</template>
<script lang="ts" setup>
import {nextTick, ref} from 'vue'
const props = defineProps({
checkCount: {
type: Number,
default: 0
},
allCount: {
type: Number,
default: 0
},
})
const emit = defineEmits(['checkAllItems'])
const checkAll = ref(false)
const checkAllItems = ()=>{
checkAll.value = !checkAll.value
emit('checkAllItems', checkAll.value)
}
const changeCheckAllState = ()=>{
nextTick(()=>{
checkAll.value = props.checkCount == props.allCount
})
}
</script>
<style>
</style>

173
src/mycomponents/detail/comDetailCardBatch.vue

@ -0,0 +1,173 @@
<template>
<view style="background-color: #fff;">
<u-collapse ref="collapse1Ref" @change="">
<u-collapse-item :open="true">
<template #title>
<item-compare-qty :dataContent="dataContent"
:handleQty="dataContent.handleQty" :isShowStdPack="false">
</item-compare-qty>
</template>
<view class="" v-for="(item,index) in dataContent.subList" :key="index">
<u-swipe-action ref="swipeAction"
:options="item.scaned?scanOptions:detailOptions"
@click="(...event)=>swipeClick(event,item,'parent')"
v-if='index==0'>
<recommend :detail="item" :isShowFromLocation="isShowFromLocation"
:isShowStatus="isShowStatus" :isShowToLocation="isShowToLocation">
</recommend>
</u-swipe-action>
</view>
</u-collapse-item>
</u-collapse>
<balance-qty-edit ref="qtyEdit" :settingParam="settingParam" :queryBalance="queryBalance"
@confirm="confirm"></balance-qty-edit>
<win-scan-location ref="scanLocationCode" title="目标库位" @getLocation='getLocation'
:locationAreaTypeList="locationAreaTypeList"></win-scan-location>
<comMessage ref="message"></comMessage>
</view>
</template>
<script setup>
import config from '@/static/config.js'
import ItemCompareQty from '@/mycomponents/item/itemCompareQty.vue'
import Recommend from '@/mycomponents/recommend/recommend.vue'
import BalanceQtyEdit from '@/mycomponents/qty/balanceQtyEdit.vue'
import WinScanLocation from "@/mycomponents/scan/winScanLocation.vue"
import {
getDetailOption,
getPurchaseReceiptOption,
} from '@/common/array.js';
import { ref, watch, onMounted, nextTick } from 'vue';
const props = defineProps({
dataContent: {
type: Object,
default: null
},
settingParam: {
type: Object,
default: null
},
isShowPack: {
type: Boolean,
default: true
},
isShowBatch: {
type: Boolean,
default: true
},
isShowLocation: {
type: Boolean,
default: true
},
isShowFromLocation: {
type: Boolean,
default: true
},
isShowToLocation: {
type: Boolean,
default: false
},
locationAreaTypeList: {
type: Array,
default: null
},
queryBalance: {
type: Boolean,
default: true
},
isShowStatus: {
type: Boolean,
default: true
},
});
const emit = defineEmits(['openDetail', 'remove', 'updateData']);
const showItem = ref({});
const locatonItem = ref({});
const editItem = ref({});
const detailOptions = ref([]);
const scanOptions = ref([]);
const options = ref([]);
const collapse1Ref = ref(null);
const qtyEditRef = ref(null);
const messageRef = ref(null);
const scanLocationCodeRef = ref(null);
watch(() => props.dataContent, (newDataContent, oldDataContent) => {
if (newDataContent?.subList?.length > 0) {
nextTick(() => {
setTimeout(() => {
if (collapse1Ref.value) {
collapse1Ref.value.resize();
}
}, 500);
});
}
}, { immediate: true, deep: true });
onMounted(() => {
if (detailOptions.value.length === 0) {
detailOptions.value = getDetailOption();
}
if (scanOptions.value.length === 0) {
scanOptions.value = getPurchaseReceiptOption(props.settingParam.allowModifyQty, false);
}
});
const swipeClick = (e, item) => {
if (e.content.text === "详情") {
detail(item);
} else if (e.content.text === "编辑") {
edit(item);
} else if (e.content.text === "库位") {
showLocation(item);
} else if (e.content.text === "移除") {
remove(item);
}
};
const edit = (item) => {
editItem.value = item;
qtyEditRef.value.openEditPopup(item.balance, item.handleQty);
};
const detail = (item) => {
emit('openDetail', item);
};
const remove = (item) => {
messageRef.value.showQuestionMessage("确定移除扫描信息?", (res) => {
if (res) {
item.scaned = false;
item.balance = {};
item.handleQty = null;
emit('remove', item);
}
});
};
const confirm = (qty) => {
editItem.value.handleQty = qty;
emit('updateData');
};
const showLocation = (item) => {
locatonItem.value = item;
scanLocationCodeRef.value.openScanPopup();
};
const getLocation = (location, code) => {
locatonItem.value.toLocationCode = code;
emit('updateData');
};
</script>
<style>
</style>

138
src/mycomponents/detail/comJobDetailCard.vue

@ -0,0 +1,138 @@
<template>
<view class="" style="background-color: #fff">
<u-collapse ref="collapse">
<u-collapse-item :open="true">
<template v-slot:title>
<itemCompareQty :dataContent="dataContent" :handleQty="dataContent.handleQty" :isShowPackUnit="true" style="flex: 1"></itemCompareQty>
</template>
<package-list :dataContent="dataContent.subList"
:isEdit="settingParam.allowModifyQty == 'TRUE'"
:settingParam="settingParam"
@collapseChange="collapseChange" @updateData="updateData"
:isShowStatus="isShowStatus" :isShowPackListStatus="isShowPackListStatus">
</package-list>
</u-collapse-item>
</u-collapse>
<recommend-qty-edit ref="receiptEdit" :dataContent="editItem" :settingParam="settingParam" @confirm="confirm"> </recommend-qty-edit>
<com-message ref="comMessageRef" />
</view>
</template>
<script setup lang="ts">
import { ref, getCurrentInstance, onMounted, nextTick, watch } from 'vue'
import itemCompareQty from '@/mycomponents/item/itemCompareQty.vue'
import recommend from '@/mycomponents/recommend/recommend.vue'
import recommendQtyEdit from '@/mycomponents/qty/recommendQtyEdit.vue'
import packageList from '@/mycomponents/package/packageList.vue'
import { getDetailOption, getPurchaseReceiptOption } from '@/common/array.js'
const props = defineProps({
dataContent: {
type: Object,
default: null
},
settingParam: {
type: Object,
default: null
},
locationAreaTypeList: {
type: Object,
default: null
},
isShowStatus: {
type: Boolean,
default: true
},
isShowPackListStatus: {
type: Boolean,
default: true
}
})
const showItem = ref({})
const editItem = ref({
record: {}
})
const locatonItem = ref({})
const detailOptions = ref([])
const scanOptions = ref([])
const comMessageRef = ref()
const collapse = ref()
const receiptEdit = ref()
//
watch(
() => props.dataContent,
(val) => {
if (val.subList.length > 0) {
if (collapse.value != undefined && collapse.value != null) {
nextTick((res) => {
collapse.value.init()
})
}
}
},
{
deep: true
}
)
onMounted(() => {
if (detailOptions.value.length == 0) {
detailOptions.value = getDetailOption()
}
if (scanOptions.value.length == 0) {
scanOptions.value = getPurchaseReceiptOption(props.settingParam.allowModifyQty, props.settingParam.allowModifyLocation)
}
})
const collapseChange = () => {
setTimeout(() => {
resizeCollapse()
}, 500)
}
const resizeCollapse = (object) => {
nextTick(() => {
collapse.value.init()
})
}
const refreshCollapse = () => {
nextTick((r) => {
collapse.value.forEach((r) => {
r.childrens.forEach((i) => {
i.init()
})
r.init()
})
})
}
const swipeClick = (e, item) => {
if (e.content.text == '编辑') {
edit(item)
} else if (e.content.text == '移除') {
remove(item)
}
}
const edit = (item) => {
editItem = item
receiptEdit.value.openTaskEditPopup(item.qty, item.handleQty, item.labelQty)
}
const remove = (item) => {
comMessageRef.value.showQuestionMessage('确定移除扫描信息?', (res) => {
if (res) {
item.scaned = false
item.handleQty = null
emit('remove', item)
}
})
}
const confirm = (qty) => {
editItem.value.handleQty = qty
emit('updateData')
}
const updateData = () => {
emit('updateData')
}
//
const emit = defineEmits(['remove', 'updateData'])
</script>
<style></style>

151
src/mycomponents/detail/comJobDetailCardBatch.vue

@ -0,0 +1,151 @@
<!-- 采购上架任务详情按批次显示详情的组件 -->
<template>
<view class="" style="background-color: #fff;">
<u-collapse ref="collapseRef">
<u-collapse-item :open="true">
<template #title>
<itemCompareQty :dataContent="dataContent" :handleQty="dataContent.handleQty"
:isShowPackUnit="true"></itemCompareQty>
</template>
<package-list :dataContent="dataContent.subList"
:isEdit="settingParam.allowModifyQty=='TRUE'"
:settingParam="settingParam"
@collapseChange="collapseChange"
@updateData="updateData"
:isShowStatus="isShowStatus"
:isShowPackListStatus="isShowPackListStatus"
></package-list>
</u-collapse-item>
</u-collapse>
<recommend-qty-edit ref="receiptEditRef" :dataContent="editItem" :settingParam="settingParam" @confirm="confirm">
</recommend-qty-edit>
<comMessage ref="messageRef"></comMessage>
</view>
</template>
<script setup>
import itemCompareQty from '@/mycomponents/item/itemCompareQty.vue'
import recommend from '@/mycomponents/recommend/recommend.vue'
import recommendQtyEdit from '@/mycomponents/qty/recommendQtyEdit.vue'
import jobDetailPopup from '@/mycomponents/detail/jobDetailPopup.vue'
import receiptDetailInfoPopup from '@/pages/purchaseReceipt/coms/receiptDetailInfoPopup.vue'
import pack from '@/mycomponents/balance/pack.vue'
import detailList from '@/mycomponents/detail/detailList.vue'
import packageList from '@/mycomponents/package/packageList.vue'
import {
getDetailOption,
getPurchaseReceiptOption
} from '@/common/array.js';
import { ref, onMounted, nextTick } from 'vue';
const props = defineProps({
dataContent: {
type: Object,
default: null
},
settingParam: {
type: Object,
default: null
},
locationAreaTypeList: {
type: Object,
default: null
},
isShowStatus: {
type: Boolean,
default: true
},
isShowPackListStatus: {
type: Boolean,
default: true
},
});
const showItem = ref({});
const editItem = ref({ record: {} });
const locatonItem = ref({});
const detailOptions = ref([]);
const scanOptions = ref([]);
const options = ref([]);
const collapseRef = ref(null);
const receiptEditRef = ref(null);
const messageRef = ref(null);
onMounted(() => {
if (detailOptions.value.length === 0) {
detailOptions.value = getDetailOption();
}
if (scanOptions.value.length === 0) {
scanOptions.value = getPurchaseReceiptOption(props.settingParam.allowModifyQty, props.settingParam.allowModifyLocation);
}
});
const collapseChange = () => {
setTimeout(() => {
resizeCollapse();
}, 500);
};
const resizeCollapse = () => {
nextTick(() => {
if (collapseRef.value) {
collapseRef.value.init();
}
});
};
const refreshCollapse = () => {
nextTick(() => {
if (collapseRef.value) {
collapseRef.value.forEach(r => {
r.childrens.forEach(i => {
i.init();
});
r.init();
});
}
});
};
const swipeClick = (e, item) => {
if (e.content.text === "编辑") {
edit(item);
} else if (e.content.text === "移除") {
remove(item);
}
};
const edit = (item) => {
editItem.value = item;
receiptEditRef.value.openTaskEditPopup(item.qty, item.handleQty, item.labelQty);
};
const remove = (item) => {
messageRef.value.showQuestionMessage("确定移除扫描信息?", (res) => {
if (res) {
item.scaned = false;
item.handleQty = null;
emit('remove', item);
}
});
};
const confirm = (qty) => {
editItem.value.handleQty = qty;
emit('updateData');
};
const updateData = () => {
emit('updateData');
};
const emit = defineEmits(['remove', 'updateData']);
</script>
<style>
</style>

178
src/mycomponents/detail/comLableDetailCard.vue

@ -0,0 +1,178 @@
<template>
<view class="" style="background-color: #fff;">
<u-collapse ref="collapse1" @change="">
<u-collapse-item :open="true">
<template v-slot:title>
<item-compare-qty :dataContent="dataContent" :handleQty="dataContent.handleQty"
:isShowStdPack="false">
</item-compare-qty>
</template>
<view class="" v-for="(item,index) in dataContent.subList" :key="index">
<u-swipe-action ref="swipeAction"
@click="(...event)=>swipeClick(event,item)"
style='padding:0px 0px 5px 0px;align-items: center;'
:options="item.scaned?scanOptions:detailOptions">
<recommend :detail="item" :isShowFromLocation="isShowFromLocation"
:isShowStatus="isShowStatus" :isShowToLocation="isShowToLocation">
</recommend>
</u-swipe-action>
</view>
</u-collapse-item>
</u-collapse>
<recommend-qty-edit ref="receiptEdit" :dataContent="editItem" :settingParam="settingParam" @confirm="confirm">
</recommend-qty-edit>
<win-scan-location ref="scanLocationCode" title="目标库位" @getLocation='getLocation'
:locationAreaTypeList="locationAreaTypeList"></win-scan-location>
<comMessage ref="message"></comMessage>
</view>
</template>
<script setup>
import itemCompareQty from '@/mycomponents/item/itemCompareQty.vue'
import recommend from '@/mycomponents/recommend/recommend.vue'
import recommendQtyEdit from '@/mycomponents/qty/recommendQtyEdit.vue'
import winScanLocation from "@/mycomponents/scan/winScanLocation.vue"
import {
getDetailOption,
getPurchaseReceiptOption
} from '@/common/array.js';
import { ref, watch, onMounted, nextTick } from 'vue';
const props = defineProps({
dataContent: {
type: Object,
default: null
},
settingParam: {
type: Object,
default: null
},
isShowPack: {
type: Boolean,
default: true
},
isShowBatch: {
type: Boolean,
default: true
},
isShowLocation: {
type: Boolean,
default: true
},
isShowFromLocation: {
type: Boolean,
default: true
},
isShowToLocation: {
type: Boolean,
default: false
},
locationAreaTypeList: {
type: Array,
default: null
},
queryBalance: {
type: Boolean,
default: true
},
isShowStatus: {
type: Boolean,
default: true
}
});
const collapse1 = ref(null);
const receiptEdit = ref(null);
const message = ref(null);
const scanLocationCode = ref(null);
const option = ref([]);
const showItem = ref({});
const locatonItem = ref({});
const editItem = ref({});
const detailOptions = ref([]);
const scanOptions = ref([]);
watch(() => props.dataContent, (newDataContent, oldDataContent) => {
if (newDataContent?.subList.length > 0) {
nextTick(() => {
setTimeout(() => {
if (collapse1.value) {
collapse1.value.resize();
}
}, 500);
});
}
}, { immediate: true, deep: true });
onMounted(() => {
if (detailOptions.value.length === 0) {
detailOptions.value = getDetailOption();
}
if (scanOptions.value.length === 0) {
scanOptions.value = getPurchaseReceiptOption(props.settingParam.allowModifyQty, false);
}
// showLocation();
});
const swipeClick = (e, item) => {
switch (e.content.text) {
case "详情":
detail(item);
break;
case "编辑":
edit(item);
break;
case "库位":
showLocation(item);
break;
case "移除":
remove(item);
break;
}
};
const edit = (item) => {
editItem.value = item;
receiptEdit.value.openTaskEditPopup(item.qty, item.handleQty, item.labelQty);
};
const detail = (item) => {
emit('openDetail', item);
// showItem.value = item;
// jobDetailPopup.value.openPopup(item);
};
const remove = (item) => {
message.value.showQuestionMessage("确定移除扫描信息?", (res) => {
if (res) {
item.scaned = false;
item.balance = {};
item.handleQty = null;
emit('remove', item);
}
});
};
const confirm = (qty) => {
editItem.value.handleQty = qty;
emit('updateData');
};
const showLocation = (item) => {
locatonItem.value = item;
scanLocationCode.value.openScanPopup();
};
const getLocation = (location, code) => {
locatonItem.value.toLocationCode = code;
emit('updateData');
};
const emit = defineEmits(['openDetail', 'remove', 'updateData']);
</script>
<style>
</style>

185
src/mycomponents/detail/comRecommendDetailCard.vue

@ -0,0 +1,185 @@
<template>
<view class="" style="background-color: #fff;">
<u-collapse ref="collapse1" >
<u-collapse-item :open="true">
<template v-slot:title>
<item-compare-qty :dataContent="dataContent" :handleQty="dataContent.handleQty"
:isShowStdPack="false">
</item-compare-qty>
</template>
<view class="" v-for="(item,index) in dataContent.subList" :key="index">
<u-swipe-action ref="swipeAction"
:options="item.scaned?scanOptions:detailOptions"
style='padding:0px 0px 5px 0px;align-items: center;'
@click="(...event)=>swipeClick(event,item)">
<view v-if="item.isRecommend" class="uni-flex" style="flex-direction: row; align-items: center;background-color: antiquewhite;">
<view class="" style="font-size: 32rpx; color: black; font-weight: bold; text-align: center;">
</view>
<recommend :detail="item" :isShowStatus="isShowStatus" :isShowFromLocation="isShowFromLocation" :isShowToLocation="isShowToLocation" style="flex:1" :isShowBatch='item.batch ? true:false' :isShowPack='isShowPack'>
</view>
<view v-else class="uni-flex" style="flex-direction: row; align-items: center;background-color: antiquewhite; margin-top: 5rpx;">
<view class="" style="font-size: 32rpx; color: red; font-weight: bold; text-align: center;">
</view>
<recommend :detail="item" :isShowStatus="isShowStatus" :isShowFromLocation="isShowFromLocation" :isShowToLocation="isShowToLocation" style="flex:1" :isShowBatch='item.batch? true:false' :isShowPack='isShowPack'></recommend>
</view>
</u-swipe-action>
</view>
</u-collapse-item>
</u-collapse>
<<recommend-qty-edit ref="recommendQtyEditRef" :dataContent="editItem" :handleQty="editItem.qty" @confirm="confirm" :settingParam='settingParam'
:isShowStatus="isShowStatus"></recommend-qty-edit>
<win-scan-location ref="scanLocationCode" title="目标库位" @getLocation='getLocation'
:locationAreaTypeList="locationAreaTypeList"></win-scan-location>
<comMessage ref="message"></comMessage>
</view>
</template>
<script setup>
import {ref, watch, onMounted, nextTick} from 'vue'
import itemCompareQty from '@/mycomponents/item/itemCompareQty.vue'
import recommend from '@/mycomponents/recommend/recommend.vue'
import recommendQtyEdit from '@/mycomponents/qty/recommendQtyEdit.vue'
import winScanLocation from '@/mycomponents/scan/winScanLocation.vue'
import {
getDetailOption,
getPurchaseReceiptOption
} from '@/common/array.js'
const props = defineProps({
dataContent: {
type: Object,
default: null
},
settingParam: {
type: Object,
default: null
},
isShowPack: {
type: Boolean,
default: true
},
isShowBatch: {
type: Boolean,
default: true
},
isShowLocation: {
type: Boolean,
default: true
},
locationAreaTypeList: {
type: Array,
default: null
},
queryBalance: {
type: Boolean,
default: true
},
isShowStatus: {
type: Boolean,
default: true
}
})
const emit = defineEmits(['openDetail', 'remove', 'updateData'])
const collapse1 = ref(null)
const qtyEdit = ref(null)
const message = ref(null)
const scanLocationCode = ref(null)
const option = ref([])
const showItem = ref({})
const locatonItem = ref({})
const editItem = ref({})
const detailOptions = ref([])
const scanOptions = ref([])
const recommendQtyEditRef = ref()
watch(() => props.dataContent, (newDataContent, oldDataContent) => {
if (newDataContent?.subList.length > 0) {
nextTick(() => {
setTimeout(() => {
if (collapse1.value) {
collapse1.value.init()
}
}, 500)
})
}
}, { immediate: true, deep: true })
onMounted(() => {
if (scanOptions.value.length === 0) {
scanOptions.value = getPurchaseReceiptOption(props.settingParam.allowModifyQty, false)
}
// showLocation();
if(import.meta.env.VITE_MANAGE_MODEL=='BY_PACKAGING'){
if (detailOptions.value.length == 0) {
detailOptions.value = getDetailOption()
}
}else {
scanOptions.value.splice(0,1)
}
})
const swipeClick = (e, item) => {
switch (e.content.text) {
case '详情':
detail(item)
break
case '编辑':
edit(item)
break
case '库位':
showLocation(item)
break
case '移除':
remove(item)
break
}
}
const edit = (item) => {
editItem.value = item
qtyEdit.value.openEditPopup(item.balance, item.handleQty)
recommendQtyEditRef.value.openTaskEditPopup(item.qty,item.handleQty,item.labelQty)
}
const detail = (item) => {
emit('openDetail', item)
// showItem.value = item;
// jobDetailPopup.value.openPopup(item);
}
const remove = (item) => {
message.value.showQuestionMessage('确定移除扫描信息?', (res) => {
if (res) {
item.scaned = false
item.balance = {}
item.handleQty = null
emit('remove', item)
}
})
}
const confirm = (qty) => {
editItem.value.handleQty = qty
emit('updateData')
}
const showLocation = (item) => {
locatonItem.value = item
scanLocationCode.value.openScanPopup()
}
const getLocation = (location, code) => {
locatonItem.value.toLocationCode = code
emit('updateData')
}
</script>
<style>
</style>

229
src/mycomponents/detail/comRecommendDetailCardBatch.vue

@ -0,0 +1,229 @@
<template>
<view class="" style="background-color: #fff;">
<item-compare-qty :dataContent="dataContent" :handleQty="dataContent.handleQty"
:isShowStdPack="false">
</item-compare-qty>
<view class="" v-for="(item,index) in dataContent.subList" :key="index">
<uni-swipe-action ref="swipeAction"
style='padding:0px 0px 5px 0px;align-items: center;'
:options="(item.scaned&&isEdit)?editAndRemoveOptions : item.scaned? removeOptions:options"
@click="(...event)=>swipeClick(event,item)">
<view v-if="item.isRecommend" class="uni-flex" style="flex-direction: row;">
<view class=""
style="font-size: 32rpx; color: black; font-weight: bold; text-align: center;background-color: antiquewhite;display: flex;align-items: center;justify-content: center;padding: 0px 10rpx;">
<br/>
</view>
<view class="" style="flex:1;">
<batch v-if="item.batch" :batch="item.batch"></batch>
<location v-if="item.fromLocationCode" title="来源库位"
:locationCode="item.fromLocationCode"></location>
</view>
<text style="font-size: 30rpx;color: #2979ff; " @click="copy(item)" v-if="isDevlement()">复制</text>
</view>
<view v-else class="uni-flex" style="flex-direction: row; margin-top: 5rpx;">
<view class=""
style="font-size: 32rpx; color: black; font-weight: bold; text-align: center;background-color: antiquewhite;display: flex;align-items: center;justify-content: center;padding: 0px 10rpx;">
<br/>
</view>
<view class="scan_view" style="flex:1;">
<location v-if="item.fromLocationCode" title="来源库位"
:locationCode="item.fromLocationCode"></location>
</view>
<!-- <recommend :detail="item" :isShowStatus="isShowStatus" :isShowToLocation="false">
</recommend> -->
</view>
</uni-swipe-action>
</view>
<balance-qty-edit ref="qtyEdit" :settingParam="settingParam" :queryBalance="queryBalance"
@confirm="confirm"></balance-qty-edit>
<win-scan-location ref="scanLocationCode" title="目标库位" @getLocation='getLocation'
:locationAreaTypeList="locationAreaTypeList"></win-scan-location>
<comMessage ref="message"></comMessage>
</view>
</template>
<script setup>
import itemCompareQty from '@/mycomponents/item/itemCompareQty.vue'
import recommend from '@/mycomponents/recommend/recommend.vue'
import balanceQtyEdit from '@/mycomponents/qty/balanceQtyEdit.vue'
import winScanLocation from "@/mycomponents/scan/winScanLocation.vue"
import location from '@/mycomponents/balance/location.vue'
import toLocation from '@/mycomponents/balance/toLocation.vue'
import batch from '@/mycomponents/balance/batch.vue'
import config from '@/static/config.js'
import {
getRemoveOption,
getEditRemoveOption
} from '@/common/array.js';
import { ref, watch, onMounted, nextTick } from 'vue';
const props = defineProps({
dataContent: {
type: Object,
default: null
},
settingParam: {
type: Object,
default: null
},
isShowPack: {
type: Boolean,
default: true
},
isShowBatch: {
type: Boolean,
default: true
},
isShowLocation: {
type: Boolean,
default: true
},
locationAreaTypeList: {
type: Array,
default: null
},
queryBalance: {
type: Boolean,
default: true
},
isShowStatus: {
type: Boolean,
default: true
},
isEdit: {
type: Boolean,
default: true
}
});
const emit = defineEmits(['openDetail', 'remove', 'updateData']);
const collapse1 = ref(null);
const qtyEdit = ref(null);
const message = ref(null);
const scanLocationCode = ref(null);
const option = ref([]);
const showItem = ref({});
const locatonItem = ref({});
const editItem = ref({});
const detailOptions = ref([]);
const scanOptions = ref([]);
const options = ref([]);
const removeOptions = ref([]);
const editAndRemoveOptions = ref([]);
watch(() => props.dataContent, (newDataContent, oldDataContent) => {
if (newDataContent?.subList.length > 0) {
nextTick(() => {
setTimeout(() => {
if (collapse1.value) {
collapse1.value.resize();
}
}, 500);
});
}
}, { immediate: true, deep: true });
onMounted(() => {
removeOptions.value = getRemoveOption();
editAndRemoveOptions.value = getEditRemoveOption();
// showLocation();
});
const swipeClick = (e, item) => {
switch (e.content.text) {
case "详情":
detail(item);
break;
case "编辑":
edit(item);
break;
case "库位":
showLocation(item);
break;
case "移除":
remove(item);
break;
}
};
const edit = (item) => {
editItem.value = item;
qtyEdit.value.openEditPopup(item.balance, item.handleQty);
};
const detail = (item) => {
emit('openDetail', item);
// showItem.value = item;
// jobDetailPopup.value.openPopup(item);
};
const remove = (item) => {
message.value.showQuestionMessage("确定移除扫描信息?", (res) => {
if (res) {
item.scaned = false;
item.balance = {};
item.handleQty = null;
emit('remove', item);
}
});
};
const confirm = (qty) => {
editItem.value.handleQty = qty;
emit('updateData');
};
const showLocation = (item) => {
locatonItem.value = item;
scanLocationCode.value.openScanPopup();
};
const getLocation = (location, code) => {
locatonItem.value.toLocationCode = code;
emit('updateData');
};
const isDevlement = () => {
return config.isDevelopment;
};
const copy = (detail) => {
console.log(detail);
const content = `HPQ;V1.0;I${detail.itemCode};P${detail.packingNumber};B${detail.batch};Q${detail.qty}`;
// #ifdef H5
navigator.clipboard.writeText(content).then(
() => {
uni.showToast({
title: '复制采购标签成功',
icon: 'none'
});
},
() => {
uni.showToast({
title: '复制失败',
icon: 'none'
});
}
);
// #endif
// #ifndef H5
uni.setClipboardData({
data: content,
success: () => {
uni.showToast({
title: '复制采购标签成功'
});
}
});
// #endif
};
</script>
<style>
</style>

146
src/mycomponents/detail/detailList.vue

@ -0,0 +1,146 @@
<template>
<view class="" v-for="(item,index) in dataContent" :key="item.id">
<uni-collapse ref="collapse" @change="">
<uni-collapse-item :open="true">
<template v-slot:title>
<recommend :detail="item" :isShowLocation="false" :isShowFromLocation="false"></recommend>
</template>
<view v-for="(pack,index) in item.packList" :key="pack.id" style="margin-left: 20px;">
<recommend :detail="pack" :isShowLocation="false" :isShowFromLocation="false"
:isShowToLocation="false" :isShowBatch="false"></recommend>
</view>
</uni-collapse-item>
</uni-collapse>
</view>
</template>
<script>
import container from '@/mycomponents/container/container.vue'
import pack from '@/mycomponents/balance/pack.vue'
import location from '@/mycomponents/balance/location.vue'
import toLocation from '@/mycomponents/balance/toLocation.vue'
import batch from '@/mycomponents/balance/batch.vue'
import recommendQty from '@/mycomponents/qty/recommendQty.vue'
import compareQty from '@/mycomponents/qty/compareQty.vue'
import config from '@/static/config.js'
import recommend from '@/mycomponents/recommend/recommend.vue'
export default {
components: {
container,
pack,
location,
toLocation,
batch,
recommendQty,
compareQty,
recommend
},
data() {
return {
}
},
props: {
dataContent: {
type: Object,
default: {}
},
isShowContainer: {
type: Boolean,
default: true
},
isShowPack: {
type: Boolean,
default: true
},
isShowBatch: {
type: Boolean,
default: true
},
isShowFromLocation: {
type: Boolean,
default: true
},
isShowToLocation: {
type: Boolean,
default: false
},
isShowStatus: {
type: Boolean,
default: true
},
locationTitle: {
type: String,
default: '库位'
},
},
watch: {
},
methods: {
copy() {
// HPQ;V1.0;ICE115F11161AG;PP20230427000026;B20230427002;Q100
var content = "HPQ;V1.0;I" + this.detail.itemCode + ";P" + this.detail.packingNumber + ";B" + this.detail
.batch + ";Q" + this.detail.qty
// #ifdef H5
this.$copyText(content).then(
res => {
uni.showToast({
title: '复制采购标签成功',
icon: 'none'
})
}
)
// #endif
// #ifndef H5
uni.setClipboardData({
data: content,
success: () => {
uni.showToast({
title: '复制采购标签成功'
})
}
})
// #endif
},
copyPro() {
// HPQ;V1.0;ICE115F11161AG;PP20230427000026;B20230427002;Q100
var content = "HMQ;V1.0;I" + this.detail.itemCode + ";P" + this.detail.packingNumber + ";B" + this.detail
.batch + ";Q" + this.detail.qty
// #ifdef H5
this.$copyText(content).then(
res => {
uni.showToast({
title: '复制制品标签成功',
icon: 'none'
})
}
)
// #endif
// #ifndef H5
uni.setClipboardData({
data: content,
success: () => {
uni.showToast({
title: '复制制品标签成功'
})
}
})
// #endif
},
isDevlement() {
return config.isDevelopment;
}
}
}
</script>
<style>
</style>

127
src/mycomponents/item/itemFilter.vue

@ -0,0 +1,127 @@
<template>
<u-popup v-model="show" @click="show = false" mode="right" width="450rpx">
<view class="maskbox" @tap="maskClick"></view>
<view class="uni-flex uni-column center" style="background-color: white; width: 200px; height: auto; padding: 20rpx; z-index: 100; position: relative; top: 100rpx; right: 20rpx; left: 30rpx; box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.2); border-radius: 10rpx">
<view class="uni-flex" style="justify-content: center; font-size: 35rpx; font-weight: bold"> 筛选条件 </view>
<view class="uni-flex" style="flex-direction: column; width: 100%; margin-top: 10rpx">
<view class="" style="font-size: 35rpx; margin-bottom: 10rpx"> 库位 </view>
<u-input v-model="locationCode" placeholder="请输入库位"></u-input>
</view>
<view class="" style="font-size: 35rpx; margin-top: 10rpx; margin-bottom: 10rpx">
库存状态 :
<uni-data-checkbox mode="tag" multiple v-model="state" :localdata="stateList"></uni-data-checkbox>
</view>
<view class="" style="margin-top: 30rpx; margin-left: 30rpx; margin-right: 30rpx">
<button type="primary" size="default" @click="confirm">确认</button>
</view>
</view>
</u-popup>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { getTodayDate } from '@/common/basic.js'
import { getInventoryStatusList } from '@/common/directory.js'
const props = defineProps({
checkedToday: {
type: Boolean,
default: false
},
checkedWaitTask: {
type: Boolean,
default: false
},
otherTitle: {
type: String,
default: ''
},
isShowAsn: {
type: Boolean,
default: false
},
isShowJob: {
type: Boolean,
default: true
},
isShowFromLocationCode: {
type: Boolean,
default: false
},
isShowProductionLineCode: {
type: Boolean,
default: false
},
productionline: {
type: Array,
default: []
}
})
const stateList = ref([])
const state = ref([])
const show = ref(false)
const scanNumber = ref()
const locationCode = ref()
const scanAsnNumber = ref(null)
//
const maskClick = () => {
//
closeScanPopup()
}
const openFilter = () => {
stateList.value = getInventoryStatusList()
stateList.value.forEach((res) => {
res.text = res.label
})
show.value = true
}
const closeScanPopup = () => {
show.value = false
}
const switchChangeToday = (isOn) => {
let creationTime = ''
if (isOn) {
creationTime = getTodayDate()
}
emit('switchChangeToday', isOn, creationTime)
closeScanPopup()
}
const scanNumberClick = () => {
scanNumber.value.openScanPopup()
}
const scanOtherClick = () => {
scanAsnNumber.value.openScanPopup()
}
const confirm = () => {
emit('onConfirmClick', locationCode.value, state.value)
closeScanPopup()
}
const clearData = ()=>{
locationCode.value = ''
state.value = []
}
const emit = defineEmits(['onConfirmClick', 'switchChangeToday'])
defineExpose({
openFilter,
closeScanPopup,
clearData
})
</script>
<style lang="scss">
.maskbox {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: 0;
}
</style>

31
src/mycomponents/job/jobAccept.vue

@ -0,0 +1,31 @@
<template>
<!-- style="margin-top: 10rpx;margin-bottom: 10rpx;" class="uni-flex uni-row space-between u-col-center" -->
<view class="task_item" style="margin-left: 15rpx; margin-right: 15rpx;">
<view class="uni-flex u-col" style="flex-direction: column;">
<view class="uni-flex uni-row u-col-center">
<text style="font-size: 32rpx;" >承接人: {{dataContent.acceptUserName}}</text>
</view>
<view class="uni-flex uni-row u-col-center">
<text style="font-size: 32rpx;" class="center">承接时间 : {{formatDate(dataContent.acceptTime)}}</text>
</view>
</view>
</view>
</template>
<script setup>
import {
dateFormat
} from '@/common/basic.js';
const props = defineProps({
dataContent: {
type: Object,
default: {}
}
})
const formatDate = function(val) {
return dateFormat(val)
}
</script>
<style lang="scss">
</style>

24
src/mycomponents/job/jobComMainCardAsn.vue

@ -0,0 +1,24 @@
<template>
<view>
<view class="task_card">
<jobTopAsn :dataContent="dataContent"></jobTopAsn>
<slot></slot>
<view class="split_line"></view>
<job-bottom :dataContent="dataContent"></job-bottom>
</view>
</view>
</template>
<script setup lang="ts">
import jobTopAsn from '@/mycomponents/job/jobTopAsn.vue'
import jobBottom from '@/mycomponents/job/jobBottom.vue'
const props = defineProps({
dataContent: {
type: Object,
default: {}
}
})
</script>
<style lang="scss"></style>

66
src/mycomponents/job/jobComMainDetailCard.vue

@ -0,0 +1,66 @@
<template>
<view class="">
<view class="task_text" style="border-top: 1px solid #dedede; padding-top: 20rpx">
<itemCompareQty :dataContent="dataContent"
:isShowPackCount="isShowPackCount"
:handleQty="dataContent.handleQty" :isShowPackUnit="false"
></itemCompareQty>
<view>
<pack v-if="isShowPack && dataContent.packingNumber != null" :packingCode="dataContent.packingNumber"> </pack>
<batch v-if="isShowBatch && dataContent.batch != null" :batch="dataContent.batch"></batch>
<view class="u-flex justify-between u-p-b-16">
<location v-if="isShowFromLocation && dataContent.fromLocationCode" title="来源库位" :locationCode="dataContent.fromLocationCode"> </location>
<level title="优先级" :priority="dataContent.priority" v-if="dataContent.priority !== '' && dataContent.priority !== undefined && dataContent.priority !== null"> </level>
<to-location v-if="isShowToLocation" title="目标库位" :locationCode="dataContent.toLocationCode || dataContent.locationCode"> </to-location>
</view>
</view>
</view>
</view>
</template>
<script setup lang="ts">
import pack from '@/mycomponents/balance/pack.vue'
import location from '@/mycomponents/balance/location.vue'
import toLocation from '@/mycomponents/balance/toLocation.vue'
import batch from '@/mycomponents/balance/batch.vue'
import jobComMainCard from '@/mycomponents/job/jobComMainCard.vue'
import itemCompareQty from '@/mycomponents/item/itemCompareQty.vue'
import level from '@/mycomponents/balance/level.vue'
const props = defineProps({
dataContent: {
type: Object,
default: {}
},
isShowContainer: {
type: Boolean,
default: true
},
isShowPack: {
type: Boolean,
default: true
},
isShowBatch: {
type: Boolean,
default: true
},
isShowFromLocation: {
type: Boolean,
default: true
},
isShowToLocation: {
type: Boolean,
default: true
},
isShowDeliverType: {
type: Boolean,
default: false
},
isShowPackCount: {
type: Boolean,
default: false
}
})
</script>
<style lang="scss"></style>

28
src/mycomponents/job/jobTopAsn.vue

@ -0,0 +1,28 @@
<template>
<view class="task_item">
<view class="uni-flex space-between u-col-center align-center">
<job-number v-if="dataContent.asnNumber == null || dataContent.asnNumber == ''" :number="dataContent.requestNumber"></job-number>
<job-number v-else :number="dataContent.asnNumber"></job-number>
<job-status :jobStatus="dataContent.status"></job-status>
</view>
</view>
</template>
<script setup lang="ts">
import jobNumber from '@/mycomponents/job/jobNumber.vue'
import jobStatus from '@/mycomponents/job/jobStatus.vue'
const props = defineProps({
dataContent: {
type: Object,
default: {}
}
})
const openDetail = (item) => {
emit('openDetail', props.dataContent)
}
//
const emit = defineEmits(['openDetail'])
</script>
<style lang="scss"></style>

68
src/mycomponents/jobList/jobList.vue

@ -0,0 +1,68 @@
<template>
<view class="wyf">
<u-popup v-model="show" mode="center" width="600rpx">
<view class="container">
<u-card :title="item.title" v-for="(item, index) in list" :key="item.id" margin="20rpx" :head-style="{ padding: '20rpx' }" :foot-style="{ padding: '0rpx' }">
<template v-slot:body>
<view class=""> 物料代码{{ item.itemCode }} </view>
<view class=""> 物料名称{{ item.itemName }} </view>
</template>
<template v-slot:foot>
<!-- <button class="go" >Go</button> -->
<u-button type="primary" @click="selectItem(item, index)" style="width: 200rpx; height: 60rpx">Go</u-button>
</template>
</u-card>
</view>
</u-popup>
</view>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const list = ref([])
const show = ref(false)
const isScanedASN = ref(false)
const openList = (listParmas, isScanedASNParmas = false) => {
list.value = listParmas
isScanedASN.value = isScanedASNParmas
show.value = true
}
const selectItem = (item, index) => {
show.value = false
emit('selectItem', item, isScanedASN.value)
}
//
const emit = defineEmits(['selectItem'])
defineExpose({
openList
})
</script>
<style lang="scss" scoped>
.container {
display: flex;
justify-content: center;
align-items: center;
.list {
width: 80%;
max-height: 50vh;
overflow-y: auto;
border-radius: 10px !important;
.slot-image {
width: 40rpx;
}
.go {
color: rgb(60, 156, 255);
}
}
}
.list ::v-deep .uni-list--border {
border: 1rpx solid #e5e5e5;
}
</style>

91
src/mycomponents/location/locationCompare.vue

@ -0,0 +1,91 @@
<template>
<view class="uni-flex u-col-center" style="padding-left: 10rpx;padding-right: 10rpx;
font-size:32rpx;">
<view class="uni-flex uni-row u-col-center" @click="showLocation">
<view class="flex uni-row" v-if="isShowEdit" >
<view >
<text style="font-size: 35rpx;">{{title}}</text>
<text style="font-size: 45rpx;color:#3FBAFF; font-weight: bold;">&nbsp {{recommendLocationCode}}</text>
<text v-if="locationCode" style="font-size: 45rpx;color:#3FBAFF;font-weight: bold;">&nbsp/&nbsp{{locationCode}}</text>
<!-- <text style="font-size: 35rpx;color:#3FBAFF;" v-if="locationCode==''&&isShowEdit==true">&nbsp 请扫描</text> -->
</view>
<image style="width:45rpx;height: 45rpx; vertical-align:center" class="center" src="/static/icons/icons_edit.svg"></image>
</view>
<view class="" v-else>
<view >
<text style="font-size: 35rpx;">{{title}}</text>
<text style="font-size: 45rpx;color:#3FBAFF;font-weight: bold;">&nbsp {{recommendLocationCode}}</text>
<!-- <text style="font-size: 35rpx;color:#3FBAFF;" v-if="locationCode==''&&isShowEdit==true">&nbsp 请扫描</text> -->
</view>
</view>
<view class="uni-flex uni-row center" style="vertical-align:center ;" v-if="isDevlement()">
<text style="font-size: 30rpx;color: #2979ff; " @click="copy">复制</text>
</view>
</view>
<win-scan-location ref="scanLocationCode" :title="title" @getLocation='getLocation'
:locationAreaTypeList="locationAreaTypeList"></win-scan-location>
</view>
</template>
<script setup lang="ts">
import { ref, getCurrentInstance } from 'vue'
import winScanLocation from '@/mycomponents/scan/winScanLocation.vue'
import config from '@/static/config.js'
const defaultlocationCode = ref('')
const props = defineProps({
title: {
type: String,
default: '需求库位'
},
recommendLocationCode: {
type: String,
default: ''
},
locationCode: {
type: String,
default: ''
},
isShowEdit: {
type: Boolean,
default: true
},
locationAreaTypeList: {
type: Array,
default: null
}
})
const scanLocationCode = ref()
const showLocation = () => {
if (props.isShowEdit) {
scanLocationCode.value.openScanPopup()
}
}
//
const getLocation = (location, code) => {
emit('getLocation', location, code)
}
const copy = () => {
// HPQ;V1.0;ICE115F11161AG;PP20230427000026;B20230427002;Q100
const content = props.recommendLocationCode
uni.setClipboardData({
data: content,
success: () => {
uni.showToast({
title: '复制库位成功'
})
}
})
}
const isDevlement = () => {
return config.isDevelopment
}
//
const emit = defineEmits(['getLocation'])
</script>
<style></style>

33
src/mycomponents/package/PackageAndItemCard.vue

@ -0,0 +1,33 @@
<template>
<view :class="dataContent.scaned ? 'scan_view' : ''" style="background-color: #fff">
<view class="uni-flex uni-row space-between" style="align-items: center">
<view style="word-break: break-all">
<item :dataContent="dataContent" style="margin-left: 4px; padding: 0px 5px 5px"></item>
<pack v-if="dataContent.packingNumber" :packingCode="dataContent.packingNumber"></pack>
<batch v-if="dataContent.batch != null" :batch="dataContent.batch"></batch>
<location v-if="dataContent.locationCode != null" :locationCode="dataContent.locationCode"></location>
</view>
<view class="uni-flex uni-row" style="word-break: break-all">
<recommend-qty :dataContent="dataContent" :isShowStdPack="false" :isShowStatus="true" :isShowPackCount="false"></recommend-qty>
</view>
</view>
</view>
</template>
<script setup lang="ts">
import { ref, getCurrentInstance, onMounted, nextTick, watch } from 'vue'
import item from '@/mycomponents/item/item.vue'
import pack from '@/mycomponents/balance/pack.vue'
import batch from '@/mycomponents/balance/batch.vue'
import location from '@/mycomponents/balance/location.vue'
import recommendQty from '@/mycomponents/qty/recommendQty.vue'
const props = defineProps({
dataContent: {
type: Object,
default: null
}
})
</script>
<style></style>

128
src/mycomponents/package/packageCard.vue

@ -0,0 +1,128 @@
<template>
<view :class="dataContent.scaned ? 'scan_view' : ''" style="background-color: #fff">
<!-- border-bottom: 1upx solid #EEEEEE; -->
<view class="uni-flex uni-row space-between" style="align-items: center">
<!-- uni-inline-item 暂时拿掉-->
<view style="word-break: break-all">
<!-- <container v-if="isShowContainer&&dataContent.containerNumber!=null" :container="dataContent.containerNumber">
</container> -->
<pack :packingCode="dataContent.packingNumber" :isShowPackingNumberProps="isShowPackingNumberProps"></pack>
<batch v-if="isShowBatch && dataContent.batch != null" :batch="dataContent.batch"></batch>
<location v-if="isShowFromLocation" title="来源库位" :locationCode="dataContent.fromLocationCode"> </location>
<!-- <to-location></to-location> -->
<to-location v-if="isShowToLocation" title="目标库位" :locationCode="dataContent.toLocationCode"> </to-location>
</view>
<view class="uni-flex uni-row" style="word-break: break-all; align-items: center">
<!-- ||dataContent.handleQty==0 可能会有扫描到0的情况-->
<recommend-qty v-if="dataContent.handleQty == null || dataContent.handleQty == undefined" :dataContent="dataContent" :isShowStdPack="false" :isShowStatus="isShowStatus"></recommend-qty>
<compare-qty v-else :dataContent="dataContent" :recommendQty="Number(dataContent.qty)" :handleQty="Number(dataContent.handleQty)" :isShowStdPack="false" :isShowStatus="isShowStatus" :isShowRecommendQty="isShowRecommendQty"></compare-qty>
<!-- <view v-if="isDevlement()">
<image style="width: 26rpx; height: 26rpx; margin-top: 44rpx" src="/static/icons/icon_copy.svg" alt="" @click="copy" />
</view> -->
</view>
</view>
</view>
</template>
<script setup lang="ts">
import { watch } from 'vue'
import container from '@/mycomponents/container/container.vue'
import pack from '@/mycomponents/balance/pack.vue'
import location from '@/mycomponents/balance/location.vue'
import toLocation from '@/mycomponents/balance/toLocation.vue'
import batch from '@/mycomponents/balance/batch.vue'
import recommendQty from '@/mycomponents/qty/recommendQty.vue'
import compareQty from '@/mycomponents/qty/compareQty.vue'
import config from '@/static/config.js'
const props = defineProps({
dataContent: {
type: Object,
default: null
},
isShowContainer: {
type: Boolean,
default: true
},
isShowPack: {
type: Boolean,
default: true
},
isShowBatch: {
type: Boolean,
default: true
},
isShowFromLocation: {
type: Boolean,
default: true
},
isShowToLocation: {
type: Boolean,
default: false
},
isShowStatus: {
type: Boolean,
default: true
},
locationTitle: {
type: String,
default: '库位'
},
//
isShowPackingNumberProps: {
type: Boolean,
default: false
},
isShowRecommendQty: {
type: Boolean,
default: true
}
})
watch(
() => props.dataContent,
(newVal, oldVal) => {
if (newVal.scaned) {
newVal.copyContent = `HPQ;V1.0;I${newVal.itemCode};P${newVal.packingNumber};B${newVal.batch};Q${newVal.qty}`
} else {
newVal.copyContent = ''
}
},
{
immediate: true,
deep: true
}
)
const copy = () => {
// HPQ;V1.0;ICE115F11161AG;PP20230427000026;B20230427002;Q100
const content = `HPQ;V1.0;I${props.dataContent.itemCode};P${props.dataContent.packingNumber};B${props.dataContent.batch};Q${props.dataContent.qty}`
uni.setClipboardData({
data: content,
success: () => {
uni.showToast({
title: '复制采购标签成功'
})
}
})
}
const copyPro = () => {
// HPQ;V1.0;ICE115F11161AG;PP20230427000026;B20230427002;Q100
const content = `HMQ;V1.0;I${props.dataContent.itemCode};P${props.dataContent.packingNumber};B${props.dataContent.batch};Q${props.dataContent.qty}`
uni.setClipboardData({
data: content,
success: () => {
uni.showToast({
title: '复制制品标签成功'
})
}
})
}
const isDevlement = () => {
return config.isDevelopment
}
</script>
<style></style>

208
src/mycomponents/package/packageList.vue

@ -0,0 +1,208 @@
<template>
<view class="">
<view class="" v-for="(item, index) in dataContent" :key="item.id">
<u-collapse ref="collapse2">
<u-collapse-item :disabled="false" @change="collapseChange" :open="true">
<template v-slot:title>
<u-swipe-action :options="item.scaned && isEdit ? editAndRemoveOptions : item.scaned ? removeOptions : options" bg-color="rgba(255,255,255,0)" @click="(...event) => swipeClick(event, item, 'parent', index)">
<package-card :dataContent="item" :isShowLocation="false" :isShowFromLocation="isShowFromLocation" :isShowStatus="isShowStatus"> </package-card>
</u-swipe-action>
</template>
<u-swipe-action :show="item.show" :index="index" v-for="(pack, key) in item.packList" :key="key" :options="cur.scaned && isEdit ? editAndRemoveOptions : cur.scaned ? removeOptions : options" bg-color="rgba(255,255,255,0)" @click="(...event) => swipeClick(event, cur, 'child', key, item)">
<package-card :dataContent="pack" :isShowLocation="false" :isShowFromLocation="false" :isShowPackingNumberProps="isShowPackingNumberProps" :isShowToLocation="false" :isShowStatus="isShowPackListStatus" :isShowRecommendQty="false" :isShowBatch="false"></package-card>
</u-swipe-action>
</u-collapse-item>
</u-collapse>
</view>
<recommend-qty-edit ref="receiptEdit" :dataContent="editItem" :settingParam="settingParam" @confirm="confirm" :isNumPackTips="isNumPackTips"></recommend-qty-edit>
<com-message ref="comMessageRef" />
</view>
</template>
<script setup lang="ts">
import { ref, getCurrentInstance, onMounted, nextTick } from 'vue'
import config from '@/static/config.js'
import packageCard from '@/mycomponents/package/packageCard.vue'
import recommendQtyEdit from '@/mycomponents/qty/recommendQtyEdit.vue'
import { getRemoveOption, getEditRemoveOption } from '@/common/array.js'
const editItem = ref({})
const options = ref([])
const removeOptions = ref([])
const editAndRemoveOptions = ref([])
const comMessageRef = ref()
const collapse2 = ref()
const receiptEdit = ref()
onMounted(() => {
removeOptions.value = getRemoveOption()
editAndRemoveOptions.value = getEditRemoveOption()
})
const props = defineProps({
dataContent: {
type: Object,
default: null
},
isShowContainer: {
type: Boolean,
default: true
},
isShowPack: {
type: Boolean,
default: true
},
isShowBatch: {
type: Boolean,
default: true
},
isShowFromLocation: {
type: Boolean,
default: true
},
isShowToLocation: {
type: Boolean,
default: false
},
isShowStatus: {
type: Boolean,
default: true
},
isShowPackListStatus: {
type: Boolean,
default: true
},
locationTitle: {
type: String,
default: '库位'
},
settingParam: {
type: Object,
default: null
},
isEdit: {
type: Boolean,
default: false
},
//
isShowPackingNumberProps: {
type: Boolean,
default: false
},
isNumPackTips: {
type: Boolean,
default: false
}
})
const dataContent = ref(props.dataContent)
dataContent.value.forEach((item) => {
item.packList.forEach((cur) => {
cur.show = false
})
})
console.log(dataContent.value)
const swipeClick = (params, item, type, index, ele) => {
let text = ''
if (item.scaned && props.isEdit) {
text = editAndRemoveOptions.value[params[1]].text
// (cur.scaned&&isEdit)?editAndRemoveOptions : cur.scaned? removeOptions:options
} else if (item.scaned) {
text = removeOptions.value[params[1]].text
} else {
text = options.value[params[1]].text
}
if (text == '编辑') {
edit(item)
} else if (text == '移除') {
if (type == 'parent') {
removeParent(item, type)
} else {
remove(item, type, index, ele)
}
}
}
const removeParent = (item, type) => {
comMessageRef.value.showQuestionMessage('确定移除扫描信息?', (res) => {
if (res) {
item.scaned = false
item.handleQty = null
item.packList.forEach((subItem) => {
subItem.scaned = false
subItem.handleQty = null
})
emit('updateData', type, item)
}
})
}
const remove = (item, type, index, ele) => {
comMessageRef.value.showQuestionMessage('确定移除扫描信息?', (res) => {
if (res) {
item.scaned = false
item.handleQty = null
collapseChange()
emit('updateData', type, item, index, ele)
}
})
}
const edit = (item) => {
editItem.value = item
receiptEdit.value.openTaskEditPopup(item.qty, item.handleQty, item.labelQty, item.packQty)
}
const collapseChange = () => {
resizeCollapse()
emit('collapseChange')
}
const resizeCollapse = () => {
nextTick(() => {
collapse2.value.forEach((r) => {
r.childrens.forEach((i) => {
i.init()
})
r.init()
})
})
}
const copy = () => {
// HPQ;V1.0;ICE115F11161AG;PP20230427000026;B20230427002;Q100
const content = `HPQ;V1.0;I${props.dataContent.itemCode};P${props.dataContent.packingNumber};B${props.dataContent.batch};Q${props.dataContent.qty}`
uni.setClipboardData({
data: content,
success: () => {
uni.showToast({
title: '复制采购标签成功'
})
}
})
}
const copyPro = () => {
// HPQ;V1.0;ICE115F11161AG;PP20230427000026;B20230427002;Q100
const content = `HMQ;V1.0;I${props.dataContent.itemCode};P${props.dataContent.packingNumber};B${props.dataContent.batch};Q${props.dataContent.qty}`
uni.setClipboardData({
data: content,
success: () => {
uni.showToast({
title: '复制制品标签成功'
})
}
})
}
const isDevlement = () => {
return config.isDevelopment
}
const confirm = (qty) => {
editItem.value.handleQty = qty
emit('updateData')
}
//
const emit = defineEmits(['collapseChange', 'updateData'])
</script>
<style>
.open {
/* background-color: green !important; */
padding-top: 0px !important;
}
</style>

118
src/mycomponents/package/packageRecordCard.vue

@ -0,0 +1,118 @@
<template>
<view :class="dataContent.scaned ? 'scan_view' : ''" style="background-color: #fff">
<!-- border-bottom: 1upx solid #EEEEEE; -->
<view class="uni-flex uni-row space-between" style="align-items: center">
<!-- uni-inline-item 暂时拿掉-->
<view style="word-break: break-all">
<!-- <container v-if="isShowContainer&&dataContent.containerNumber!=null" :container="dataContent.containerNumber">
</container> -->
<pack v-if="isShowPack && dataContent.packingNumber != null" :packingCode="dataContent.packingNumber"> </pack>
<batch v-if="isShowBatch && dataContent.batch != null" :batch="dataContent.batch"></batch>
<location v-if="isShowFromLocation" title="来源库位" :locationCode="dataContent.fromLocationCode"> </location>
<!-- <to-location></to-location> -->
<to-location v-if="isShowToLocation" title="目标库位" :locationCode="dataContent.toLocationCode"> </to-location>
</view>
<view class="uni-flex uni-row" style="word-break: break-all">
<qty v-if="true" :dataContent="dataContent" :isShowStdPack="isShowStdPack" :isShowStatus="isShowStatus"> </qty>
<compare-qty v-else :dataContent="dataContent" :recommendQty="Number(dataContent.qty)" :handleQty="dataContent.handleQty" :isShowStatus="false" :isShowPack="isShowPack"> </compare-qty>
<view class="uni-flex uni-row center" style="vertical-align: center" v-if="isDevlement()">
<!-- <text style="font-size: 25rpx;color: #2979ff; width: 45rpx; " @click="copy">复制</text> -->
<image style="width: 26rpx; height: 26rpx" src="/static/icons/icon_copy.svg" alt="" @click.stop="copy" />
</view>
</view>
</view>
</view>
</template>
<script setup lang="ts">
import qty from '@/mycomponents/qty/qty.vue'
import container from '@/mycomponents/container/container.vue'
import pack from '@/mycomponents/balance/pack.vue'
import location from '@/mycomponents/balance/location.vue'
import toLocation from '@/mycomponents/balance/toLocation.vue'
import batch from '@/mycomponents/balance/batch.vue'
import recommendQty from '@/mycomponents/qty/recommendQty.vue'
import compareQty from '@/mycomponents/qty/compareQty.vue'
import config from '@/static/config.js'
import balanceQty from '@/mycomponents/qty/balanceQty.vue'
const props = defineProps({
dataContent: {
type: Object,
default: {}
},
isShowStdPack: {
type: Boolean,
default: true
},
isShowContainer: {
type: Boolean,
default: true
},
isShowPack: {
type: Boolean,
default: true
},
isShowBatch: {
type: Boolean,
default: true
},
isShowFromLocation: {
type: Boolean,
default: true
},
isShowToLocation: {
type: Boolean,
default: false
},
isShowStatus: {
type: Boolean,
default: true
},
locationTitle: {
type: String,
default: '库位'
},
isShowBalanceQty: {
type: Boolean,
default: true
},
showPack: {
type: Boolean,
default: false
}
})
const copy = () => {
// HPQ;V1.0;ICE115F11161AG;PP20230427000026;B20230427002;Q100
const content = `HPQ;V1.0;I${props.dataContent.itemCode};P${props.dataContent.packingNumber};B${props.dataContent.batch};Q${props.dataContent.qty}`
uni.setClipboardData({
data: content,
success: () => {
uni.showToast({
title: '复制采购标签成功'
})
}
})
}
const copyPro = () => {
// HPQ;V1.0;ICE115F11161AG;PP20230427000026;B20230427002;Q100
const content = `HMQ;V1.0;I${props.dataContent.itemCode};P${props.dataContent.packingNumber};B${props.dataContent.batch};Q${props.dataContent.qty}`
uni.setClipboardData({
data: content,
success: () => {
uni.showToast({
title: '复制制品标签成功'
})
}
})
}
const isDevlement = () => {
return config.isDevelopment
}
</script>
<style></style>

163
src/mycomponents/package/packageRecordList.vue

@ -0,0 +1,163 @@
<template>
<view class="">
<view class="" v-for="(item,index) in dataContent" :key="item.id">
<u-collapse ref="collapse2">
<u-collapse-item :disabled="false" @change="collapseChange">
<template v-slot:title>
<packageRecordCard :dataContent="item" :isShowLocation="false"
:isShowFromLocation="false" style='flex:1'></packageRecordCard>
</template>
<u-swipe-action :show="item.show" :index="index" v-for="(item,index) in item.packList"
:key="index" :options="editAndRemoveOptions" bg-color='rgba(255,255,255,0)'
@click="(...event) =>swipeClick(event,item)">
<packageRecordCard :dataContent="item" :isShowLocation="false" :isShowFromLocation="false"
:isShowToLocation="false" :isShowBatch="false"></packageRecordCard>
</u-swipe-action>
</u-collapse-item>
</u-collapse>
</view>
<balance-qty-edit ref="balanceQtyEdit" @confirm="confirm"></balance-qty-edit>
</view>
</template>
<script setup lang="ts">
import {
ref,
getCurrentInstance,
onMounted,
nextTick
} from 'vue'
import config from '@/static/config.js'
import packageRecordCard from '@/mycomponents/package/packageRecordCard.vue'
import balanceQtyEdit from '@/mycomponents/qty/balanceQtyEdit.vue'
import {
getRemoveOption,
getEditRemoveOption
} from '@/common/array.js';
onMounted(()=>{
removeOptions.value = getRemoveOption();
editAndRemoveOptions.value =getEditRemoveOption()
})
const props = defineProps({
dataContent: {
type: Object,
default: null
},
isShowContainer: {
type: Boolean,
default: true
},
isShowPack: {
type: Boolean,
default: true
},
isShowBatch: {
type: Boolean,
default: true
},
isShowFromLocation: {
type: Boolean,
default: true
},
isShowToLocation: {
type: Boolean,
default: false
},
isShowStatus: {
type: Boolean,
default: true
},
locationTitle: {
type: String,
default: '库位'
},
settingParam: {
type: Object,
default: null
},
isEdit:{
type: Boolean,
default: false
}
})
const editItem = ref({})
const options = ref([])
const removeOptions = ref([])
const editAndRemoveOptions = ref([])
const collapse2 = ref([])
const dataContent = ref(props.dataContent)
dataContent.value.forEach(item=>{
item.packList.forEach(cur=>{
cur.show= false
})
})
const swipeClick=(e, item) =>{
if (e.content.text == "编辑") {
// this.edit(item)
}
}
const collapseChange=()=> {
emit("collapseChange");
resizeCollapse();
}
const resizeCollapse=()=> {
nextTick(r => {
collapse2.value.forEach(r => {
r.childrens.forEach(i => {
i.init();
})
r.init();
})
});
}
const copy=()=> {
// HPQ;V1.0;ICE115F11161AG;PP20230427000026;B20230427002;Q100
var content = "HPQ;V1.0;I" + props.detail.itemCode + ";P" + props.detail.packingNumber + ";B" + props.detail
.batch + ";Q" + props.detail.qty
uni.setClipboardData({
data: content,
success: () => {
uni.showToast({
title: '复制采购标签成功'
})
}
})
}
const copyPro=()=> {
// HPQ;V1.0;ICE115F11161AG;PP20230427000026;B20230427002;Q100
var content = "HMQ;V1.0;I" + props.detail.itemCode + ";P" + props.detail.packingNumber + ";B" + props.detail
.batch + ";Q" + props.detail.qty
uni.setClipboardData({
data: content,
success: () => {
uni.showToast({
title: '复制制品标签成功'
})
}
})
}
const isDevlement=()=> {
return config.isDevelopment;
}
const confirm=(qty)=>{
editItem.value.qty =qty;
emit('updateData')
}
//
const emit = defineEmits(['collapseChange', 'updateData'])
</script>
<style>
.open {
/* background-color: green !important; */
padding-top: 0px !important;
}
</style>

144
src/mycomponents/print/print.vue

@ -0,0 +1,144 @@
<template>
<view class="uni-flex uni-column" style="width: 100%">
<view class="title" style="display: flex; align-items: center; padding: 10rpx">
<text style="flex-shrink: 0; width: 22%; font-size: 35rpx; font-weight: bold">打印机 :</text>
<view class="uni-flex" style="uni-row; width: 78%; justify-content: space-between; align-items: center; ">
<view class="customerBorder" @click="showSelectPrint">
{{ printName }}
</view>
<u-select v-model="showPrintSelect" mode="mutil-column-auto" :list="printList" @confirm="confirmSelectPrint"></u-select>
<view class="" style="">
<image src="/static/icons/down.svg" mode="" style="width: 40rpx; height: 40rpx; margin-left: 20rpx" @click="showSelectPrint"> </image>
</view>
</view>
</view>
<view class="split_line"></view>
<view class="title" style="display: flex; align-items: center; padding: 10rpx">
<text style="flex-shrink: 0; width: 22%; font-size: 35rpx; font-weight: bold">模版 :</text>
<view class="uni-flex" style="uni-row; width: 78%; justify-content: space-between; align-items: center; ">
<view class="customerBorder" @click="showSelectTemplate">
{{ templateName }}
</view>
<u-select v-model="showTemplateSelect" mode="mutil-column-auto" :list="templateList" @confirm="confirmSelectTemplate"></u-select>
<view class="">
<image src="/static/icons/down.svg" mode="" style="width: 40rpx; height: 40rpx; margin-left: 20rpx" @click="showSelectTemplate"> </image>
</view>
</view>
</view>
<view class="split_line"></view>
<comMessage ref="comMessage"></comMessage>
</view>
</template>
<script>
import { getPrintList, getPrintTemplateList } from '@/api/request2.js'
export default {
data() {
return {
showPrintSelect: false,
printName: '请选择打印机',
printCode: '',
showTemplateSelect: false,
templateName: '请选择打印模版',
templateCode: '',
printList: [],
templateList: []
}
},
//
props: {
// printList: {
// type: Array,
// default() {
// return [];
// }
// },
// templateList: {
// type: Array,
// default() {
// return [];
// }
// },
// printDeafult:{
// type:String,
// default:""
// },
// templateDeafult:{
// type:String,
// default:""
// },
},
methods: {
setDefaultData(printDeafult, templateDeafult) {
this.printName = printDeafult?.label || '请选择打印机'
this.printCode = printDeafult?.value || ''
this.templateName = templateDeafult?.label || '请选择打印模板'
this.templateCode = templateDeafult?.value || ''
},
showErrorMessage(message, type) {
setTimeout((r) => {
this.$refs.comMessage.showErrorMessage(message, (res) => {})
})
},
async showSelectPrint() {
uni.showLoading({
title: '加载中',
mask: true
})
await getPrintList()
.then((res) => {
this.printList = res.data
this.showPrintSelect = true
uni.hideLoading()
})
.catch((error) => {
uni.hideLoading()
this.showErrorMessage(error)
})
},
confirmSelectPrint(e) {
console.log(e)
this.printCode = e[0].value
this.printName = e[0].label
this.$emit('printCode', e[0])
},
async showSelectTemplate() {
uni.showLoading({
title: '加载中',
mask: true
})
await getPrintTemplateList()
.then((res) => {
this.templateList = res.data
uni.hideLoading()
this.showTemplateSelect = true
})
.catch((error) => {
uni.hideLoading()
this.showErrorMessage(error)
})
},
confirmSelectTemplate(e) {
this.templateCode = e[0].value
this.templateName = e[0].label
this.$emit('templateCode', e[0])
}
}
}
</script>
<style lang="scss">
.customerBorder {
width: 100%;
border: 1rpx solid lightgray;
border-radius: 5rpx;
padding: 15rpx;
}
</style>
<style></style>

213
src/mycomponents/qty/numbeIntegerrBox.vue

@ -0,0 +1,213 @@
<template>
<view class="uni-numbox">
<view @click="_calcValue('minus')" class="uni-numbox__minus uni-numbox-btns" :style="{ background }">
<text class="uni-numbox--text" :class="{ 'uni-numbox--disabled': inputValue <= min || disabled }">-</text>
</view>
<input :disabled="disabled" @input="onKeyInput" @blur="_onBlur" class="uni-numbox__value" type="number" v-model="inputValue" />
<view @click="_calcValue('plus')" class="uni-numbox__plus uni-numbox-btns" :style="{ background }">
<text class="uni-numbox--text" :class="{ 'uni-numbox--disabled': inputValue >= max || disabled }">+</text>
</view>
</view>
</template>
<script setup lang="ts">
import { onMounted, nextTick, watch } from 'vue'
// name: "UniNumberBox"
const props = defineProps({
value: {
type: [Number, String],
default: 1
},
min: {
type: Number,
default: 0
},
max: {
type: Number,
default: 100
},
step: {
type: Number,
default: 1
},
background: {
type: String,
default: '#f5f5f5'
},
disabled: {
type: Boolean,
default: false
}
})
const inputValue = ref(0)
watch(
() => inputValue.value,
(newVal, oldVa) => {
if (+newVal !== +oldVal) {
emit('change', newVal)
}
},
{
immediate: true,
deep: true
}
)
onMounted(() => {
inputValue.value = +props.value
})
const setValue = (val) => {
inputValue.value = val
}
//
const onKeyInput = (event) => {
// console.log( event.detail.value)
const hint = event.detail.value
if (!Number.isInteger(hint)) {
//
const temp = hint.toString().match(/^\d+/)
if (Array.isArray(temp)) {
inputValue.value = temp[0]
} else {
inputValue.value = temp
}
// this.inputValue = hint.toString().match(/^\d+/) || 0;
} else {
//
inputValue.value = hint
}
}
// (minus:;plus:)
const _calcValue = (type) => {
if (this.disabled) {
return
}
const scale = _getDecimalScale()
let value = inputValue.value * scale
const step = props.step * scale
if (type === 'minus') {
value -= step
if (value < props.min * scale) {
return
}
if (value > props.max * scale) {
value = props.max * scale
}
} else if (type === 'plus') {
value += step
if (value > props.max * scale) {
return
}
if (value < props.min * scale) {
value = props.min * scale
}
}
if (`${value}`.length > 5) {
value = value.toFixed(0) // toFixed
}
inputValue.value = String(value / scale)
}
const _getDecimalScale = () => {
const scale = 1
//
// if (~~this.step !== this.step) {
// scale = Math.pow(10, (this.step + "").split(".")[1].length);
// }
return scale
}
const onBlur = (event) => {
let { value } = event.detail
if (!value) {
return
}
value = +value
if (value > props.max) {
value = props.max
} else if (value < props.min) {
value = props.min
}
inputValue.value = value
/* 小数点后保留四位 */
// if (value > 0) {
// event.detail.value =parseFloat(event.detail.value).toFixed(0)
// } else {
// event.detail.value =-parseFloat(event.detail.value).toFixed(0)
// }
// input
nextTick(() => {
inputValue.value = event.detail.value
})
}
//
const emit = defineEmits(['change', 'confirm'])
</script>
<style lang="scss" scoped>
$box-height: 26px;
$bg: #f5f5f5;
$br: 2px;
$color: #333;
.uni-numbox {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
}
.uni-numbox-btns {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
align-items: center;
justify-content: center;
padding: 0 8px;
background-color: $bg;
/* #ifdef H5 */
cursor: pointer;
/* #endif */
}
.uni-numbox__value {
margin: 0 2px;
background-color: $bg;
width: 100px;
height: $box-height;
text-align: center;
font-size: 14px;
border-left-width: 0;
border-right-width: 0;
color: $color;
}
.uni-numbox__minus {
border-top-left-radius: $br;
border-bottom-left-radius: $br;
width: 64rpx;
}
.uni-numbox__plus {
border-top-right-radius: $br;
border-bottom-right-radius: $br;
width: 64rpx;
}
.uni-numbox--text {
// fix nvue
line-height: 20px;
font-size: 20px;
font-weight: 300;
color: $color;
}
.uni-numbox .uni-numbox--disabled {
color: #c0c0c0 !important;
/* #ifdef H5 */
cursor: not-allowed;
/* #endif */
}
</style>

205
src/mycomponents/qty/numberBox.vue

@ -0,0 +1,205 @@
<template>
<view class="uni-numbox">
<view @click="_calcValue('minus')" class="uni-numbox__minus uni-numbox-btns" :style="{ background }">
<text class="uni-numbox--text" :class="{ 'uni-numbox--disabled': inputValue <= min || disabled }">-</text>
</view>
<input :disabled="disabled" @input="onKeyInput" @blur="_onBlur" class="uni-numbox__value" type="number" v-model="inputValue" />
<view @click="_calcValue('plus')" class="uni-numbox__plus uni-numbox-btns" :style="{ background }">
<text class="uni-numbox--text" :class="{ 'uni-numbox--disabled': inputValue >= max || disabled }">+</text>
</view>
</view>
</template>
<script>
/**
* NumberBox 数字输入框
* @description 带加减按钮的数字输入框
* @tutorial https://ext.dcloud.net.cn/plugin?id=31
* @property {Number} value 输入框当前值
* @property {Number} min 最小值
* @property {Number} max 最大值
* @property {Number} step 每次点击改变的间隔大小
* @property {String} background 背景色
* @property {Boolean} disabled = [true|false] 是否为禁用状态
* @event {Function} change 输入框值改变时触发的事件参数为输入框当前的 value
*/
export default {
name: 'UniNumberBox',
emits: ['change'],
props: {
value: {
type: [Number, String],
default: 1
},
min: {
type: Number,
default: 0
},
max: {
type: Number,
default: 100
},
step: {
type: Number,
default: 1
},
background: {
type: String,
default: '#f5f5f5'
},
disabled: {
type: Boolean,
default: false
}
},
data() {
return {
inputValue: 0
}
},
watch: {
inputValue(newVal, oldVal) {
if (+newVal !== +oldVal) {
this.$emit('change', newVal)
}
}
},
created() {
this.inputValue = +this.value
},
methods: {
//
onKeyInput(event) {
// this.value = event.target.value;
},
// (minus:;plus:)
_calcValue(type) {
if (this.disabled) {
return
}
const scale = this._getDecimalScale()
let value = this.inputValue * scale
const step = this.step * scale
if (type === 'minus') {
value -= step
if (value < this.min * scale) {
return
}
if (value > this.max * scale) {
value = this.max * scale
}
} else if (type === 'plus') {
value += step
if (value > this.max * scale) {
return
}
if (value < this.min * scale) {
value = this.min * scale
}
}
if (`${value}`.length > 5) {
value = value.toFixed(6) // toFixed
}
this.inputValue = String(value / scale)
},
_getDecimalScale() {
let scale = 1
//
if (~~this.step !== this.step) {
scale = 10 ** `${this.step}`.split('.')[1].length
}
return scale
},
_onBlur(event) {
let { value } = event.detail
if (!value) {
return
}
value = +value
if (value > this.max) {
value = this.max
} else if (value < this.min) {
value = this.min
}
this.inputValue = value
/* 小数点后保留四位 */
if (value > 0) {
event.detail.value = parseFloat(event.detail.value).toFixed(6)
} else {
event.detail.value = -parseFloat(event.detail.value).toFixed(6)
}
// input
this.$nextTick(() => {
this.inputValue = event.detail.value
})
}
}
}
</script>
<style lang="scss" scoped>
$box-height: 26px;
$bg: #f5f5f5;
$br: 2px;
$color: #333;
.uni-numbox {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
}
.uni-numbox-btns {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
align-items: center;
justify-content: center;
padding: 0 8px;
background-color: $bg;
/* #ifdef H5 */
cursor: pointer;
/* #endif */
}
.uni-numbox__value {
margin: 0 2px;
background-color: $bg;
width: 100px;
height: $box-height;
text-align: center;
font-size: 14px;
border-left-width: 0;
border-right-width: 0;
color: $color;
}
.uni-numbox__minus {
border-top-left-radius: $br;
border-bottom-left-radius: $br;
width: 64rpx;
}
.uni-numbox__plus {
border-top-right-radius: $br;
border-bottom-right-radius: $br;
width: 64rpx;
}
.uni-numbox--text {
// fix nvue
line-height: 20px;
font-size: 20px;
font-weight: 300;
color: $color;
}
.uni-numbox .uni-numbox--disabled {
color: #c0c0c0 !important;
/* #ifdef H5 */
cursor: not-allowed;
/* #endif */
}
</style>

26
src/mycomponents/qty/packQty.vue

@ -0,0 +1,26 @@
<template>
<view class="std_pack" v-if="dataContent.packQty!=undefined">
<text>
{{Number(dataContent.packQty)}}{{getPackUnit(dataContent.packUnit)}}
</text>
</view>
</template>
<script setup lang="ts">
import {
getPackUnitInfo
} from "@/common/directory.js"
const props = defineProps({
dataContent: {
packQty: 1000,
uom: "EA",
}
})
const getPackUnit = (packUnit) => {
let std = getPackUnitInfo(packUnit);
return std == "" ? packUnit : std.label;
}
</script>
<style>
</style>

40
src/mycomponents/qty/packUnit.vue

@ -0,0 +1,40 @@
<template>
<view class="std_pack" v-if="dataContent.packQty">
<text>
<!-- {{Number(dataContent.packQty)}}{{getUomInfo(dataContent.uom)}}/{{getPackUnitName(dataContent.packUnit)}} -->
<!-- {{getPackUnit(dataContent.packUnit)}}({{Number(dataContent.packQty)}}{{getUom(dataContent.uom)}})-->
{{ dataContent.packUnit }}({{ Number(dataContent.packQty) }}{{ getUom(dataContent.uom) }})
</text>
</view>
</template>
<script setup lang="ts">
import {onLoad} from "@dcloudio/uni-app";
import {
getUomInfo,
getPackUnitName
} from '@/common/directory.js';
const props = defineProps({
dataContent: {
packQty: 1000,
uom: "EA",
}
})
const getUom = (uom) => {
let item = getUomInfo(uom);
if (item == '') {
return uom;
} else {
return item.label
}
}
const getPackUnit = (packUnit) => {
let unit = getPackUnitName(packUnit);
return unit;
}
</script>
<style>
</style>

151
src/mycomponents/qty/qtyEdit.vue

@ -0,0 +1,151 @@
<template>
<view class="">
<u-popup v-model="show" mode="bottom">
<view class="uni-flex uni-column pop_customer">
<view class="" style="padding:10rpx">
<view class="uni-flex u-col-center uni-row space-between" style="padding: 10rpx 10rpx 20rpx 10rpx">
<view class="" style="font-size: 35rpx;">
{{title}}
</view>
<image style="width: 35rpx;height: 35rpx;" src="/static/icons/icons_close.svg"
@click="closeEditPopup"></image>
</view>
<view class='split_line'></view>
<view class="uni-flex uni-column" style="background-color: white; height:60%;">
<view class="uni-flex uni-column ">
<view class="uni-flex uni-row space-between padding title u-col-center">
<text>数量 : </text>
<view class="uni-flex uni-row uni-center" style="align-items: center;">
<input class="qty_input" v-model="allQty" :focus="true" type="number"
@confirm="confirm()" />
<uom :uom="dataContent.uom"></uom>
</view>
</view>
</view>
</view>
</view>
<view class="uni-flex uni-row hide_border">
<button class="btn_edit_big_cancle" hover-class="btn_edit_big_after" @click="cancel()">取消</button>
<button class="btn_edit_big_confirm" hover-class="btn_edit_big_after" @click="confirm()">确认</button>
</view>
</view>
</u-popup>
<comMessage ref="comMessageRef"></comMessage>
</view>
</template>
<script setup>
import uom from '@/mycomponents/qty/uom.vue'
import StdUom from '@/mycomponents/qty/StdUom.vue'
import balanceStatus from '@/mycomponents/status/balanceStatus.vue'
import { ref,onBeforeMount } from 'vue';
import { onLoad } from '@dcloudio/uni-app'; // uni-app onLoad
const props = defineProps({
title: {
type: String,
default: "编辑数量"
},
settingParam: {
type: Object,
default: () => ({})
},
isShowStatus: {
type: Boolean,
default: true
},
allowEditStatus: {
type: Boolean,
default: false
},
allowBiggerQty: {
type: String,
default: 'TRUE'
},
});
const emit = defineEmits(['confirm']);
const comMessageRef = ref(null);
const allQty = ref(0);
const balanceQty = ref(0);
const inventoryStatus = ref("");
const originalInventoryStatus = ref("");
const dataContent = ref({});
const handleQty = ref(0);
const reason = ref("");
const show = ref(false);
const openEditPopup = (item, handleQty) => {
dataContent.value = item;
allQty.value = Number(handleQty);
setTimeout(() => {
show.value = true
}, 100);
};
const closeEditPopup = () => {
show.value = false
};
const confirm = () => {
setValue();
};
const cancel = () => {
dataContent.value.inventoryStatus = originalInventoryStatus.value;
closeEditPopup();
};
const calcQty = (val) => {
allQty.value = val * Number(dataContent.value.packQty);
};
const setValue = () => {
const balanceQtyValue = Number(dataContent.value.qty);
if (allQty.value === 0) {
comMessageRef.value.showConfirmWarningModal('数量必须大于0', () => {
allQty.value = balanceQtyValue;
});
} else if (allQty.value > balanceQtyValue && props.allowBiggerQty == 'FALSE') {
comMessageRef.value.showConfirmWarningModal(`数量[${allQty.value}]不允许大于库存数量[${balanceQtyValue}]`, () => {
allQty.value = balanceQtyValue;
});
} else {
console.log(33, allQty.value);
emit('confirm', Number(allQty.value));
closeEditPopup();
}
};
const updateStatus = (value) => {
inventoryStatus.value = value;
console.log(inventoryStatus.value);
};
</script>
<style lang="scss">
.uni-popup .uni-popup__wrapper {
width: 100% !important;
padding: 30rpx;
}
.hide_border {
button {
border: none;
}
button::after {
border: none;
}
}
.title {
font-size: 30rpx;
}
</style>

86
src/mycomponents/qty/recommendHandleQty.vue

@ -0,0 +1,86 @@
<template>
<view>
<status v-if="isShowStatus" :status='dataContent.inventoryStatus'></status>
<view class="uni-flex uni-row center">
<view class="text_recommend " v-if="Number(recommendQty)">
{{ Number(recommendQty) }}/
</view>
<view class="text_recommend ">
{{ Number(dataContent.qty) }}
</view>
</view>
<view>
<pack-unit :dataContent="dataContent"></pack-unit>
<!-- <std-pack-qty v-show="isShowStdPack" :dataContent="dataContent"></std-pack-qty> -->
</view>
</view>
</template>
<script setup>
import packUnit from '@/mycomponents/qty/packUnit.vue'
import uom from '@/mycomponents/qty/uom.vue'
import status from '@/mycomponents/status/status.vue'
import { ref, watch } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
const props = defineProps({
type: {
type: String,
default: 'default' // recommend: compare:
},
dataContent: {
type: Object,
default: () => ({})
},
recommendQty: {
type: Number,
default: 0
},
handleQty: {
type: Number,
default: 0
},
isShowStatus: {
type: Boolean,
default: true
},
isShowStdPack: {
type: Boolean,
default: true
},
objTextStyle: {
type: Object,
default: null
},
isShowPackCount: {
type: Boolean,
default: true
},
isShowCount: {
type: Boolean,
default: true
}
});
const calc = (qty, packQty) => {
if (qty && packQty) {
return Math.ceil(Number(qty) / Number(packQty));
} else {
return 0;
}
};
watch(() => props.type, (newVal) => {
//
});
onLoad(() => {
//
});
</script>
<style lang="scss">
</style>

205
src/mycomponents/query/balanceQuery.vue

@ -0,0 +1,205 @@
<template>
<view style=" ">
<u-popup v-model="show" mode="left" : :width="330">
<view style="height:100vh;display:flex;flex-direction:column;">
<view class="uni-flex" style="justify-content: center;
background-color:#007AFF ;
color: #fff;
padding: 15rpx;
font-size: 35rpx;">
库存查询
</view>
<scroll-view v-if="true" style="height: calc(100vh - 180rpx)" scroll-y="true">
<!-- <button @click="closeDrawer" type="primary">关闭Drawer</button> -->
<!-- <view v-for="item in 110" :key="item">可滚动内容 {{ item }}</view> -->
<view class="" style="margin: 10rpx; font-size: 35rpx;">
物料号
</view>
<view style=" margin: 10rpx; display: flex; align-items: center;">
<u-input class="uni-mt-5" prefixIcon="search" v-model="itemCode" placeholder="请输入物料号"
@clear="clearItemCode" @confirm="onConfirmItemCode"></u-input>
<!-- <view>查询</view> -->
<!-- <button style="height: 80rpx; align-items: center; text-align: center;" type="primary" size="mini" >查询</button> -->
</view>
<view v-for="(item, index) in itemCodeResult" :key="index" @click="selectItemCode(item)">
<view class="" style="font-size: 30rpx; margin: 20rpx;">
<view class="">
({{index+1}}) 物料代码 : {{item.code}}
</view>
<view class="">
名称 : {{item.name}}
</view>
<view class="">
描述1 : {{item.desc1}}
</view>
<view class="">
描述2 : {{item.desc1}}
</view>
</view>
<view class="split_line"></view>
</view>
<scroll-view scroll-x="true" v-if="tableData.length>0"
style="width: 330px; display: flex; align-items: center; justify-content: center; ">
<view
style="width: 330px; display: flex;justify-content: center; background-color: #fff; padding-bottom: 150rpx;">
<u-table border stripe emptyText="暂无更多数据">
<!-- 表头行 -->
<u-tr>
<u-th width="60" align="left">批次</u-th>
<u-th width="100" align="left">库位</u-th>
<u-th width="60" align="left">状态</u-th>
<u-th width="120" align="left">数量</u-th>
</u-tr>
<!-- 表格数据行 -->
<u-tr v-for="(item, index) in tableData" :key="index">
<u-td>{{item.batch}}</u-td>
<u-td>{{item.locationCode}}</u-td>
<u-td>{{statusDesc(item.inventoryStatus)}}</u-td>
<u-td>{{item.totalQty}}</u-td>
</u-tr>
</u-table>
<!-- <view class="uni-flex" style=" flex-direction: column; position: fixed; bottom: 0; margin-bottom: 100rpx; background-color: #fff; width: 100%; align-items: center;" >
<view class="" style="width: 100%; display: flex; justify-content: center; font-size: 32rpx;margin-top: 10rpx;margin-bottom: 10rpx;">
<view class="" >当前页{{ current }}总数{{ total }}每页{{ pageSize }}
</view>
</view>
<uni-pagination :current="current" :total="total" :show-icon="true"
@change="change" />
</view> -->
</view>
</scroll-view>
</scroll-view>
<button @click="closeDrawer" type="primary" style="padding-left: 20rpx; width: 100%;">关闭</button>
</view>
</u-popup>
<comMessage ref="comMessageRef"></comMessage>
</view>
</template>
<script setup>
import {
getBasicItemByCodeSenior,
getBalanceByBusinessType
} from '@/api/request2.js';
import {
getInventoryStatusStyle,
getInventoryStatusName
} from '@/common/directory.js';
import { ref } from 'vue';
import { onLoad } from '@dcloudio/uni-app'; // uni-app onLoad
const props = defineProps({
businessTypeCode: {
type: String,
default: ""
}
});
const comMessageRef = ref(null);
const itemCode = ref("");
const itemCodeResult = ref([]);
const current = ref(1);
const total = ref(18);
const tableData = ref([]);
const statusStyle = (val) => {
return getInventoryStatusStyle(val);
};
const statusDesc = (value) => {
return getInventoryStatusName(value);
};
const change = () => {
};
const showErrorMessage = (message) => {
comMessageRef.value.showErrorMessage(message, (res) => {
if (res) {
}
});
};
const selectItemCode = (item) => {
itemCode.value = item.code;
itemCodeResult.value = [];
getBalanceByBusiness(itemCode.value, props.businessTypeCode);
};
const clearItemCode = () => {
itemCode.value = "";
itemCodeResult.value = [];
tableData.value = [];
};
const onConfirmItemCode = () => {
if (!itemCode.value) {
showErrorMessage("物料号为空,请先输入物料号");
return;
}
tableData.value = [];
uni.showLoading({
title: "加载中",
mask: true
});
getBasicItemByCodeSenior(itemCode.value).then((res) => {
if (res.data && res.data.list.length > 0) {
if (res.data.list.length === 1) {
itemCode.value = res.data.list[0].code;
getBalanceByBusiness(itemCode.value, props.businessTypeCode);
} else {
uni.hideLoading();
itemCodeResult.value = res.data.list;
}
} else {
uni.hideLoading();
showErrorMessage("未查找到物料[" + itemCode.value + "]");
}
}).catch((error) => {
uni.hideLoading();
showErrorMessage(error);
});
};
const getBalanceByBusiness = (itemCode, businessType) => {
const params = {
itemCode: itemCode,
businessType: businessType,
inOrOut: "out"
};
getBalanceByBusinessType(params).then((res) => {
uni.hideLoading();
if (res.data && res.data.length > 0) {
tableData.value = res.data;
} else {
showErrorMessage("系统异常:按" + res.msg + "未查找到库存");
}
}).catch((error) => {
uni.hideLoading();
showErrorMessage(error);
});
};
const showDrawer = () => {
show.value = true
};
const closeDrawer = () => {
show.value = false
};
</script>
<style>
</style>

293
src/mycomponents/query/fifoQuery.vue

@ -0,0 +1,293 @@
<template>
<view style=" ">
<u-popup ref="showRight" mode="left" length="80%">
<view style="height:100vh;display:flex;flex-direction:column;">
<view class="" style=" display:flex; background-color:#007AFF ;
flex-direction: row;
align-items: center;
justify-content: center;
">
<view class="uni-flex" style="
color: #fff;
padding: 20rpx;
font-size: 35rpx;">
先进先出查询
</view>
<view class="" @click="closeDrawer"
style="position: fixed; color: #fff; font-size: 35rpx;right: 0; padding-right: 15rpx;">
关闭
</view>
</view>
<scroll-view v-if="true" style="height: calc(100vh - 180rpx)" scroll-y="true">
<!-- <button @click="closeDrawer" type="primary">关闭Drawer</button> -->
<!-- <view v-for="item in 110" :key="item">可滚动内容 {{ item }}</view> -->
<view class="" style="margin: 10rpx; font-size: 35rpx;">
物料号
</view>
<view style=" margin: 10rpx; display: flex; align-items: center;">
<u-input class="uni-mt-5" prefixIcon="search" v-model="itemCode" placeholder="请输入物料号"
@clear="clearItemCode"></u-input>
<!-- <view>查询</view> -->
<!-- <button style="height: 80rpx; align-items: center; text-align: center;" type="primary" size="mini" >查询</button> -->
</view>
<view class="" style="margin: 10rpx; margin-top: 20rpx; font-size: 35rpx;">
仓库
</view>
<view style=" margin: 10rpx; display: flex; align-items: center;">
<u-input class="uni-mt-5" prefixIcon="search" v-model="warehouseCode" placeholder="请输入仓库"
></u-input>
</view>
<view v-for="(item, index) in itemCodeResult" :key="index" @click="selectItemCode(item)">
<view class="" style="font-size: 30rpx; margin: 20rpx;">
<view class="">
({{ index + 1 }}) 物料代码 : {{ item.code }}
</view>
<view class="">
名称 : {{ item.name }}
</view>
<view class="">
描述1 : {{ item.desc1 }}
</view>
<view class="">
描述2 : {{ item.desc1 }}
</view>
</view>
<view class="split_line"></view>
</view>
<scroll-view v-if="tableData.length>0"
:scroll-x="true"
:scroll-y="true"
style=" width: 340px; display: flex; align-items: center; justify-content: center; ">
<u-table border stripe emptyText="暂无更多数据">
<!-- 表头行 -->
<u-tr>
<!-- <uni-th align="left">批次</uni-th>
<uni-th align="left">库位</uni-th>
<uni-th align="left">状态</uni-th>
<uni-th align="left">数量</uni-th>
<uni-th align="left">单位</uni-th> -->
<u-th width="60" align="left">批次</u-th>
<u-th width="60" align="left">库位</u-th>
<u-th width="60" align="left">状态</u-th>
<u-th width="100" align="left">数量</u-th>
<u-th width="60" align="left">单位</u-th>
</u-tr>
<!-- 表格数据行 -->
<u-tr v-for="(item, index) in tableData" :key="index">
<u-td>{{ item.batch }}</u-td>
<u-td>{{ item.locationCode }}</u-td>
<u-td>{{ statusDesc(item.inventoryStatus) }}</u-td>
<u-td>{{ item.totalQty }}</u-td>
<u-td>
<uom :uom="uom"></uom>
</u-td>
</u-tr>
</u-table>
<!-- <view class="uni-flex" style=" flex-direction: column; position: fixed; bottom: 0; margin-bottom: 100rpx; background-color: #fff; width: 100%; align-items: center;" >
<view class="" style="width: 100%; display: flex; justify-content: center; font-size: 32rpx;margin-top: 10rpx;margin-bottom: 10rpx;">
<view class="" >当前页{{ current }}总数{{ total }}每页{{ pageSize }}
</view>
</view>
<uni-pagination :current="current" :total="total" :show-icon="true"
@change="change" />
</view> -->
</scroll-view>
</scroll-view>
<button @click="query" type="primary" style="padding-left: 20rpx; width: 100%;">查询</button>
</view>
</u-popup>
<comMessage ref="comMessage"></comMessage>
</view>
</template>
<script setup>
import {
getBasicItemByCodeSenior,
getBalanceByBusinessType,
getBasicItemByCode
} from '@/api/request2.js';
import {
getInventoryStatusStyle,
getInventoryStatusName
} from '@/common/directory.js';
import Uom from '@/mycomponents/qty/uom.vue'
import {ref, watch} from 'vue';
const itemCode = ref('');
const itemCodeResult = ref([]);
const current = ref(1);
const total = ref(18);
const tableData = ref([]);
const warehouseCode = ref('');
const areaCode = ref('');
const uom = ref('');
const props = defineProps({
businessTypeCode: {
type: String,
default: ''
}
});
const comMessage = ref(null);
const showRight = ref();
const statusStyle = (val) => {
return getInventoryStatusStyle(val);
};
const statusDesc = (value) => {
return getInventoryStatusName(value);
};
const change = () => {
};
const showErrorMessage = (message) => {
comMessage.value.showErrorMessage(message, (res) => {
if (res) {
}
});
};
const selectItemCode = (item) => {
itemCode.value = item.code;
itemCodeResult.value = [];
getBalanceByBusiness(itemCode.value, props.businessTypeCode);
};
const clearItemCode = () => {
itemCode.value = '';
itemCodeResult.value = [];
tableData.value = [];
};
const onConfirmItemCode = () => {
if (!itemCode.value) {
showErrorMessage('物料号为空,请先输入物料号');
return;
}
tableData.value = [];
uni.showLoading({
title: '加载中',
mask: true
});
getBasicItemByCodeSenior(itemCode.value).then((res) => {
if (res.data && res.data.list.length > 0) {
if (res.data.list.length === 1) {
itemCode.value = res.data.list[0].code;
getBalanceByBusiness(itemCode.value, props.businessTypeCode);
} else {
uni.hideLoading();
itemCodeResult.value = res.data.list;
}
} else {
uni.hideLoading();
showErrorMessage(`未查找到物料[${itemCode.value}]`);
}
}).catch((error) => {
uni.hideLoading();
showErrorMessage(error);
});
};
const getBalanceByBusiness = (itemCode, businessType) => {
const params = {
itemCode,
businessType,
inOrOut: 'out'
};
getBalanceByBusinessType(params).then((res) => {
uni.hideLoading();
if (res.data && res.data.length > 0) {
tableData.value = res.data;
} else {
showErrorMessage(`系统异常:按${res.msg}未查找到库存`);
}
}).catch((error) => {
uni.hideLoading();
showErrorMessage(error);
});
};
const showDrawer = () => {
showRight.value.open();
};
const closeDrawer = () => {
showRight.value.close();
};
const query = () => {
if (itemCode.value === '') {
showErrorMessage('物料代码为空,请输入物料代码');
return;
}
if (warehouseCode.value === '') {
showErrorMessage('仓库代码为空,请输入仓库代码');
return;
}
uni.showLoading({
title: '查询中',
mask: true
});
getBasicItemByCode(itemCode.value).then((res) => {
if (res.data && res.data.list.length === 1) {
uom.value = res.data.list[0].uom;
queryBalance();
} else {
uni.hideLoading();
showErrorMessage(`未查询到物料号${itemCode.value}的信息`);
}
}).catch((error) => {
uni.hideLoading();
showErrorMessage(error);
});
};
const queryBalance = () => {
const params = {
itemCode: itemCode.value,
warehouseCode: warehouseCode.value,
businessType: props.businessTypeCode,
inOrOut: 'out'
};
getBalanceByBusinessType(params).then((res) => {
uni.hideLoading();
if (res.data && res.data.length > 0) {
tableData.value = res.data;
} else {
showErrorMessage(`系统异常:按${res.msg}未查找到库存`);
}
}).catch((error) => {
uni.hideLoading();
showErrorMessage(error);
});
};
defineExpose({
showDrawer
})
</script>
<style>
</style>

68
src/mycomponents/query/showListItem.vue

@ -0,0 +1,68 @@
<template>
<view class="wyf">
<u-popup v-model="show" mode="center">
<view class="container">
<uni-list class="list">
<uni-list-item v-for="(item,index) in list" :title="item.title"
thumb-size="lg" >
<template v-slot:footer>
<!-- <image class="slot-image" src="@/static/logo.png" mode="widthFix" @click="selectItem(item,index)"></image -->
<text class="go" @click="selectItem(item,index)">Go</text>
</template>
</uni-list-item>
</uni-list>
</view>
</u-popup>
</view>
</template>
<script setup>
import {ref} from 'vue'
const isScanedASN = ref(false)
const list = ref([])
const show = ref(false)
const emit = defineEmits(['selectItem'])
const openList = (list) => {
list.value = list
show.value = true
}
const selectItem = (item,index)=>{
show.value = false
emit("selectItem", item)
}
</script>
<style lang="scss" scoped>
.wyf{
// display: block;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1000
}
.container{
display: flex;
justify-content: center;
align-items: center;
.list{
width: 80%;
max-height:50vh;
overflow-y: auto;
border-radius: 10px !important;
.slot-image{
width: 40rpx;
}
.go{
color: rgb(60, 156, 255);
}
}
}
.list ::v-deep .uni-list--border{
border: 1rpx solid #e5e5e5;
}
</style>

31
src/mycomponents/receive/receiveBottom.vue

@ -0,0 +1,31 @@
<template>
<!-- style="margin-top: 10rpx;margin-bottom: 10rpx;" class="uni-flex uni-row space-between u-col-center" -->
<view class="task_item">
<view class="uni-flex space-between u-col-center">
<view class="uni-flex uni-row u-col-center">
<image class="card_icon_normal" src="/static/icons/icon_customer.svg" alt="" />
<text style="font-size: 32rpx;" >{{dataContent.creator}}</text>
</view>
<view class="uni-flex uni-row u-col-center">
<image class="card_icon_normal" src="/static/icons/icon_date.svg" alt="" />
<text style="font-size: 32rpx;" class="center">{{formatDate(dataContent.createTime)}}</text>
</view>
</view>
</view>
</template>
<script setup>
import {
dateFormat
} from '@/common/basic.js';
const props = defineProps({
dataContent: {
type: Object,
default: {}
}
})
const formatDate = date => dateFormat(date)
</script>
<style lang="scss">
</style>

22
src/mycomponents/receive/receiveNumber.vue

@ -0,0 +1,22 @@
<template>
<view class="task_number">
<!-- <text>任务编号 : {{number}}</text> -->
<text> {{number}}</text>
</view>
</template>
<script setup>
const props = defineProps({
number: {
type: String,
default: ''
},
})
</script>
<style lang="scss">
</style>
<style>
</style>

30
src/mycomponents/receive/receiveStatus.vue

@ -0,0 +1,30 @@
<template>
<view >
<text :class="statusStyle(receiveStatus)">
{{ receiveStatusInfo.label}}
</text>
</view>
</template>
<script setup>
import {
getReceiveStateInfo,
} from '@/common/directory.js';
import { ref } from 'vue'
const props = defineProps({
receiveStatus: {
type: String,
default: ""
}
})
const receiveStatusInfo = ref({})
const statusStyle = (value) => {
receiveStatusInfo.value = getReceiveStateInfo(value);
return getReceiveStateInfo(value).remark
}
</script>
<style>
</style>

27
src/mycomponents/receive/receiveTop.vue

@ -0,0 +1,27 @@
<template>
<view class="task_top">
<view class="uni-flex space-between u-col-center align-center" style="margin-bottom: 10rpx;">
<receive-number :number="dataContent.number"></receive-number>
<receive-status :receiveStatus="dataContent.receiveStatus"></receive-status>
</view>
</view>
</template>
<script setup>
import receiveNumber from '@/mycomponents/receive/receiveNumber.vue'
import receiveStatus from '@/mycomponents/receive/receiveStatus.vue'
const props = defineProps({
dataContent: {
type: Object,
default: {}
},
})
const openDetail = (item)=>{
emit("openDetail", dataContent.value);
}
const emit = defineEmits(['openDetail'])
</script>
<style lang="scss">
</style>

72
src/mycomponents/receive/recordComDetailCard.vue

@ -0,0 +1,72 @@
<template>
<view class="task_item">
<view class="task_text" style="border-top: 1px solid #dedede;padding-top: 20rpx;margin-top: 20rpx;">
<!-- 主子表拆分没有数量了 -->
<itemCompareQty :dataContent="dataContent"
:isShowPackCount="isShowPackCount"
:handleQty="dataContent.handleQty" :isShowPackUnit="false"
></itemCompareQty>
<!-- :objTextStyle="{'fontWeight':'bold','fontSize':'40rpx'}" -->
<div class="u-p-l-10">
<pack v-if="isShowPack && dataContent.packingNumber!=null" :packingCode="dataContent.packingNumber">
</pack>
<batch v-if="isShowBatch && dataContent.batch!=null" :batch="dataContent.batch"></batch>
<view class="u-flex u-row-between">
<location v-if="isShowFromLocation&&dataContent.fromLocationCode" title="来源库位" :locationCode="dataContent.fromLocationCode">
</location>
</view>
<to-location v-if="isShowToLocation" title="目标库位" :locationCode="dataContent.toLocationCode||dataContent.locationCode">
</to-location>
</div>
</view>
</view>
</template>
<script setup>
import pack from '@/mycomponents/balance/pack.vue'
import location from '@/mycomponents/balance/location.vue'
import toLocation from '@/mycomponents/balance/toLocation.vue'
import batch from '@/mycomponents/balance/batch.vue'
import itemCompareQty from '@/mycomponents/item/itemCompareQty.vue'
import level from '@/mycomponents/balance/level.vue'
const props = defineProps({
dataContent: {
type: Object,
default: {}
},
isShowContainer: {
type: Boolean,
default: true
},
isShowPack: {
type: Boolean,
default: true
},
isShowBatch: {
type: Boolean,
default: true
},
isShowFromLocation: {
type: Boolean,
default: true
},
isShowToLocation: {
type: Boolean,
default: true
},
isShowDeliverType: {
type: Boolean,
default: false
},
isShowPackCount: {
type: Boolean,
default: false
}
})
</script>
<style lang="scss">
</style>

27
src/mycomponents/receive/recordComMainCard.vue

@ -0,0 +1,27 @@
<template>
<view>
<view class="task_card">
<receiveTop :dataContent="dataContent"></receiveTop>
<!-- <view class="split_line"></view> -->
<slot></slot>
<view class="split_line"></view>
<receiveBottom :dataContent="dataContent"></receiveBottom>
</view>
</view>
</template>
<script setup>
import receiveTop from '@/mycomponents/receive/receiveTop.vue'
import receiveBottom from '@/mycomponents/receive/receiveBottom.vue'
const props = defineProps({
dataContent: {
type: Object,
default: {}
}
})
</script>
<style lang="scss">
</style>

141
src/mycomponents/recommend/recommendBatch.vue

@ -0,0 +1,141 @@
<template>
<view :class="detail.scaned?'scan_view':''" style="background-color: #ffffff; border-bottom: 1upx solid #EEEEEE;">
<view class="uni-flex uni-row space-between" style="align-items: center">
<!-- uni-inline-item 暂时拿掉-->
<view style="word-break: break-all;">
<!-- <container v-if="isShowContainer&&detail.containerNumber!=null" :container="detail.containerNumber">
</container> -->
<batch v-if="isShowBatch && detail.batch!=null" :batch="detail.batch"></batch>
<location v-if="isShowFromLocation" title="来源库位" :locationCode="detail.fromLocationCode">
</location>
<!-- <to-location></to-location> -->
<to-location v-if="isShowToLocation" title="目标库位" :locationCode="detail.toLocationCode">
</to-location>
</view>
<view style="word-break: break-all;" class="uni-flex uni-row center">
<!-- ||detail.handleQty==0 可能会有扫描到0的情况-->
<recommend-qty v-if="detail.handleQty==null || detail.handleQty==undefined" :dataContent="detail"
:isShowStdPack="false" :isShowStatus="isShowStatus"></recommend-qty>
<compare-qty v-else :dataContent="detail" :recommendQty="Number(detail.qty)"
:handleQty="Number(detail.handleQty)" :isShowStdPack="false" :isShowStatus="isShowStatus">
</compare-qty>
<view class="uni-flex uni-row center" style="vertical-align:center ;" v-if="isDevlement()">
<text style="font-size: 30rpx;color: #2979ff; width: 20px; " @click="copy">复制</text>
<!-- <text style="font-size: 30rpx;color: #2979ff;" @click="copyPro">|制品</text> -->
</view>
</view>
</view>
</view>
</template>
<script setup>
import container from '@/mycomponents/container/container.vue'
import pack from '@/mycomponents/balance/pack.vue'
import location from '@/mycomponents/balance/location.vue'
import toLocation from '@/mycomponents/balance/toLocation.vue'
import batch from '@/mycomponents/balance/batch.vue'
import recommendQty from '@/mycomponents/qty/recommendQty.vue'
import compareQty from '@/mycomponents/qty/compareQty.vue'
import config from '@/static/config.js'
import { watch, computed } from 'vue';
const props = defineProps({
detail: {
type: Object,
default: () => ({})
},
isShowContainer: {
type: Boolean,
default: true
},
isShowPack: {
type: Boolean,
default: true
},
isShowBatch: {
type: Boolean,
default: true
},
isShowFromLocation: {
type: Boolean,
default: true
},
isShowToLocation: {
type: Boolean,
default: false
},
isShowStatus: {
type: Boolean,
default: true
},
locationTitle: {
type: String,
default: '库位'
}
});
// Watchers
watch(() => props.detail, (newVal, oldVal) => {
if (newVal.scaned) {
newVal.copyContent = `HPQ;V1.0;I${newVal.itemCode};P${newVal.packingNumber};B${newVal.batch};Q${newVal.qty}`;
} else {
newVal.copyContent = '';
}
console.log('newVal.copyContent', newVal.copyContent);
}, { immediate: true, deep: true });
const copy = () => {
const content = `HPQ;V1.0;I${props.detail.itemCode};P${props.detail.packingNumber};B${props.detail.batch};Q${props.detail.qty}`;
// #ifdef H5
uni.$copyText(content).then(() => {
uni.showToast({
title: '复制采购标签成功',
icon: 'none'
});
});
// #endif
// #ifndef H5
uni.setClipboardData({
data: content,
success: () => {
uni.showToast({
title: '复制采购标签成功'
});
}
});
// #endif
};
const copyPro = () => {
const content = `HMQ;V1.0;I${props.detail.itemCode};P${props.detail.packingNumber};B${props.detail.batch};Q${props.detail.qty}`;
// #ifdef H5
uni.$copyText(content).then(() => {
uni.showToast({
title: '复制制品标签成功',
icon: 'none'
});
});
// #endif
// #ifndef H5
uni.setClipboardData({
data: content,
success: () => {
uni.showToast({
title: '复制制品标签成功'
});
}
});
// #endif
};
const isDevlement = ()=>{
return config.isDevelopment;
};
</script>
<style>
</style>

207
src/mycomponents/record/recordComDetailCardBatch.vue

@ -0,0 +1,207 @@
<template>
<view class="" style="background-color: #fff;">
<uni-collapse ref="collapse1">
<uni-collapse-item :open="true">
<template v-slot:title>
<uni-swipe-action>
<uni-swipe-action-item @click="removeItem($event,dataContent)" :right-options="removeOptions">
<item-qty :dataContent="dataContent" :isShowBalance="true"
:isShowBalanceQty="isShowBalanceQty"
:isShowRecommendQty="false"
></item-qty>
<view style="margin-left: 10px; margin-top: 5px;">
<pack title='父包装' v-if="dataContent.containerNumber"
:packingCode='dataContent.containerNumber'></pack>
<location v-if="isShowParentToLocation" title='目标库位'
:locationCode='dataContent.toLocationCode'></location>
</view>
</uni-swipe-action-item>
</uni-swipe-action>
</template>
<view class='split_line'></view>
<view class="" v-for="(detail,index) in dataContent.subList" :key="index">
<uni-swipe-action>
<uni-swipe-action-item @click="swipeClick($event,detail,index)"
:right-options="detail.scaned?scanOptions:detailOptions">
<balance :dataContent="detail" :isShowStdPack="false" :isShowStatus="isShowStatus"
:isShowPack="true" :isShowFromLocation="isShowFromLocation"
:isShowToLocation="isShowToLocation" :isShowParentPack="isShowParentPack">
</balance>
</uni-swipe-action-item>
</uni-swipe-action>
<!-- <view class='split_line'></view> -->
</view>
</uni-collapse-item>
</uni-collapse>
<balance-qty-edit ref="balanceQtyEdit" @confirm="confirm"></balance-qty-edit>
<record-detail-popup ref="recordDetailPopup"></record-detail-popup>
<comMessage ref="comMessage"></comMessage>
</view>
</template>
<script setup>
import itemQty from '@/mycomponents/item/itemQty.vue'
import balance from '@/mycomponents/balance/balance.vue'
import recommend from '@/mycomponents/recommend/recommend.vue'
import balanceQtyEdit from '@/mycomponents/qty/balanceQtyEdit.vue'
import balanceDetailPopup from '@/mycomponents/balance/balanceDetailPopup.vue'
import purchaseLabel from '@/mycomponents/balance/purchaseLabel.vue'
import location from '@/mycomponents/balance/location.vue'
import recordDetailPopup from '@/mycomponents/detail/recordDetailPopup.vue'
import pack from '@/mycomponents/balance/pack.vue'
import PackageAndItemCard from '@/mycomponents/package/PackageAndItemCard.vue'
import {
getDetailOption,
getDetailEditRemoveOption,
getClearOption,
getEditLocationRemoveOption,
getRecordOption
} from '@/common/array.js';
import {ref, watch, onMounted, nextTick} from 'vue';
const props = defineProps({
dataContent: {
type: Object,
default: () => ({})
},
settingParam: {
type: Object,
default: () => ({})
},
isShowStatus: {
type: Boolean,
default: true
},
isShowFromLocation: {
type: Boolean,
default: true
},
isShowToLocation: {
type: Boolean,
default: true
},
isShowParentToLocation: {
type: Boolean,
default: true
},
isShowBalanceQty: {
type: Boolean,
default: false
},
isShowParentPack: {
type: Boolean,
default: true
},
isShowModifedLocation: {
type: Boolean,
default: false
},
allowModifyQty: {
type: Boolean,
default: true
},
allowModifyLocation: {
type: Boolean,
default: false
}
});
const emit = defineEmits(['removeItem', 'removePack', 'editLocation', 'updateData']);
const option = ref([]);
const title = ref("推荐详情");
const showItem = ref({});
const editItem = ref({});
const detailOptions = ref([]);
const scanOptions = ref([]);
const removeOptions = ref([]);
const dataList = ref([]);
watch(() => props.dataContent, (newDataContent, oldDataContent) => {
if (newDataContent.subList.length > 0) {
nextTick(() => {
setTimeout(() => {
const collapse1 = ref(null);
if (collapse1.value) {
collapse1.value.init();
}
}, 500);
});
}
}, {immediate: true, deep: true});
onMounted(() => {
detailOptions.value = getDetailOption();
scanOptions.value = getRecordOption(props.allowModifyQty, props.allowModifyLocation);
removeOptions.value = props.isShowModifedLocation ? getEditLocationRemoveOption() : getClearOption();
});
const removeItem = (e, dataContent) => {
if (e.content.text === "移除") {
uni.showModal({
title: "提示",
content: "确定清空物料及箱码信息?",
success: (res) => {
if (res.confirm) {
emit('removeItem', dataContent);
}
}
});
} else {
editLocation(dataContent);
}
};
const swipeClick = (e, item, index) => {
if (e.content.text === "详情") {
detail(item);
} else if (e.content.text === "编辑") {
edit(item);
} else if (e.content.text === "移除") {
remove(item, index);
}
};
const edit = (item) => {
editItem.value = item;
const balanceQtyEdit = ref(null);
if (balanceQtyEdit.value) {
balanceQtyEdit.value.openEditPopup(editItem.value, editItem.value.handleQty);
}
};
const detail = (item) => {
showItem.value = item;
const recordDetailPopup = ref(null);
if (recordDetailPopup.value) {
recordDetailPopup.value.openPopup(item);
}
};
const remove = (item, index) => {
uni.showModal({
title: "提示",
content: "确定移除扫描信息?",
success: (res) => {
if (res.confirm) {
props.dataContent.subList.splice(index, 1);
emit('removePack');
}
}
});
};
const editLocation = (item) => {
editItem.value = item;
emit('editLocation', item);
};
const confirm = (qty) => {
editItem.value.handleQty = qty;
emit('updateData');
};
</script>
<style>
</style>

26
src/mycomponents/record/recordComMainCard.vue

@ -0,0 +1,26 @@
<template>
<view>
<view class="task_card">
<record-top :dataContent="dataContent"></record-top>
<slot></slot>
<u-line color="#909399" />
<record-bottom :dataContent="dataContent"></record-bottom>
</view>
</view>
</template>
<script setup lang="ts">
import recordTop from '@/mycomponents/record/recordTop.vue'
import recordBottom from '@/mycomponents/record/recordBottom.vue'
const props = defineProps({
dataContent: {
type: Object,
default: { }
}
})
</script>
<style lang="scss">
</style>

132
src/mycomponents/record/recordDetailCard.vue

@ -0,0 +1,132 @@
<template>
<view class="" style="background-color: #fff">
<u-collapse ref="collapse">
<u-collapse-item :open="true">
<template v-slot:title>
<itemQty :dataContent="dataContent" :handleQty="dataContent.handleQty" :isShowPackUnit="false" style="flex: 1"> </itemQty>
</template>
<packageRecordList :dataContent="dataContent.subList" :isEdit="settingParam.allowModifyQty == 'TRUE'" :settingParam="settingParam" @collapseChange="collapseChange"></packageRecordList>
</u-collapse-item>
</u-collapse>
<recommend-qty-edit ref="receiptEdit" :dataContent="editItem" :settingParam="settingParam" @confirm="confirm"> </recommend-qty-edit>
<win-scan-location ref="scanLocationCode" title="目标库位" @getLocation="getLocation" :locationAreaTypeList="locationAreaTypeList"></win-scan-location>
<receipt-detail-info-popup ref="jobDetailPopupRef" :dataContent="showItem"></receipt-detail-info-popup>
<com-message ref="comMessageRef" />
</view>
</template>
<script setup lang="ts">
import { ref, getCurrentInstance, onMounted, nextTick } from 'vue'
import itemQty from '@/mycomponents/item/itemQty.vue'
import recommend from '@/mycomponents/recommend/recommend.vue'
import recommendQtyEdit from '@/mycomponents/qty/recommendQtyEdit.vue'
import jobDetailPopup from '@/mycomponents/detail/jobDetailPopup.vue'
import receiptDetailInfoPopup from '@/pages/purchaseReceipt/coms/receiptDetailInfoPopup.vue'
import winScanLocation from '@/mycomponents/scan/winScanLocation.vue'
import pack from '@/mycomponents/balance/pack.vue'
import packageRecordList from '@/mycomponents/package/packageRecordList.vue'
import { getDetailOption, getPurchaseReceiptOption } from '@/common/array.js'
const props = defineProps({
dataContent: {
type: Object,
default: null
},
settingParam: {
type: Object,
default: null
},
locationAreaTypeList: {
type: Object,
default: null
}
})
const showItem = ref({})
const editItem = ref({
record: {}
})
const locatonItem = ref({})
const detailOptions = ref([])
const scanOptions = ref([])
const comMessageRef = ref()
const collapse = ref()
const jobDetailPopupRef = ref()
onMounted(() => {
if (detailOptions.value.length == 0) {
detailOptions.value = getDetailOption()
}
if (scanOptions.value.length == 0) {
scanOptions.value = getPurchaseReceiptOption(props.settingParam.allowModifyQty, props.settingParam.allowModifyLocation)
}
})
const collapseChange = () => {
setTimeout(() => {
resizeCollapse()
}, 500)
}
const resizeCollapse = () => {
nextTick((r) => {
collapse.value.init()
})
}
const refreshCollapse = () => {
nextTick((r) => {
collapse.value.forEach((r) => {
r.childrens.forEach((i) => {
i.init()
})
r.init()
})
})
}
const swipeClick = (e, item) => {
if (e.content.text == '详情') {
this.detail(item)
} else if (e.content.text == '编辑') {
this.edit(item)
} else if (e.content.text == '库位') {
this.showLocation(item)
} else if (e.content.text == '移除') {
this.remove(item)
}
}
const edit = (item) => {
editItem.value = item
receiptEdit.value.openTaskEditPopup(item.qty, item.handleQty, item.labelQty)
}
const showLocation = (item) => {
locatonItem.value = item
scanLocationCode.value.openScanPopup()
}
//
const getLocation = (location, code) => {
locatonItem.value.toLocationCode = code
emit('updateData')
}
const detail = (item) => {
showItem.value = item
jobDetailPopupRef.value.openPopup(item)
}
const remove = (item) => {
comMessageRef.value.showErrorMessage('确定移除扫描信息?', (res) => {
if (res) {
item.scaned = false
item.handleQty = null
emit('remove', item)
}
})
}
const confirm = (qty) => {
editItem.value.handleQty = qty
emit('updateData')
}
//
const emit = defineEmits(['remove', 'updateData'])
</script>
<style></style>

243
src/mycomponents/scan/winCheckFgLabel.vue

@ -0,0 +1,243 @@
<template>
<view>
<u-popup v-model="show" mode="bottom" :mask-close-able="false">
<!-- <uni-popup ref="popup" @change="change" @maskClick="closeScanPopup()"> -->
<view class="popup_box">
<view class="pop_title uni-flex space-between">
<view class="" style="font-size: 35rpx"> 校验客户标签 </view>
<view class="">
<image class="fr icons_scan_close" src="/static/icons/icons_scan_close.svg" @click="closeScanPopup()"></image>
</view>
</view>
<view class="">
<view class="" style="position: relative">
<win-com-scan ref="comscanFgLabel" placeholder="WMS制品标签" @getResult="getScanFgResult" :isShowHistory="false" :clearResult="true" :headerType="headerType"></win-com-scan>
<view class="uni-flex" style="position: absolute; color: #3c9cff; font-weight: bold; font-size: 15px; left: 10px; bottom: 10px; z-index: 999">
{{ itemCode }}
</view>
</view>
<view class="">
<win-com-scan-customer-label ref="comscanCustomerLabel" placeholder="客户标签" @getResult="getScanCustomerResult" :isShowHistory="false" :clearResult="true" :headerType="headerType"></win-com-scan-customer-label>
</view>
</view>
</view>
</u-popup>
</view>
<com-message ref="comMessageRef" />
</template>
<script setup lang="ts">
import { ref, getCurrentInstance, onMounted, nextTick, watch } from 'vue'
import winComScan from '@/mycomponents/scan/winComScan.vue'
import winComScanCustomerLabel from '@/mycomponents/scan/winComScanCustomerLabel.vue'
import BalanceSelect from '@/mycomponents/balance/balanceSelect.vue'
import { getBalanceByManagementPrecision } from '@/common/balance.js'
import { getCustomerItemList } from '@/api/request2.js'
import { getListLocationAreaTypeDesc, checkDirectoryItemExist, getDirectoryItemArray, getLocationAreaTypeName, getInventoryStatusDesc } from '@/common/directory.js'
const props = defineProps({
title: {
type: String,
default: '箱标签'
},
headerType: {
type: String,
default: 'HPQ,HMQ'
}
})
const show = ref(false)
const scanResult = ref({})
const scanList = ref([])
const expand = ref(false)
const showScanResult = ref({})
const expendIcon = ref('arrow-down')
const fromLocationCode = ref('')
const fromLocation = ref('')
const fromLocationList = ref([])
const fromLocationAreaTypeList = ref([])
const locationOnFocus = ref(false)
const businessType = ref({})
const inventoryStatus = ref([])
const managementPrecision = ref('')
const fromInventoryStatuses = ref('')
const isCheck = ref(false)
const itemCode = ref('')
const customerItem = ref(null)
const customerCode = ref('') //
const packingNumber = ref('') //
const comscanFgLabel = ref()
const comscanCustomerLabel = ref()
const comMessageRef = ref()
const openScanPopupForType = (customerCodeParams) => {
customerCode.value = customerCodeParams
fromInventoryStatuses.value = getDirectoryItemArray(businessType.value.outInventoryStatuses)
inventoryStatus.value = getDirectoryItemArray(businessType.value.outInventoryStatuses) //
fromLocationAreaTypeList.value = getDirectoryItemArray(businessType.value.fromLocationAreaTypeList) //
show.value = true
setTimeout(() => {
if (fromLocationCode.value != '') {
packGetFocus();
} else {
locationGetFocus();
}
}, 500)
}
//
const openScanPopupForJob = (fromLocationCode, fromLocationList, jobContent) => {
fromLocationCode.value = fromLocationCode
fromLocationList.value = fromLocationList
fromInventoryStatuses.value = getDirectoryItemArray(businessType.value.outInventoryStatuses)
inventoryStatus.value = getDirectoryItemArray(businessType.value.outInventoryStatuses) //
fromLocationAreaTypeList.value = getDirectoryItemArray(businessType.value.fromLocationAreaTypeList) //
show.value = true
setTimeout((res) => {
if (fromLocationCode != '') {
packGetFocus()
} else if (fromLocationList.value.length == 0) {
locationGetFocus()
} else {
fromLocationCode.value = fromLocationList.value[0]
packGetFocus()
}
}, 500)
fromInventoryStatuses.value = getDirectoryItemArray(jobContent.outInventoryStatuses)
inventoryStatus.value = getDirectoryItemArray(jobContent.outInventoryStatuses) // 出库库存状态; //出库库存状态
fromLocationAreaTypeList.value = getDirectoryItemArray(jobContent.fromAreaTypes) //
}
const closeScanPopup = (content) => {
show.value = false
emit('close', '')
}
const getScanFgResult = (result) => {
console.log('getScanFgResult', result)
itemCode.value = result.label.itemCode
packingNumber.value = result.package.number //
const filters = []
filters.push({
column: 'customerCode',
action: '==',
value: customerCode.value
})
filters.push({
column: 'itemCode',
action: '==',
value: itemCode.value
})
const params = {
filters,
pageNo: 1,
pageSize: 10
}
getCustomerItemList(params)
.then((res) => {
console.log('getCustomerItemList', res)
if (res.data != null && res.data.list.length > 0) {
customerItem.value = res.data.list[0]
} else {
showErrorMessage('未查找到客户物料代码')
}
})
.catch((error) => {
showErrorMessage(error)
})
customerGetFocus()
}
const getScanCustomerResult = (result) => {
console.log('getScanCustomerResult', result)
if (customerItem.value != null) {
//
if (customerItem.value.customerItemCode == result) {
//
emit('checkResult', {
packingNumber: packingNumber.value, //
customerItemCode: customerItem.value.customerItemCode, //
customerItemCode_reality: result, //
itemCode: itemCode.value, //
pass: true
})
} else {
//
emit('checkResult', {
packingNumber: packingNumber.value, //
customerItemCode: customerItem.value.customerItemCode, //
customerItemCode_reality: result, //
itemCode: itemCode.value, //
pass: false
})
}
}
}
const packGetFocus = () => {
if (comscanFgLabel.value != undefined) {
comscanFgLabel.value.getfocus()
}
}
const packLoseFocus = () => {
if (comscanFgLabel.value != undefined) {
comscanFgLabel.value.losefocus()
}
}
const customerGetFocus = () => {
if (comscanCustomerLabel.value != undefined) {
comscanCustomerLabel.value.getfocus()
}
}
const customerLoseFocus = () => {
if (comscanCustomerLabel.value != undefined) {
comscanCustomerLabel.value.losefocus()
}
}
const locationGetFocus = () => {
fromLocationCode.value = ''
locationOnFocus.value = true
}
const showMessage = (message, callback) => {
setTimeout((r) => {
packLoseFocus()
comMessageRef.value.showMessage(message, callback)
})
}
const showErrorMessage = (message, callback) => {
setTimeout((r) => {
packLoseFocus()
comMessageRef.value.showErrorMessage(message, callback)
})
}
//
const emit = defineEmits(['close', 'checkResult'])
defineExpose({
closeScanPopup,
openScanPopupForType,
packGetFocus
})
</script>
<style lang="scss">
.scroll-view {
overflow-y: scroll;
height: auto;
max-height: 300rpx;
}
</style>

318
src/mycomponents/scan/winComScanBalance.vue

@ -0,0 +1,318 @@
<template>
<view>
<u-popup v-model="show" mode="bottom">
<view class="popup_box">
<view class="pop_title uni-flex space-between">
<view class="" style="font-size: 35rpx;">
扫描{{title}}
</view>
<view class="">
<image class="fr icons_scan_close" src="/static/icons/icons_scan_close.svg"
@click="closeScanPopup()"></image>
</view>
</view>
<view class="">
<view class="">
<win-com-scan ref="comscan" :placeholder="title" @getResult="getScanResult"
:isShowHistory="isShowHistory" :clearResult="true" :headerType="headerType"></win-com-scan>
</view>
</view>
</view>
</u-popup>
<balance-select ref="balanceSelectRef" @onSelectItem='selectBalanceItem'></balance-select>
</view>
<comMessage ref="comMessageRef"></comMessage>
</template>
<script setup lang="ts">
import winComScan from '@/mycomponents/scan/winComScan.vue'
import BalanceSelect from '@/mycomponents/balance/balanceSelect.vue'
import {
getBalanceByManagementPrecisionByPacking,
} from '@/common/balance.js';
import {
getBalanceByParams,
getBasicItemByCode,
getBalanceByFilter
} from '@/api/request2.js';
import {
getListLocationAreaTypeDesc,
checkDirectoryItemExist,
getDirectoryItemArray,
getLocationAreaTypeName,
getInventoryStatusDesc,
getListItemTypeDesc,
getItemTypeInfo
} from '@/common/directory.js';
import { ref, onMounted, watch } from 'vue'
const props = defineProps({
title: {
type: String,
default: '箱标签'
},
isShowHistory: {
type: Boolean,
default: false
},
headerType: {
type: String,
default: "HPQ,HMQ"
},
balanceFromInventoryStatuses: { // fromInventoryStatuses
type: Boolean,
default: true
},
bussinessCode: {
type: String,
default: ''
},
verifyCategory: {
type: Boolean,
default: false
},
isCheckLocationBalance: {
type: Boolean,
default: true
}
})
const scanResult = ref({})
const show = ref(false)
const scanList = ref([])
const expand = ref(false)
const expendIcon = ref('arrow-down')
const fromLocationCode = ref('')
const fromLocation = ref('')
const fromLocationList = ref([])
const fromLocationAreaTypeList = ref([])
const toLocationAreaTypeList = ref([])
const businessType = ref({})
const inventoryStatus = ref([])
const fromInventoryStatuses = ref([])
const itemTypesList = ref([])
const resultData = ref({})
const popup = ref(null)
const comMessageRef = ref(null)
const comscan = ref(null)
const balanceSelectRef = ref(null)
//
const openScanPopup = (businessTypeValue) => {
businessType.value = businessTypeValue
fromInventoryStatuses.value = getDirectoryItemArray(businessTypeValue.outInventoryStatuses)
fromLocationAreaTypeList.value = getDirectoryItemArray(businessTypeValue.outAreaTypes)
toLocationAreaTypeList.value = getDirectoryItemArray(businessTypeValue.inAreaTypes)
itemTypesList.value = getDirectoryItemArray(businessTypeValue.itemTypes)
show.value = true
setTimeout(() => {
getfocus()
}, 500)
}
const getScanResult = (result) => {
resultData.value = result
if (!result.package) {
showErrorMessage(result.label.code + "包装信息为空")
return
}
getItemCodeType(result.package.itemCode, () => {
if (props.isCheckLocationBalance) {
queryBalance(resultData.value)
} else {
queryBalance(resultData.value)
}
})
}
const getToLocationBalance = (result) => {
uni.showLoading({
title: '查询中',
mask: true
})
const filters = []
if (result.package.parentNumber) {
const packingNumber = result.package.parentNumber + "," + result.package.number
filters.push({
column: "packingNumber",
action: "in",
value: packingNumber
})
} else {
filters.push({
column: "packingNumber",
action: "==",
value: result.package.number
})
}
filters.push({
column: "itemCode",
action: "==",
value: result.package.itemCode
})
filters.push({
column: "batch",
action: "==",
value: result.package.batch
})
filters.push({
column: "areaType",
action: "in",
value: toLocationAreaTypeList.value.join(',')
})
const params = {
filters: filters,
pageNo: 1,
pageSize: 100,
}
getBalanceByFilter(params).then(res => {
uni.hideLoading()
if (res.data.list.length > 0) {
showErrorMessage("包装在库位【" + res.data.list[0].locationCode + "】已有库存余额")
} else {
queryBalance(resultData.value)
}
}).catch(err => {
showErrorMessage(err.message)
})
}
const queryBalance = (result) => {
const params = {
itemCode: result.package.itemCode,
batch: result.label.batch,
packingNumber: result.label.packingNumber,
parentPackingNumber: result.package.parentNumber,
inventoryStatus: fromInventoryStatuses.value,
areaType: fromLocationAreaTypeList.value,
bussinessCode: props.bussinessCode
}
uni.showLoading({
title: '查询中',
mask: true
})
getBalanceByParams(params).then(res => {
uni.hideLoading()
if (res.data.length === 0) {
const status = getInventoryStatusDesc(params.inventoryStatus)
const areaType = getListLocationAreaTypeDesc(params.areaType)
const hint =
"按物料号 [" + params.itemCode + "] \n" +
"包装号 [" + params.packingNumber + "] \n" +
"批次 [" + params.batch + "] \n" +
"状态 [" + status + "] \n" +
"库区 [" + areaType + "] \n" +
"未查找到库存余额"
showErrorMessage(hint)
} else if (res.data.length === 1) {
result.balance = res.data[0]
if (result.label.packingNumber !== result.balance.packingNumber) {
result.balance.lableQty = result.label.qty
}
emit('getBalance', result)
} else {
balanceSelectRef.value.openPopup(res.data)
}
}).catch(error => {
uni.hideLoading()
showErrorMessage(error)
})
}
const getItemCodeType = (itemCode, callBack) => {
uni.showLoading({
title: "加载中",
mask: true
})
getBasicItemByCode(itemCode).then(res => {
if (res.data && res.data.list.length > 0) {
const result = res.data.list[0]
const status = result.available
const type = result.type
if (status === "TRUE") {
if (checkDirectoryItemExist(itemTypesList.value, type)) {
if (props.verifyCategory) {
if (result.category === 'LCJ' || result.category === 'BJ') {
callBack()
} else {
showErrorMessage("扫描物料的种类不是【量产件】或者【备件】")
}
} else {
callBack()
}
} else {
const hint = getListItemTypeDesc(itemTypesList.value)
uni.hideLoading()
showErrorMessage("扫描物料[" + itemCode + "]是[" +
getItemTypeInfo(type).label + "],需要的物料类型是[" + hint + "]")
}
} else {
uni.hideLoading()
showErrorMessage('物料【' + itemCode + '】不可用')
}
} else {
uni.hideLoading()
showErrorMessage('未查找到物料【' + itemCode + '】')
}
}).catch(error => {
uni.hideLoading()
showErrorMessage(error)
})
}
const showErrorMessage = (message) => {
losefocus()
comMessageRef.value.showErrorMessage(message, res => {
if (res) {
if (comscan.value) {
comscan.value.getfocus()
}
}
})
}
const selectBalanceItem = (item) => {
resultData.value.balance = item
emit('getBalance', resultData.value)
}
const closeScanPopup = () => {
losefocus()
show.value = false
}
const getfocus = () => {
if (comscan.value) {
comscan.value.getfocus()
}
}
const losefocus = () => {
if (comscan.value) {
comscan.value.losefocus()
}
}
const emit = defineEmits(['getBalance'])
defineExpose({
openScanPopup,
closeScanPopup,
getfocus,
losefocus
})
</script>
<style lang="scss">
.scroll-view {
overflow-y: scroll;
height: auto;
max-height: 300rpx;
}
</style>

295
src/mycomponents/scan/winComScanBalanceLocation.vue

@ -0,0 +1,295 @@
<template>
<view>
<u-popup v-model="show" mode="bottom">
<view class="popup_box">
<view class="pop_title uni-flex space-between">
<view class="" style="font-size: 35rpx"> 扫描{{ title }} </view>
<view class="">
<image class="fr icons_scan_close" src="/static/icons/icons_scan_close.svg" @click="closeScanPopup()"></image>
</view>
</view>
<view class="uni-flex uni-row" style="align-items: center; background-color: #fff; margin-left: 20rpx; margin-right: 20rpx; border-radius: 8rpx; height: 30px">
<view class="uni-center" style="width: 25%; font-size: 35rpx"> 来源库位 </view>
<!-- style="width: 75%;padding: 8rpx" -->
<view class="">
<!-- <input v-model="fromLocationCode" placeholder="请扫描来源库位" :focus="locationOnFocus"
placeholder-style="font-size:12px" style="padding: 5px;" @confirm="scanLocation" /> -->
<view v-if="allowModifyLocation">
<uni-combox :candidates="fromLocationList" v-model="fromLocationCode" placeholder="请扫描来源库位" @confirm="handleConfirm" style="height: 30rpx; border: 1px solid #fff"></uni-combox>
</view>
<view v-else>
<text style="padding: 5px; font-size: 40rpx">
{{ fromLocationCode }}
</text>
</view>
</view>
</view>
<view class="">
<view class="">
<win-com-scan ref="comscanRef" :placeholder="title" @getResult="getScanResult" :isShowHistory="isShowHistory" :clearResult="true" :headerType="headerType"></win-com-scan>
</view>
</view>
</view>
</u-popup>
<balance-select ref="balanceSelect" @onSelectItem="selectBalanceItem"></balance-select>
<!-- 模拟扫描功能 -->
</view>
<comMessage ref="comMessageRef"></comMessage>
</template>
<script setup>
import winComScan from '@/mycomponents/scan/winComScan.vue'
import BalanceSelect from '@/mycomponents/balance/balanceSelect.vue'
import { getBalanceByManagementPrecisionByPacking } from '@/common/balance.js'
import { getBalanceByParams, getBasicItemByCode } from '@/api/request2.js'
import { getListLocationAreaTypeDesc, checkDirectoryItemExist, getDirectoryItemArray, getLocationAreaTypeName, getInventoryStatusDesc, getListItemTypeDesc, getItemTypeInfo } from '@/common/directory.js'
import {getLabelInfo} from '@/common/label.js';
import { ref, onMounted, watch } from 'vue';
const props = defineProps({
title: {
type: String,
default: '箱标签'
},
isShowHistory: {
type: Boolean,
default: false
},
headerType: {
type: String,
default: 'HPQ,HMQ'
},
balanceFromInventoryStatuses: {
type: Boolean,
default: true
},
bussinessCode: {
type: String,
default: ''
},
allowModifyLocation: {
type: Boolean,
default: true
}
});
const businessType = ref({});
const fromInventoryStatuses = ref([]);
const fromLocationAreaTypeList = ref([]);
const itemTypesList = ref([]);
const fromLocationCode = ref('');
const fromLocationList = ref([]);
const inventoryStatus = ref([]);
const resultData = ref({});
const show = ref(false)
const comMessageRef = ref(null);
const comscanRef = ref(null);
const openScanPopup = (businessTypeValue) => {
businessType.value = businessTypeValue;
fromInventoryStatuses.value = getDirectoryItemArray(businessTypeValue.outInventoryStatuses);
fromLocationAreaTypeList.value = getDirectoryItemArray(businessTypeValue.outAreaTypes);
itemTypesList.value = getDirectoryItemArray(businessTypeValue.itemTypes);
show.value = true
setTimeout(() => {
packGetFocus();
}, 500);
};
const openScanPopupForJob = (fromLocationCodeValue, fromLocationListValue, jobContent) => {
fromLocationCode.value = fromLocationCodeValue;
fromLocationList.value = fromLocationListValue;
fromInventoryStatuses.value = getDirectoryItemArray(jobContent.outInventoryStatuses);
inventoryStatus.value = getDirectoryItemArray(jobContent.outInventoryStatuses);
fromLocationAreaTypeList.value = getDirectoryItemArray(jobContent.fromAreaTypes);
show.value = true
setTimeout(() => {
if (fromLocationCode.value !== '') {
packGetFocus();
} else {
if (fromLocationList.value.length === 0) {
// locationGetFocus();
} else {
fromLocationCode.value = fromLocationList.value[0];
packGetFocus();
}
}
}, 500);
};
const openScanPopupForJobSimulate = (fromLocationCodeValue, fromLocationListValue, jobContent, scanMessage) => {
fromLocationCode.value = fromLocationCodeValue;
fromLocationList.value = fromLocationListValue;
if (!fromLocationCodeValue) {
if (fromLocationList.value.length === 0) {
alert('没有来源库位:List');
} else {
fromLocationCode.value = fromLocationList.value[0];
}
}
fromInventoryStatuses.value = getDirectoryItemArray(jobContent.outInventoryStatuses);
inventoryStatus.value = getDirectoryItemArray(jobContent.outInventoryStatuses);
fromLocationAreaTypeList.value = getDirectoryItemArray(jobContent.fromAreaTypes);
getLabelInfo(scanMessage, props.headerType, (callback) => {
if (callback.success) {
getScanResult(callback);
} else {
showErrorMessage(callback.message, () => {});
}
});
};
const handleConfirm = () => {
emit('confirm', fromLocationCode.value);
};
const getScanResult = (result) => {
if (fromLocationCode.value === '') {
showErrorMessage('请选择来源库位', () => {});
return;
}
resultData.value = result;
if (!result.package) {
showErrorMessage(`${result.label.code}包装信息为空`);
return;
}
getItemCodeType(result.package.itemCode, () => {
queryBalance(resultData.value);
});
};
const queryBalance = (result) => {
const params = {
locationCode: fromLocationCode.value,
itemCode: result.package.itemCode,
batch: result.label.batch,
packingNumber: result.label.packingNumber,
parentPackingNumber: result.package.parentNumber,
inventoryStatus: fromInventoryStatuses.value,
areaType: fromLocationAreaTypeList.value,
bussinessCode: props.bussinessCode
};
uni.showLoading({
title: '查询中',
mask: true
});
getBalanceByParams(params)
.then((res) => {
uni.hideLoading();
if (res.data.length === 0) {
const status = getInventoryStatusDesc(params.inventoryStatus);
const areaType = getListLocationAreaTypeDesc(params.areaType);
const hint = `按物料号 [${params.itemCode}] \n` +
`包装号 [${params.packingNumber}] \n` +
`批次 [${params.batch}] \n` +
`状态 [${status}] \n` +
`库区 [${areaType}] \n` +
'未查找到库存余额';
showErrorMessage(hint);
} else if (res.data.length === 1) {
result.balance = res.data[0];
if (result.label.packingNumber !== result.balance.packingNumber) {
result.balance.lableQty = result.label.qty;
}
emit('getBalance', result);
} else {
show.value = true
}
})
.catch((error) => {
uni.hideLoading();
showErrorMessage(error);
});
};
const getItemCodeType = (itemCode, callBack) => {
uni.showLoading({
title: '加载中',
mask: true
});
getBasicItemByCode(itemCode)
.then((res) => {
if (res.data != null && res.data.list.length > 0) {
const result = res.data.list[0];
const status = result.available;
const { type } = result;
if (status === 'TRUE') {
if (checkDirectoryItemExist(itemTypesList.value, type)) {
callBack();
} else {
const hint = getListItemTypeDesc(itemTypesList.value);
uni.hideLoading();
showErrorMessage(`扫描物料[${itemCode}]是[${getItemTypeInfo(type).label}],需要的物料类型是[${hint}]`);
}
} else {
uni.hideLoading();
showErrorMessage(`物料【${itemCode}】不可用`);
}
} else {
uni.hideLoading();
showErrorMessage(`未查找到物料【${itemCode}`);
}
})
.catch((error) => {
uni.hideLoading();
showErrorMessage(error);
});
};
const showErrorMessage = (message) => {
packLoseFocus();
comMessageRef.value.showErrorMessage(message, (res) => {
if (res) {
if (comscanRef.value) {
comscanRef.value.getfocus();
}
}
});
};
const selectBalanceItem = (item) => {
resultData.value.balance = item;
emit('getBalance', resultData.value);
};
const closeScanPopup = () => {
packLoseFocus();
show.value = false
emit('onCloseScanPopup');
};
const getfocus = () => {
if (comscanRef.value) {
comscanRef.value.getfocus();
}
};
const packGetFocus = () => {
if (comscanRef.value) {
comscanRef.value.getfocus();
}
};
const packLoseFocus = () => {
if (comscanRef.value) {
comscanRef.value.losefocus();
}
};
const emit = defineEmits(['confirm', 'getBalance', 'onCloseScanPopup']);
</script>
<style lang="scss">
.scroll-view {
overflow-y: scroll;
height: auto;
max-height: 300rpx;
}
</style>

198
src/mycomponents/scan/winComScanCustomerLabel.vue

@ -0,0 +1,198 @@
<!--扫描组件-->
<template>
<!-- <page-meta root-font-size="18px"></page-meta> -->
<view>
<view class="pop_tab">
<view class="tab_info">
<view class="conbox">
<textarea inputmode="none" v-model="scanMsg" trim="all" maxlength="1000" style="margin-left: 5px; width: 90%" :focus="boxfocus" :placeholder="placeholderValue" @focus="getfocus" @blur="losefocus" @input="handelScanMsg" :cursor="cursorIndex"></textarea>
</view>
<view class="uni-flex uni-row space-between u-col-center">
<view class="uni-flex" style="padding: 10px; color: #3c9cff; font-weight: bold; font-size: 15px">
{{ customerItemCode }}
</view>
<view class="uni-flex">
<button class="clean_scan_btn" @click="clearScanValue()">清空</button>
<button class="scan_btn" @click="clickScanMsg()">扫描</button>
</view>
</view>
</view>
</view>
<com-message ref="comMessageRef" />
</view>
</template>
<script setup lang="ts">
import { ref, getCurrentInstance, onMounted, nextTick, watch } from 'vue'
const props = defineProps({
placeholder: {
type: String,
default: '请扫描标签'
},
clearResult: {
type: Boolean,
default: true
},
boxFocus: {
type: Boolean,
default: true
},
isShowHistory: {
type: Boolean,
default: true
},
headerType: {
type: String,
default: 'HPQ' // HLB HMQ HCQ HPQ
}
})
const scanMsg = ref('')
const boxfocus = ref(false)
const placeholderValue = ref('')
const scanResult = ref({})
const scanList = ref([])
const expand = ref(true)
const expendIcon = ref('arrow-down')
const cursorIndex = ref(0)
const customerItemCode = ref('')
const comMessageRef = ref()
onMounted(() => {
boxfocus.value = true
uni.hideKeyboard()
// #ifdef H5
if (document.querySelector('textarea') != null) {
document.querySelector('textarea').setAttribute('inputmode', 'none')
}
// #endif
hide()
})
watch(
() => props.placeholder,
(val) => {
placeholderValue.value = `请扫描${val}`
}
)
placeholderValue.value = props.placeholder
const hide = () => {
// #ifdef APP-PLUS
//
const interval = setInterval(function () {
uni.hideKeyboard() //
console.log('刷新')
}, 5)
setTimeout(() => {
clearInterval(interval)
console.log('停止刷新')
}, 1000)
// #endif
}
const getValue = () => {
return scanMsg.value
}
const setValue = (val) => {
scanMsg.value = val
}
const clearScanValue = () => {
scanMsg.value = ''
getfocus()
}
const clickScanMsg = () => {
scanMsg.value += '\n'
handelScanMsg()
}
const handelScanMsg = () => {
scanMsg.value.replace('\n', '')
const index = scanMsg.value.indexOf('\n')
// if (index >= 0) {
setTimeout(() => {
losefocus()
const content = scanMsg.value.trim()
if (content == '') {
getfocus()
comMessageRef.value.showErrorMessage('扫描内容为空,请重新扫描', (res) => {
if (res) {
scanMsg.value = ''
getfocus()
}
})
return
}
const items = scanMsg.value.split('*')
customerItemCode.value = items[1]
emit('getResult', customerItemCode.value)
}, 500)
// }
}
const getfocus = () => {
nextTick((r) => {
boxfocus.value = true
})
hide()
}
const losefocus = () => {
nextTick((r) => {
boxfocus.value = false
})
}
const clear = () => {
if (props.clearResult) {
cursorIndex.value = 0
scanMsg.value = ''
}
}
const iconClick = (type) => {
emit('clearResult', scanMsgk.value)
}
const expands = () => {
expand.value = !expand.value
expendIcon.value = expand.value == true ? 'arrow-down' : 'arrow-up'
}
const scanClick = () => {
handelScanMsg()
}
const cancelClick = () => {
clear()
getfocus()
}
const showItem = (item) => {
comMessageRef.value.showMessage(item, (res) => {
if (res) {
// this.$refs.modal.cancelClose();
}
})
}
const scanQRCode = () => {
uni.scanCode({
onlyFromCamera: true,
success: (res) => {
scanMsg.value = res.result
emit('getResult', res.result)
},
fail: (res) => {
showItem(`扫描出现错误:${res.result}`)
console.log(`扫描出现错误:${res.result}`)
}
})
}
//
const emit = defineEmits(['clearResult', 'getResult'])
defineExpose({
getfocus,
losefocus
})
</script>
<script module="textarea" lang="renderjs">
export default {
mounted() {
document.querySelector('textarea').setAttribute('inputmode', 'none')
},
}
</script>
<style scoped lang="scss"></style>

299
src/mycomponents/scan/winComScanFg.vue

@ -0,0 +1,299 @@
<!--扫描组件-->
<template>
<!-- <page-meta root-font-size="18px"></page-meta> -->
<view>
<view class="pop_tab">
<view class="tab_info">
<view class="conbox">
<textarea inputmode="none" v-model="scanMsg"
trim="all" maxlength="1000" style="margin-left: 5px; width: 90%"
:focus="boxfocus" :placeholder="placeholderValue"
@focus="handleFocus" @input="handelScanMsg" :cursor="cursorIndex">
</textarea>
</view>
<view class="uni-flex uni-row space-between u-col-center">
<view class="uni-flex">
<button class="clean_scan_btn" @touchend.prevent="clearScanValue()">清空</button>
<button class="scan_btn" @click="clickScanMsg()">扫描</button>
</view>
</view>
</view>
<view style="width: 100%">
<view style="width: 100%" v-if="scanList.length > 0 && isShowHistory">
<view class="uni-flex uni-row space-between u-col-center">
<view class="" style="padding: 10rpx"> 历史记录 </view>
<view class="" style="padding-right: 10rpx">
<u-icon :name="expendIcon" size="35rpx" @click="expands()"></u-icon>
</view>
</view>
<u-line class="line_color" style="padding-top: 10rpx; padding-bottom: 20rpx"></u-line>
<scroll-view scroll-y="true" class="scroll-view" v-if="expand && scanList.length > 0" style="height: 70px">
<view class="uni-flex u-col" v-for="(item, index) in scanList" :key="index">
<view style="width: 100%; max-height: 100px">
<view class="uni-flex u-row space-between u-col-center" @click="showItem(item)">
<view class="text_ellipsis" style="padding: 15rpx">
{{ item }}
</view>
<view class="">
<u-icon name="arrow-right"></u-icon>
</view>
</view>
<u-line class="line_color"></u-line>
</view>
</view>
</scroll-view>
</view>
</view>
</view>
<com-message ref="comMessageRef" />
</view>
</template>
<script setup lang="ts">
import { ref, getCurrentInstance, onMounted, nextTick, watch } from 'vue'
import { getLabelInfo } from '../../common/label.js'
import { getMesPackInfo } from '@/api/request2.js'
const { proxy } = getCurrentInstance()
const props = defineProps({
placeholder: {
type: String,
default: '请扫描标签'
},
clearResult: {
type: Boolean,
default: true
},
boxFocus: {
type: Boolean,
default: true
},
isShowHistory: {
type: Boolean,
default: true
},
headerType: {
type: String,
default: 'HPQ' // HLB HMQ HCQ HPQ
}
})
const scanMsg = ref('')
const boxfocus = ref(false)
const placeholderValue = ref('')
const scanResult = ref({})
const scanList = ref([])
const expand = ref(true)
const expendIcon = ref('arrow-down')
const cursorIndex = ref(0)
const itemCode = ref('')
const comMessageRef = ref()
onMounted(() => {
boxfocus.value = true
// uni.hideKeyboard()
// #ifdef H5
// if (document.querySelector('textarea') != null) {
// document.querySelector('textarea').setAttribute('inputmode', 'none')
// }
// #endif
// hide()
placeholderValue.value = `请扫描${props.placeholder}`
})
watch(
() => props.placeholder,
() => {
placeholderValue.value = `请扫描${placeholder.value}`
}
)
const handleFocus = () => {}
const setItemCodeSimulate = (itemCode, scanMsg) => {
itemCode.value = itemCode
scanMsg.value = scanMsg
}
const setItemCode = (itemCodeParams) => {
itemCode.value = itemCodeParams
}
const getValue = () => {
return scanMsg.value
}
const setValue = (val) => {
scanMsg.value = val
}
const clearScanValue = () => {
cursorIndex.value = 0
scanMsg.value = ''
getfocus()
}
const clickScanMsg = () => {
scanMsg.value += '\n'
handelScanMsg()
}
const handelScanMsg = () => {
const index = scanMsg.value.indexOf('\n')
if (index >= 0) {
setTimeout(() => {
losefocus()
// let content = uni.$u.trim(that.scanMsg)
const content = scanMsg.value.trim()
// let content = that.scanMsg;
if (content == '') {
comMessageRef.value.showErrorMessage('扫描内容为空,请重新扫描', (res) => {
if (res) {
scanMsg.value = ''
getfocus()
}
})
return
}
if (proxy.isShowHistory) {
scanList.value.unshift(content)
}
console.log('扫描长度', content.length)
getMesPackInfo(itemCode.value)
.then((res) => {
try {
if (res.data.list.length == 0) {
clear()
throw new Error(`没有查找到物料号【${itemCode.value}】对应的生产条码配置`)
}
const result = res.data.list[0] // Mes
const { partNumber } = result //
const { lengthMat } = result
const { lengthBc } = result
// Q5,,typeQ5
if (result.type == 'P') {
const scanPartNumber = content.substr(0, lengthMat) //
// const productDate = content.substr(lengthMat, 8)
// const batch = content.substr(lengthMat + 8, 3)
const order = content.substr(-8)
if (content.length != lengthBc) {
clear();
throw new Error("解析错误:扫描标签长度与配置条码的长度不一致")
}
if (scanPartNumber != partNumber) {
clear()
throw new Error(`解析错误:扫描的客户物料号【${scanPartNumber}】与生成条码配置表中的客户物料号【${partNumber}】不一致`)
}
const scanResult = {
itemCode: scanPartNumber,
// productDate,
// batch,
order,
qty: 1,
content,
success: true
}
clear()
emit('getResult', scanResult)
} else {
// ,
const scanResult = {
itemCode: itemCode.value,
// productDate: new Date(),
// batch: new Date(),
order: 0,
qty: 1,
content,
success: true
}
clear()
emit('getResult', scanResult)
}
} catch (error) {
losefocus()
comMessageRef.value.showErrorMessage(error.message, (res) => {
if (res) {
getfocus()
}
})
}
})
.catch((error) => {
losefocus()
comMessageRef.value.showErrorMessage(error, (res) => {
if (res) {
scanMsg.value = ''
getfocus()
}
})
})
}, 500)
}
}
const getfocus = () => {
nextTick((r) => {
boxfocus.value = true
})
hide()
}
const losefocus = () => {
nextTick((r) => {
boxfocus.value = false
})
}
const clear = () => {
cursorIndex.value = 0
scanMsg.value = ''
}
const iconClick = (type) => {
emit('clearResult', scanMsg.value)
}
const expands = () => {
expand.value = !expand.value
expendIcon.value = expand.value == true ? 'arrow-down' : 'arrow-up'
}
const scanClick = () => {
handelScanMsg()
}
const cancelClick = () => {
clear()
getfocus()
}
const showItem = (item) => {
comMessageRef.value.showMessage(item, (res) => {
if (res) {
}
})
}
const scanQRCode = () => {
uni.scanCode({
onlyFromCamera: true,
success: (res) => {
scanMsg.value = res.result
emit('getResult', res.result)
console.log(`扫描二维码成功,结果:${res.result}`)
},
fail: (res) => {
showItem(`扫描出现错误:${res.result}`)
}
})
}
//
const emit = defineEmits(['getResult', 'clearResult'])
defineExpose({
getfocus,
handelScanMsg,
clearScanValue,
clear,
clickScanMsg,
losefocus,
setItemCode
})
</script>
<script module="textarea" lang="renderjs">
export default {
mounted() {
document.querySelector('textarea').setAttribute('inputmode', 'none')
},
}
</script>
<style scoped lang="scss"></style>

100
src/mycomponents/scan/winScanFgLabel.vue

@ -0,0 +1,100 @@
<template>
<view>
<u-popup v-model="show" mode="bottom" :mask-close-able="false">
<view class="popup_box">
<view class="pop_title uni-flex space-between">
<view class="" style="font-size: 35rpx"> 扫描{{ title }} </view>
<view class="">
<image class="fr icons_scan_close" src="/static/icons/icons_scan_close.svg" @click="closeScanPopup()"></image>
</view>
</view>
<view class="">
<view class="">
<win-com-scan-fg ref="comscan" :placeholder="title" @getResult="getScanResult" :isShowHistory="isShowHistory" :clearResult="true"></win-com-scan-fg>
</view>
</view>
</view>
</u-popup>
<com-message ref="comMessageRef" @afterClose="getfocus" />
</view>
</template>
<script setup lang="ts">
import { ref, getCurrentInstance, onMounted, nextTick, watch } from 'vue'
import winComScanFg from '@/mycomponents/scan/winComScanFg.vue'
const props = defineProps({
title: {
type: String,
default: '成品标签'
},
isShowHistory: {
type: Boolean,
default: true
}
})
const show = ref(false)
const comscan = ref()
const comscansimulate = ref()
const openScanPopup = (itemCode) => {
show.value = true
setTimeout((res) => {
setTimeout((re) => {
comscan.value.setItemCode(itemCode)
}, 500)
getfocus()
}, 200)
}
const closeScanPopup = () => {
show.value = false
emit('close', '')
}
const scanClick = () => {
comscan.value.clickScanMsg()
}
const cancelClick = () => {
comscan.value.clearScanValue()
}
const getScanResult = (result) => {
if (result.success) {
emit('getResult', result)
} else {
showMessage(result.message)
}
}
const getfocus = () => {
if (comscan.value != undefined) {
comscan.value.getfocus()
}
}
const losefocus = () => {
if (comscan.value) {
comscan.value.losefocus()
}
}
const showMessage = (message) => {
comMessageRef.value.showMessage(message)
}
//
const emit = defineEmits(['getResult', 'close'])
defineExpose({
openScanPopup,
closeScanPopup,
losefocus,
getfocus,
})
</script>
<style lang="scss">
.scroll-view {
overflow-y: scroll;
height: auto;
max-height: 300rpx;
}
</style>

271
src/mycomponents/scan/winScanPackAndLocationNoBalance.vue

@ -0,0 +1,271 @@
<template>
<view>
<u-popup v-model="show" mode="bottom" :mask-close-able="false">
<view class="popup_box">
<view class="pop_title uni-flex space-between">
<view class="" style="font-size: 35rpx"> 扫描{{ title }} </view>
<view class="">
<image class="fr icons_scan_close" src="/static/icons/icons_scan_close.svg" @click="closeScanPopup()"></image>
</view>
</view>
<view class="uni-flex uni-row" style="align-items: center; background-color: #fff; margin-left: 20rpx; margin-right: 20rpx; border-radius: 8rpx; height: 30px">
<view class="uni-center" style="width: 25%"> 来源库位 </view>
<!-- style="width: 75%;padding: 8rpx" -->
<view class="">
<!-- <input v-model="fromLocationCode" placeholder="请扫描来源库位" :focus="locationOnFocus"
placeholder-style="font-size:12px" style="padding: 5px;" @confirm="scanLocation" /> -->
<view v-if="allowModifyLocation">
<uni-combox :candidates="fromLocationList" v-model="fromLocationCode" placeholder="请扫描来源库位" style="height: 30rpx; border: 1px solid #fff"></uni-combox>
</view>
<view v-else>
<text style="padding: 5px">
{{ fromLocationCode }}
</text>
</view>
</view>
</view>
<view class="">
<view class="">
<win-com-scan ref="comscan" :placeholder="title" @getResult="getScanResult" :isShowHistory="isShowHistory" :clearResult="true" :headerType="headerType"></win-com-scan>
</view>
</view>
</view>
</u-popup>
<!-- <balance-select ref="balanceSelectRef" @onSelectItem='selectBalanceItem'></balance-select> -->
</view>
<com-message ref="comMessageRef" />
</template>
<script setup lang="ts">
import { ref, getCurrentInstance, onMounted, nextTick, watch } from 'vue'
import winComScan from '@/mycomponents/scan/winComScan.vue'
import BalanceSelect from '@/mycomponents/balance/balanceSelect.vue'
import { getBalanceByManagementPrecision } from '@/common/balance.js'
import { getBasicLocationByCode } from '@/api/request2.js'
import { getListLocationTypeDesc, checkDirectoryItemExist, getDirectoryItemArray, getLocationTypeName, getInventoryStatusDesc } from '@/common/directory.js'
const { proxy } = getCurrentInstance()
const props = defineProps({
title: {
type: String,
default: '箱标签'
},
isShowHistory: {
type: Boolean,
default: true
},
allowNullBalance: {
type: Boolean,
default: false
},
//
noShowBalanceMessage: {
type: Boolean,
default: false
},
//
allowModifyLocation: {
type: Boolean,
default: true
},
headerType: {
type: String,
default: 'HPQ,HMQ'
}
})
const scanResult = ref({})
const show = ref(false)
const scanList = ref([])
const expand = ref(false)
const showScanResult = ref({})
const expendIcon = ref('arrow-down')
const fromLocationCode = ref('')
const fromLocation = ref('')
const fromLocationList = ref([])
const fromLocationTypeArray = ref([])
const locationOnFocus = ref(false)
const businessType = ref({})
const inventoryStatus = ref([])
const managementPrecision = ref('')
const fromInventoryStatuses = ref('')
const isCheck = ref(false)
const balanceSelectRef = ref()
const comscan = ref()
const comMessageRef = ref()
//
const openScanPopupForType = (fromLocationCodeParms, businessTypeParms) => {
businessType.value = businessTypeParms
fromLocationCode.value = fromLocationCodeParms
fromInventoryStatuses.value = getDirectoryItemArray(businessType.value.outInventoryStatuses)
inventoryStatus.value = getDirectoryItemArray(businessType.value.outInventoryStatuses) //
fromLocationTypeArray.value = getDirectoryItemArray(businessType.value.outLocationTypes) //
show.value = true
setTimeout((res) => {
if (fromLocationCodeParms != '') {
packGetFocus()
} else {
locationGetFocus()
}
}, 500)
}
//
const openScanPopupForJob = (fromLocationCodeParms, fromLocationListParms, jobContent) => {
fromLocationCode.value = fromLocationCodeParms
fromLocationList.value = fromLocationListParms
fromInventoryStatuses.value = getDirectoryItemArray(jobContent.outInventoryStatuses)
inventoryStatus.value = getDirectoryItemArray(jobContent.outInventoryStatuses) // 出库库存状态; //出库库存状态
fromLocationTypeArray.value = getDirectoryItemArray(jobContent.fromLocationTypes) //
show.value = true
setTimeout((res) => {
if (fromLocationListParms != '') {
packGetFocus()
} else if (fromLocationList.value.length == 0) {
locationGetFocus()
} else {
fromLocationCode.value = fromLocationList.value[0]
packGetFocus()
}
}, 500)
}
const closeScanPopup = (content) => {
packLoseFocus()
show.value = false
emit('close', '')
}
const getScanResult = (scanResult) => {
scanResult.value = scanResultParams
const isCheck = false
if (fromLocationCode.value == '') {
showErrorMessage('来源库位不能为空', (callback) => {
locationGetFocus()
})
return
}
if (fromLocationList.value.length > 0) {
if (!isInLocationList(fromLocationCode.value)) {
showErrorMessage(`扫描库位【${fromLocationCode.value}】不在任务来源库位中`, (callback) => {
locationGetFocus()
})
return
}
}
uni.showLoading({
title: '扫描中...',
mask: true
})
getBasicLocationByCode(fromLocationCode.value)
.then((res) => {
if (res.data.total > 0) {
const result = res.data.list[0]
if (result.code != fromLocationCode.value) {
showErrorMessage(`未查询到库位[${fromLocationCode.value}]`)
return
}
const { type } = result
const { available } = result
if (available == 'TRUE') {
if (checkDirectoryItemExist(fromLocationTypeArray.value, type)) {
location.value = result
packCallBack()
} else {
uni.hideLoading()
const hint = getListLocationTypeDesc(fromLocationTypeArray.value)
showErrorMessage(`库位[${fromLocationCode.value}]是${getLocationTypeName(type)},\n需要的库位类型是[${hint}]`, (callback) => {
locationGetFocus()
})
}
} else {
showErrorMessage(`扫描库位[${fromLocationCode.value}]不可用`, (res) => {
locationGetFocus()
})
}
uni.hideLoading()
} else {
uni.hideLoading()
showErrorMessage(`未查询到库位[${fromLocationCode.value}]`, (res) => {
locationGetFocus()
})
}
})
.catch((error) => {
uni.hideLoading()
showErrorMessage(error, (res) => {
locationGetFocus()
})
})
}
const packCallBack = (item) => {
comscan.value.clear()
//
const data = {
label: scanResult.value.label,
package: scanResult.value.package,
balance: null,
fromLocationCode: fromLocationCode.value
}
packGetFocus()
emit('getResult', data)
}
const packGetFocus = () => {
if (comscan.value != undefined) {
comscan.value.getfocus()
}
}
const packLoseFocus = () => {
if (comscan.value != undefined) {
comscan.value.getfocus()
}
}
const locationGetFocus = () => {
fromLocationCode.value = ''
locationOnFocus.value = true
}
const showMessage = (message, callback) => {
setTimeout((r) => {
packLoseFocus()
comMessageRef.value.showMessage(message, callback)
})
}
const showErrorMessage = (message, callback) => {
setTimeout((r) => {
packLoseFocus()
comMessageRef.value.showErrorMessage(message, callback)
})
}
const isInLocationList = (location) => {
let item = fromLocationList.value.find((res) => res == location)
if ((item = undefined)) {
return false
}
return true
}
const addLocationCode = (code) => {
if (!isInLocationList(code)) {
fromLocationList.value.push(code)
}
}
//
const emit = defineEmits(['close', 'getCountScanResult', 'getResult'])
defineExpose({ packGetFocus, packLoseFocus, openScanPopupForJob })
</script>
<style lang="scss">
.scroll-view {
overflow-y: scroll;
height: auto;
max-height: 300rpx;
}
</style>

110
src/mycomponents/scan/winScanPackJob.vue

@ -0,0 +1,110 @@
<template>
<u-popup v-model="show" mode="bottom">
<view class="popup_box">
<view class="pop_title uni-flex space-between">
<view class="" style="font-size: 35rpx"> 扫描{{ title }} </view>
<view class="">
<image class="fr icons_scan_close" src="/static/icons/icons_scan_close.svg" @click="closeScanPopup()"></image>
</view>
</view>
<view class="">
<view class="">
<win-com-scan ref="comscan" :placeholder="title" @getResult="getScanResult" :isShowHistory="isShowHistory" :clearResult="true" :headerType="headerType"></win-com-scan>
</view>
</view>
</view>
</u-popup>
<com-message ref="comMessageRef" />
</template>
<script setup lang="ts">
import { ref, getCurrentInstance, nextTick } from 'vue'
import winComScan from '@/mycomponents/scan/winComScan.vue'
import { getBalanceByManagementPrecision } from '@/common/balance.js'
import { getPutawayJobList } from '@/api/request2.js'
import { getListLocationTypeDesc, checkDirectoryItemExist, getDirectoryItemArray, getLocationTypeName, getInventoryStatusDesc } from '@/common/directory.js'
const props = defineProps({
title: {
type: String,
default: '箱标签'
},
isShowHistory: {
type: Boolean,
default: true
},
headerType: {
type: String,
default: 'HPQ,HMQ'
}
})
const comscan = ref()
const comMessageRef = ref(null)
const show = ref(false)
//
const openScanPopup = () => {
setTimeout(()=>{
show.value = true
packGetFocus()
},500)
}
//
const closeScanPopup = (content) => {
show.value = false
packLoseFocus()
emit('close', '')
}
//
const getScanResult = (result) => {
emit('getResult', result)
}
const packGetFocus = () => {
if (comscan.value) {
comscan.value.getfocus()
}
}
const packLoseFocus = () => {
if (comscan.value) {
comscan.value.losefocus()
}
}
const showMessage = (message, callback) => {
setTimeout((r) => {
packLoseFocus()
comMessageRef.value.showMessage(message, callback)
})
}
const showErrorMessage = (message, callback) => {
setTimeout((r) => {
packLoseFocus()
comMessageRef.value.showMessage(message, callback)
})
}
const change = (e) => {
show.value = e.show
}
const selectItem = (item, index) => {}
const emit = defineEmits(['getResult', 'close', 'getCountScanResult'])
defineExpose({
openScanPopup,
closeScanPopup,
packLoseFocus,
packGetFocus
})
</script>
<style lang="scss">
.scroll-view {
overflow-y: scroll;
height: auto;
max-height: 300rpx;
}
</style>

156
src/mycomponents/scan/winScanPackLevel.vue

@ -0,0 +1,156 @@
<template>
<view>
<u-popup v-model="show" mode="bottom">
<view class="popup_box">
<view class="pop_title uni-flex space-between">
<view class="" style="font-size: 35rpx"> 扫描{{ title }}</view>
<view class="">
<image class="fr icons_scan_close" src="/static/icons/icons_scan_close.svg" @click="closeScanPopup()">
</image>
</view>
</view>
<view class="uni-flex uni-row"
style="align-items: center; background-color: #fff; margin-left: 20rpx; margin-right: 20rpx; border-radius: 8rpx">
<view class="uni-center" style="width: 25%; font-size: 32rpx; font-weight: bold"> 优先级</view>
<view style="width: 100%">
<uni-data-select style="padding: 20rpx;" v-model="priorityCode" :localdata="priorityList" @change="change"
:clear="false"></uni-data-select>
</view>
</view>
<view class="">
<view class="">
<win-com-scan ref="comscan" :placeholder="title" @getResult="getScanResult" :headerType="headerType"
:isShowHistory="isShowHistory" :clearResult="true"></win-com-scan>
</view>
</view>
</view>
</u-popup>
<com-message ref="comMessageRef"/>
</view>
</template>
<script setup lang="ts">
import {ref, getCurrentInstance, nextTick} from 'vue'
import {onLoad, onNavigationBarButtonTap, onPullDownRefresh} from '@dcloudio/uni-app'
import {getLabelInfo} from '@/common/label.js'
import winComScan from '@/mycomponents/scan/winComScan.vue'
const props = defineProps({
title: {
type: String,
default: '箱标签'
},
isShowHistory: {
type: Boolean,
default: true
},
headerType: {
type: String,
default: 'HPQ'
}
})
const emit = defineEmits(['close'])
const show = ref(false)
const comMessageRef = ref(null)
const priorityList = ref([
{
value: 0,
text: '低'
},
{
value: 1,
text: '中'
},
{
value: 2,
text: '高'
}
])
const priorityCode = ref(1)
const comscan = ref()
const simulateScan = (scanMessage) => {
getLabelInfo(scanMessage, headerType.value, (callback) => {
if (callback.success) {
getScanResult(callback)
} else {
showMessage(callback.message)
}
})
}
const openScanPopup = () => {
setTimeout((res) => {
show.value = true
getfocus()
}, 500)
}
const closeScanPopup = () => {
losefocus()
show.value = false
emit('close', '')
}
const scanClick = () => {
if (comscan.value) {
comscan.value.clickScanMsg()
}
}
const cancelClick = () => {
if (comscan.value) {
comscan.value.clearScanValue()
}
}
const getScanResult = (result) => {
if (result.success) {
result.priorityCode = priorityCode.value
emit('getResult', result)
} else {
showMessage(result.message)
}
}
const getfocus = () => {
if (comscan.value) {
comscan.value.getfocus()
}
}
const losefocus = () => {
if (comscan.value) {
comscan.value.losefocus()
}
}
const showMessage = (message) => {
comMessageRef.value.showMessage(message)
}
const change = (e) => {
console.log(e)
}
defineExpose({
simulateScan,
openScanPopup,
closeScanPopup,
scanClick,
cancelClick,
getScanResult,
getfocus,
losefocus,
showMessage,
change
})
</script>
<style lang="scss">
.scroll-view {
overflow-y: scroll;
height: auto;
max-height: 300rpx;
}
</style>

265
src/mycomponents/scan/winScanPackage.vue

@ -0,0 +1,265 @@
<template>
<view>
<u-popup v-model="show" mode="bottom" :mask-close-able="false">
<view class="popup_box">
<view class="pop_title uni-flex space-between">
<view class="" style="font-size: 35rpx"> 扫描{{ title }} </view>
<view class="">
<image class="fr icons_scan_close" src="/static/icons/icons_scan_close.svg" @click="closeScanPopup()"></image>
</view>
</view>
<view class="">
<view class="">
<win-com-scan ref="comscan" :placeholder="title" @getResult="getScanResult" :headerType="headerType" :isShowHistory="isShowHistory" :clearResult="true"></win-com-scan>
</view>
</view>
</view>
</u-popup>
<!-- 模拟扫描功能 -->
<win-com-scan v-show="false" ref="comscansimulate" @getResult="getScanResult" :headerType="headerType" :isShowHistory="false" :clearResult="true"></win-com-scan>
<com-message ref="comMessageRef" />
</view>
</template>
<script setup lang="ts">
import { ref, getCurrentInstance, onMounted, nextTick, watch } from 'vue'
import winComScan from '@/mycomponents/scan/winComScan.vue'
import { getBalanceByFilter } from '@/api/request2.js'
import {
getInventoryStatusDesc,
getDirectoryItemArray,
getLocationAreaTypeName
} from '@/common/directory.js';
const props = defineProps({
title: {
type: String,
default: '箱标签'
},
isShowHistory: {
type: Boolean,
default: true
},
headerType: {
type: String,
default: 'HPQ,HMQ'
}
})
const show = ref(false)
const comscansimulate = ref()
const comscan = ref()
const comMessageRef = ref()
const businessType = ref(null)
const scanResult = ref({})
const simulateScan = (item) => {
comscansimulate.value.setItemCodeSimulate(item.copyContent)
comscansimulate.value.clickScanMsg()
}
const openScanPopup = () => {
setTimeout((res) => {
show.value = true
getfocus()
}, 500)
}
const closeScanPopup = () => {
losefocus()
show.value = false
emit('close', '')
}
const openScanPopupByBusinessType = (businessTypeParams) => {
show.value = false
setTimeout((res) => {
getfocus()
businessType.value = businessTypeParams
}, 500)
}
const scanClick = () => {
if (comscan.value) {
comscan.value.clickScanMsg()
}
}
const cancelClick = () => {
if (comscan.value) {
comscan.value.clearScanValue()
}
}
const getScanResult = (result) => {
if (result.success) {
scanResult.value = result
getBalance(result, (res) => {
result.balance = res
emit('getResult', result)
})
} else {
showMessage(result.message)
}
}
const getParams = (label)=> {
let filters = [{
column: "itemCode",
action: "==",
value: label.itemCode
}, {
column: "batch",
action: "==",
value: label.batch
}];
if (businessType.value.outInventoryStatuses != null) {
filters.push({
column: "inventoryStatus",
action: "in",
value: businessType.value.outInventoryStatuses
})
}
if (businessType.value.outAreaTypes != null){
filters.push({
column: "areaType",
action: "in",
value: businessType.value.outAreaTypes
})
}
if (businessType.value.outAreaCodes != null){
filters.push({
column: "areaCode",
action: "in",
value: businessType.value.outAreaCodes
})
}
return filters;
}
const getQueryCondition = ()=> {
let condition = '按照以下条件:\n';
let label = scanResult.value.label;
let status = getInventoryStatusDesc(getDirectoryItemArray(businessType.value.outInventoryStatuses));
let areaType = getLocationAreaTypeName(businessType.value.outAreaTypes)
condition = condition + '物料号=[' + label.itemCode
+ ']\n箱码=[' + label.packingNumber +
']\n批次=[' +
label.batch +
']'
if (status) {
condition = condition + '\n库存状态=[' + status + ']'
}
if (areaType) {
condition = condition + '\n库区类型=[' + areaType + ']'
}
if (businessType.value.outAreaCodes) {
condition = condition + '\n库区代码=[' + businessType.value.outAreaCodes + ']'
}
return condition;
}
const getBalance = (result, callback) => {
let filters = []
const { label } = result
const packageInfo = result.package
let comfilters = getParams(label);
if (packageInfo.parentNumber) {
const packingNumber = `${packageInfo.parentNumber},${label.packingNumber}`
filters.push({
column: 'packingNumber',
action: 'in',
value: packingNumber
})
} else {
filters.push({
column: 'packingNumber',
action: '==',
value: label.packingNumber
})
}
filters = filters.concat(comfilters);
filters.push({
column: 'itemCode',
action: '==',
value: label.itemCode
})
const params = {
filters,
pageNo: 1,
pageSize: 100
}
getBalanceByFilter(params)
.then((res) => {
if (res.data.list.length > 0) {
res.data.list.forEach(r => {
if (packageInfo.parentNumber) {
r.parentPackingNumber = packageInfo.parentNumber
} else {
r.parentPackingNumber = packageInfo.number
}
})
callback(res.data.list)
} else {
//
if (packageInfo.subList.length > 0) {
let packparams = '';
packageInfo.subList.forEach(pack => {
packparams = packparams + pack.number + ','
})
packparams = packparams.trimEnd(',');
filters = [];
filters.push({
column: "packingNumber",
action: "in",
value: packparams
})
filters = filters.concat(comfilters);
params.filters = filters;
getBalanceByFilter(params).then(res1 => {
if (res1.data.list.length == 0) {
showErrorMessage(getQueryCondition()+'\n未查找到该包装的库存余额')
} else {
res1.data.list.forEach(r => r.parentPackingNumber = packageInfo.number)
callback(res1.data.list)
}
}).catch(err => {
this.showErrorMessage(err.message);
})
} else {
showErrorMessage(getQueryCondition()+'\n未查找到该包装的库存余额')
}
}
})
.catch((err) => {
showErrorMessage(err.message)
})
}
const getfocus = () => {
if (comscan.value) {
comscan.value.getfocus()
}
}
const losefocus = () => {
if (comscan.value) {
comscan.value.losefocus()
}
}
const showMessage = (message) => {
comMessageRef.value.showMessage(message)
}
const showErrorMessage = (message) => {
losefocus()
comMessageRef.value.showErrorMessage(message, (res) => {
if (res) {
getfocus()
}
})
}
//
const emit = defineEmits(['getResult'])
</script>
<style lang="scss">
.scroll-view {
overflow-y: scroll;
height: auto;
max-height: 300rpx;
}
</style>

224
src/mycomponents/scan/winScanParentPackage.vue

@ -0,0 +1,224 @@
<template>
<view>
<u-popup v-model="show" @change="change" :mask-close-able="false">
<view class="popup_box">
<view class="pop_title uni-flex space-between">
<view class="" style="font-size: 35rpx;">
扫描{{title}}
</view>
<view class="">
<image class="fr icons_scan_close" src="/static/icons/icons_scan_close.svg"
@click="closeScanPopup()"></image>
</view>
</view>
<view class="">
<view class="">
<win-com-scan ref="comscan" :placeholder="title" @getResult="getScanResult"
:headerType="headerType" :isShowHistory="isShowHistory" :clearResult="true"></win-com-scan>
</view>
</view>
</view>
</u-popup>
<!-- 模拟扫描功能 -->
<win-com-scan v-show="false" ref="comscansimulate" @getResult="getScanResult" :headerType="headerType"
:isShowHistory="false" :clearResult="true"></win-com-scan>
<comMessage ref="comMessageRef" @afterClose="getfocus"></comMessage>
</view>
</template>
<script setup>
import winComScan from '@/mycomponents/scan/winComScan.vue'
import {
getBalanceByFilter
} from '@/api/request2.js';
import { ref, onMounted } from 'vue';
const props = defineProps({
title: {
type: String,
default: '箱标签'
},
isShowHistory: {
type: Boolean,
default: true
},
headerType: {
type: String,
default: 'HPQ,HMQ'
}
});
const show = ref(false);
const businessType = ref(null);
const comscansimulate = ref(null);
const comscan = ref(null);
const comMessageRef = ref(null);
const simulateScan = (item) => {
comscansimulate.value.setItemCodeSimulate(item.copyContent);
comscansimulate.value.clickScanMsg();
};
const openScanPopup = () => {
show.value = true
setTimeout(() => {
getfocus();
}, 500);
};
const openScanPopupByBusinessType = (businessType) => {
show.value = true
setTimeout(() => {
getfocus();
businessType.value = businessType;
}, 500);
};
const closeScanPopup = () => {
losefocus();
show.value = false
emit("close", '');
};
const scanClick = () => {
if (comscan.value) {
comscan.value.clickScanMsg();
}
};
const cancelClick = () => {
if (comscan.value) {
comscan.value.clearScanValue();
}
};
const getScanResult = (result) => {
if (result.success) {
getBalance(result, (res) => {
result.balance = res;
emit("getResult", result);
});
} else {
showMessage(result.message);
}
};
const getParams = (label) => {
let filters = [
{ column: "itemCode", action: "==", value: label.itemCode },
{ column: "batch", action: "==", value: label.batch }
];
if (businessType.value?.outInventoryStatuses) {
filters.push({ column: "inventoryStatus", action: "in", value: businessType.value.outInventoryStatuses });
}
if (businessType.value?.outAreaTypes) {
filters.push({ column: "areaType", action: "in", value: businessType.value.outAreaTypes });
}
if (businessType.value?.outAreaCodes) {
filters.push({ column: "areaCode", action: "in", value: businessType.value.outAreaCodes });
}
return filters;
};
const getBalance = (result, callback) => {
let filters = [];
let packageInfo = result.package;
let comfilters = getParams(packageInfo);
let balance = { parentBalance: {}, childBalance: [] };
let parentPackingNumber = packageInfo.parentNumber;
let childPackingNumber = packageInfo.number;
if (parentPackingNumber) {
let packingNumber = parentPackingNumber + "," + childPackingNumber;
filters.push({ column: "packingNumber", action: "in", value: packingNumber });
} else {
filters.push({ column: "packingNumber", action: "==", value: childPackingNumber });
}
filters = filters.concat(comfilters);
const params = { filters, pageNo: 1, pageSize: 100 };
getBalanceByFilter(params).then((res) => {
res.data.list.forEach((r) => {
if (packageInfo.parentNumber) {
r.parentPackingNumber = parentPackingNumber;
} else {
r.parentPackingNumber = childPackingNumber;
}
});
if (packageInfo.subList.length > 0) {
let packparams = packageInfo.subList.map((pack) => pack.number).join(',');
filters = [{ column: "packingNumber", action: "in", value: packparams }];
filters = filters.concat(comfilters);
params.filters = filters;
getBalanceByFilter(params).then((res1) => {
if (res1.data.list.length === 0) {
showErrorMessage('未查找到该包装的库存余额', () => packGetFocus());
} else {
res1.data.list.forEach((r) => r.parentPackingNumber = childPackingNumber);
balance.parentBalance = res.data.list.filter((r) => r.packingNumber === childPackingNumber);
balance.childBalance = res1.data.list;
callback(balance);
}
}).catch((err) => {
showErrorMessage(err.message);
});
} else {
balance.childBalance = res.data.list.filter((r) => r.packingNumber === childPackingNumber);
balance.parentBalance = res.data.list.filter((r) => r.packingNumber === parentPackingNumber);
callback(balance);
}
}).catch((err) => {
showErrorMessage(err.message);
});
};
const getfocus = () => {
if (comscan.value) {
comscan.value.getfocus();
}
};
const losefocus = () => {
if (comscan.value) {
comscan.value.losefocus();
}
};
const showMessage = (message) => {
comMessageRef.value.showMessage(message);
};
const change = (e) => {
show.value = e.show;
};
const showErrorMessage = (message) => {
losefocus();
comMessageRef.value.showErrorMessage(message, (res) => {
if (res) {
getfocus();
}
});
};
const emit = defineEmits(['close', 'getResult']);
</script>
<style lang="scss">
.scroll-view {
overflow-y: scroll;
height: auto;
max-height: 300rpx;
}
</style>

195
src/pages/check/checkFgLabel.vue

@ -0,0 +1,195 @@
<template>
<view class="page-wraper">
<view class="">
<com-blank-view @goScan="showFromLocationPopup" v-if="customerCode == ''" title="选择用户"></com-blank-view>
</view>
<view class="page-wraper" v-if="customerCode != ''">
<view class="page-header">
<view class="header_item"> 客户代码 : {{ customerCode }} </view>
<!-- <view class='split_line'></view> -->
</view>
<view class="page-main">
<scroll-view scroll-y="true" class="page-main-scroll">
<view :class="[item.pass ? 'scan_view' : 'refuse_view']" v-for="(item, index) in list" :key="index">
<view class="card_view">
<text class="card_packing_code card_content">箱码</text>
<text class="card_content">{{ item.packingNumber }}</text>
</view>
<view class="card_view">
<text class="card_batch card_content" style="padding-left: 30px">WMS 物料</text>
<text class="card_content">{{ item.itemCode }}</text>
</view>
<view class="card_view">
<text class="card_order card_content" style="padding-left: 30px">客户 物料</text>
<text class="card_content">{{ item.customerItemCode }}</text>
</view>
<view class="card_view">
<text class="card_order card_content" style="padding-left: 30px">实际校验 物料</text>
<text class="card_content">{{ item.customerItemCode_reality }}</text>
</view>
<view class="line"></view>
</view>
</scroll-view>
</view>
<win-scan-button @goScan="openScanPopup"></win-scan-button>
</view>
<u-select v-model="show" mode="mutil-column-auto" :list="customerList" @confirm="confirmSelect"></u-select>
<win-check-fg-label ref="scanPopup" @checkResult="checkResult"></win-check-fg-label>
<com-message ref="comMessageRef" />
</view>
</template>
<script setup lang="ts">
import { ref, getCurrentInstance, onMounted, nextTick, watch } from 'vue'
import { onShow, onNavigationBarButtonTap, onReady, onReachBottom, onPullDownRefresh, onLoad } from '@dcloudio/uni-app'
import { issueRecordSubmit, getWorkShopLineStation, getBasicCustomerList } from '@/api/request2.js'
import { goHome, getPackingNumberAndBatchByList, deepCopyData } from '@/common/basic.js'
import { calc } from '@/common/calc.js'
import { getInventoryStatusDesc, getDirectoryItemArray } from '@/common/directory.js'
import { getBusinessType, createItemInfo, createDetailInfo, calcTreeHandleQty } from '@/common/record.js'
import { getManagementPrecisions, getPrecisionStrategyList, getPrecisionStrategyParams } from '@/common/balance.js'
import winScanButton from '@/mycomponents/scan/winScanButton.vue'
import winScanPack from '@/mycomponents/scan/winScanPack.vue'
import requiredLocation from '@/mycomponents/location/requiredLocation.vue'
import comBlankView from '@/mycomponents/common/comBlankView.vue'
import winScanLocation from '@/mycomponents/scan/winScanLocation.vue'
import winCheckFgLabel from '@/mycomponents/scan/winCheckFgLabel.vue'
import winScanPackAndLocation from '@/mycomponents/scan/winScanPackAndLocation.vue'
import recordComDetailCard from '@/mycomponents/record/recordComDetailCard.vue'
const { proxy } = getCurrentInstance()
const showToLoaction = ref(true)
const recommendLocationList = ref([]) //
const fromWarehouseCode = ref('') //
const positionList = ref([])
const show = ref(false)
const positionInfo = ref('请选择生产线')
const customerList = ref([])
const customerCode = ref('')
const customerName = ref('')
const list = ref([])
const scanPopup = ref()
const comMessageRef = ref()
onLoad((option) => {
getBasicCustomerList()
.then((res) => {
if (res.data.length > 0) {
const list = res.data
list.forEach((item) => {
item.label = item.name
item.value = item.code
})
customerList.value = list
}
})
.catch((error) => {
showErrorMessage(error)
})
})
//
onNavigationBarButtonTap((e) => {
if (e.index === 0) {
goHome()
}
})
//
const checkResult = (result) => {
let flag = true
for (let i = 0; i < list.value.length; i++) {
if (list.value[i].packingNumber == result.packingNumber && list.value[i].customerItemCode == result.customerItemCode && list.value[i].customerItemCode_reality == result.customerItemCode_reality && list.value[i].itemCode == result.itemCode && list.value[i].pass == result.pass) {
flag = false
}
}
if (flag) {
list.value.unshift(result)
}
if (result.pass) {
//
showMessage('校验通过')
} else {
showErrorMessage('校验未通过')
}
scanPopup.value.closeScanPopup()
}
//
const openScanPopup = () => {
scanPopup.value.openScanPopupForType(customerCode.value)
}
const showErrorMessage = (message) => {
comMessageRef.value.showErrorMessage(message, (res) => {
if (res) {
}
})
}
const showSelect = () => {
show.value = true
}
const confirmSelect = (e) => {
if (e.length > 0) {
customerCode.value = e[0].value
customerName.value = e[0].label
}
}
const showFromLocationPopup = () => {
show.value = true
}
const closeScanPopup = () => {
if (scanPopup.value != undefined) {
scanPopup.value.closeScanPopup()
}
}
const scanPopupGetFocus = () => {
if (scanPopup.value != undefined) {
scanPopup.value.packGetFocus()
}
}
const showMessage = (message) => {
comMessageRef.value.showMessage(message, (res) => {
if (res) {
}
})
}
const showScanMessage = (message) => {
comMessageRef.value.showScanMessage(message)
}
const afterCloseMessage = () => {
scanPopupGetFocus()
}
const closeScanMessage = () => {
scanPopupGetFocus()
}
const showCommitSuccessMessage = (hint) => {
comMessageRef.value.showSuccessMessage(hint, (res) => {})
}
</script>
<style scoped lang="scss">
.u-drawer-content {
height: 500rpx;
background-color: bisque;
}
.refuse_view {
background: linear-gradient(90deg, rgba(255, 160, 161, 1) 0%, rgba(255, 160, 161, 0) 100%);
}
.line {
background-color: #e0e0e0;
height: 1px;
}
</style>

96
src/pages/count/coms/comCountDetailcards.vue

@ -0,0 +1,96 @@
<template>
<view class="" style="width: 100%">
<view class="uni-flex uni-row space-between" style="align-items: center">
<view class="">
<item :dataContent="dataContent" style="margin-left: 15rpx"></item>
<pack v-if="dataContent.packingNumber" :packingCode="dataContent.packingNumber"></pack>
<batch :batch="dataContent.batch"></batch>
</view>
<view class="">
<view class="uni-flex uni-row">
<compareQty :dataContent="dataContent" :recommendQty="dataContent.recommendQty" :handleQty="dataContent.handleQty" :isShowRecommendQty="isShowRecommendQty"> </compareQty>
</view>
<!-- <view v-if="dataContent.scaned" style="margin-top: 10rpx; float: right;">
<button type="primary" size="mini" @click="edit">编辑</button>
</view> -->
<view class="uni-flex uni-row" style="vertical-align: center" v-if="isDevlement()">
<text style="font-size: 30rpx; color: #2979ff" @click="copy">复制采购</text>
<text style="font-size: 30rpx; color: #2979ff" @click="copyPro">|制品</text>
</view>
<!-- <move-status :fromInventoryStatus="dataContent.inventoryStatus" >
</move-status> -->
</view>
</view>
</view>
</template>
<script setup lang="ts">
import { ref, onMounted, nextTick, watch } from 'vue'
import item from '@/mycomponents/item/item.vue'
import pack from '@/mycomponents/balance/pack.vue'
import batch from '@/mycomponents/balance/batch.vue'
import compareQty from '@/mycomponents/qty/compareQty.vue'
import moveStatus from '@/mycomponents/balance/moveStatus.vue'
import config from '@/static/config.js'
const props = defineProps({
dataContent: {
type: Object,
default: null
},
handleQty: {
type: Number,
default: 0
},
isShowBalanceQty: {
type: Boolean,
default: true
},
showStdPack: {
type: Boolean,
default: false
},
isShowRecommendQty: {
type: Boolean,
default: true
},
isShowRecommendQty: {
type: Boolean,
default: true
}
})
const emit = defineEmits(['editItem'])
const edit = () => {
emit('editItem', props.dataContent)
}
const isDevlement = () => {
return config.isDevelopment
}
const copy = () => {
// HPQ;V1.0;ICE115F11161AG;PP20230427000026;B20230427002;Q100
const content = `HPQ;V1.0;I${props.dataContent.itemCode};P${props.dataContent.packingNumber};B${props.dataContent.batch};Q${props.dataContent.qty}`
uni.setClipboardData({
data: content,
success: () => {
uni.showToast({
title: '复制采购标签成功'
})
}
})
}
const copyPro = () => {
// HPQ;V1.0;ICE115F11161AG;PP20230427000026;B20230427002;Q100
const content = `HMQ;V1.0;I${props.dataContent.itemCode};P${props.dataContent.packingNumber};B${props.dataContent.batch};Q${props.dataContent.qty}`
uni.setClipboardData({
data: content,
success: () => {
uni.showToast({
title: '复制采购标签成功'
})
}
})
}
</script>
<style></style>

43
src/pages/count/coms/comFuzzyCountJobCard.vue

@ -0,0 +1,43 @@
<template>
<job-com-main-card :dataContent="dataContent">
<view class="task_item" style="border-top: 1px solid #dedede; padding-top: 20rpx; margin-top: 20rpx">
<view class="task_text">
<view class="card_view">
<text class="card_packing_code">盘点计划</text>
<text class="card_content">{{ dataContent.planNumber }}</text>
</view>
</view>
<view v-if="dataContent.countRange != undefined" class="">
<view class="task_text">
<view v-for="(range, index) in dataContent.countRange" :key="index">
<view class="card_view">
<text class="card_packing_code">{{ getCountScopeName(range.type) }}</text>
<text class="card_content">{{ range.value }}</text>
</view>
</view>
</view>
</view>
</view>
</job-com-main-card>
</template>
<script setup lang="ts">
import { ref, onMounted, nextTick, watch } from 'vue'
import { getCountScopeType } from '@/common/directory.js'
import jobComMainCard from '@/mycomponents/job/jobComMainCard.vue'
import jobComMainDetailCard from '@/mycomponents/job/jobComMainDetailCard.vue'
import toLocation from '@/mycomponents/balance/toLocation.vue'
const props = defineProps({
dataContent: {
type: Object,
default: {}
}
})
const getCountScopeName = () => {
const item = getCountScopeType(value)
return item.label
}
</script>
<style lang="scss"></style>

528
src/pages/count/job/countBlindDetail.vue

@ -0,0 +1,528 @@
<template>
<view class="page-wraper">
<view class="page-header">
<view class="header-view">
<view class="header_job_top">
<job-top :dataContent="jobContent"></job-top>
</view>
<view class="cen_card" style="padding-top: 10rpx; padding-bottom: 10rpx">
<view class="cell_box uni-flex uni-row" style="font-weight: bold">
<view class="cell_info" style="color: #000">
<view class="text_lightblue" style="color: #000">阶段</view>
<view style="color: #000">{{ getCountStageName(jobContent.stage) }}</view>
</view>
<view class="cell_info">
<view class="text_lightblue" style="color: #000">策略</view>
<view style="color: #000">{{ isOpenCount(jobContent.isOpenCount) }}</view>
</view>
<view class="cell_info">
<view class="text_lightblue" style="color: #000">库位</view>
<view style="color: #000">{{ fromLocationCode }}</view>
</view>
<view class="cell_info">
<view class="text_lightblue" style="color: #000">已扫描</view>
<view style="color: #000">{{ scanCount }}</view>
</view>
</view>
</view>
</view>
</view>
<u-line color="#D8D8D8" style="margin-bottom: 10rpx"></u-line>
<view style="margin-top: 160rpx; margin-bottom: 50rpx">
<u-line color="#D8D8D8" style="margin-bottom: 15rpx"></u-line>
<scroll-view scroll-y="true" class="" style="margin-bottom: 50px">
<view class="detail-list" v-for="(item, index) in showList" :key="item.id">
<u-swipe-action ref="swipeAction"
:options="item.scaned ? scanOptions : detailOptions"
@click="(...event)=>swipeClick(event, item)">
<view class="uni-flex uni-row" style="align-items: center" :class="item.scaned ? 'scan_view' : 'item'">
<view class="" style="font-size: 30rpx; font-weight: bold"> {{ index + 1 }}. </view>
<comCountDetailcards :ref="'countDetail_' + index" :dataContent="item" :index="index" @editItem="editItem" :settingParam="jobContent" @remove="updateData" :isShowRecommendQty="false" @updateData="updateData"> </comCountDetailcards>
</view>
<view class="split_line"></view>
</u-swipe-action>
</view>
</scroll-view>
<u-loadmore :status="loadingType" v-if="showList.length > 0" />
</view>
<view class="page-footer">
<view class="uni-flex u-col-center space-between padding_10" style="background-color: ghostwhite; width: 100%">
<view class=""> </view>
<view class="uni-flex uni-row">
<button class="btn_single_commit" hover-class="btn_commit_after" @click="commit">提交</button>
</view>
</view>
</view>
<win-scan-button @goScan="openScanPopup"></win-scan-button>
<win-scan-pack-and-location :allowModifyLocation="false" ref="scanPopup" :noShowBalanceMessage="true" :queryBalance="true" @getResult="getScanResult"> </win-scan-pack-and-location>
<count-qty-edit ref="countQtyEdit" @confirm="editConfirm" @close="editClose" :isShowStatus="true" :allowEditStatus="editInventoryStatus" :isShowBalance="jobContent.isOpenCount == 'TRUE'"> </count-qty-edit>
<detail-info-popup ref="detailInfoPopup"></detail-info-popup>
<comMessage ref="comMessage"></comMessage>
</view>
</template>
<script setup>
import { Decimal } from 'decimal.js' //
import { getCountJobDetail, takeCountJob, cancleTakeCountJob, countJobSubmit } from '@/api/request2.js'
import { calc } from '@/common/calc.js'
import { goHome, navigateBack, getPackingNumberAndBatch, compare } from '@/common/basic.js'
import { getCountStageName } from '@/common/directory.js'
import { getDetailOption, getDetailEditRemoveOption, getClearOption } from '@/common/array.js'
import winScanButton from '@/mycomponents/scan/winScanButton.vue'
import winScanPack from '@/mycomponents/scan/winScanPack.vue'
import comCountDetailcards from '@/pages/count/coms/comCountDetailcards.vue'
import winScanPackAndLocation from '@/mycomponents/scan/winScanPackAndLocation.vue'
import countQtyEdit from '@/mycomponents/qty/countQtyEdit.vue'
import jobTop from '@/mycomponents/job/jobTop.vue'
import detailInfoPopup from '@/pages/count/coms/detailInfoPopup.vue'
import { ref } from 'vue'
import { onLoad, onPullDownRefresh, onReachBottom, onBackPress, onNavigationBarButtonTap } from '@dcloudio/uni-app'
import { useCountStore } from "@/store";
const store = useCountStore()
const id = ref(null)
const jobStatus = ref('')
const detailOptions = ref(getDetailOption())
const scanOptions = ref(getDetailEditRemoveOption())
const loadingType = ref('')
const index = ref(1)
const showList = ref([])
const allDetails = ref([])
const allCount = ref(0)
const fromLocationCode = ref('')
const jobContent = ref({})
const currentEditItem = ref(null)
const showItem = ref(null)
const detailInfoPopup = ref(null)
const scanPopup = ref(null)
const comMessage = ref(null)
const countQtyEdit = ref(null)
onLoad(option => {
uni.setNavigationBarTitle({ title: `${option.title}详情` })
id.value = option.id
if (id.value !== undefined) {
if (option.status === '1') {
receive(() => getDetail())
} else {
getDetail()
}
}
detailOptions.value = getDetailOption()
scanOptions.value = getDetailEditRemoveOption()
})
onNavigationBarButtonTap(e => {
if (e.index === 0) {
goHome()
}
})
onBackPress(e => {
if (e.from === 'backbutton') {
if (jobStatus.value === '2') {
cancleTakeCountJob(id.value)
.then(() => uni.navigateBack())
.catch(() => uni.navigateBack())
} else {
uni.navigateBack()
}
return true
}
})
onPullDownRefresh(() => {
initList()
uni.stopPullDownRefresh()
})
onReachBottom(() => {
console.log('onReachBottom')
if (loadingType.value === 'nomore') return
index.value++
const list = getDataPage(index.value, pageSize)
if (list.length > 0) {
showList.value = showList.value.concat(list)
} else {
loadingType.value = 'nomore'
}
})
const receive = (callback) => {
if (id.value !== null) {
takeCountJob(id.value)
.then(callback)
.catch(error => showErrorMessage(error))
}
}
const getDetail = () => {
uni.showLoading({ title: '加载中....', mask: true })
getCountJobDetail(id.value)
.then(res => {
uni.hideLoading()
if (res.data === null) {
showMessage('未获取到详情')
} else {
jobContent.value = res.data
jobStatus.value = res.data.status
fromLocationCode.value = jobContent.value.countSplitCode
res.data.subList.forEach(item => {
item.recommendQty = item.qty
item.handleQty = 0
item.countTime = new Date()
item.fromLocationCode = fromLocationCode.value
})
allDetails.value = res.data.subList
allCount.value = res.data.subList.length
initList()
}
})
.catch(error => {
uni.hideLoading()
showErrorMessage(error)
})
}
const initList = () => {
index.value = 1
showList.value = []
loadingType.value = ''
showList.value = getDataPage(index.value, pageSize)
}
const getDataPage = (pageNo, pageSize) => {
const totalPages = Math.ceil(allCount.value / pageSize)
const start = (pageNo - 1) * pageSize
const end = start + pageSize
return allDetails.value.slice(start, end)
}
const swipeClick = (e, item) => {
if (e.content.text === '详情') {
detail(item)
} else if (e.content.text === '编辑') {
editItem(item)
} else if (e.content.text === '移除') {
remove(item)
}
}
const detail = (item) => {
showItem.value = item
detailInfoPopup.value.openPopup(item)
}
const remove = (item, index) => {
comMessage.value.showQuestionMessage('确定移除扫描信息?', res => {
if (res) {
item.scaned = false
item.handleQty = 0
emit('removePack')
}
})
}
const updateData = () => {}
const openScanPopup = () => {
const fromlocationList = [fromLocationCode.value]
scanPopup.value.openScanPopupForJob(fromLocationCode.value, fromlocationList, jobContent.value)
}
const closeScanPopup = () => {
if (scanPopup.value !== undefined) {
scanPopup.value.closeScanPopup()
}
}
const scanPopupGetFocus = () => {
if (scanPopup.value !== undefined) {
scanPopup.value.packGetFocus()
}
}
const scanPopupLoseFocus = () => {
if (scanPopup.value !== undefined) {
scanPopup.value.packLoseFocus()
}
}
const getScanResult = (result) => {
const { itemCode, packingNumber, batch, inventoryStatus, qty } = result.label
const items = allDetails.value.filter(r => r.itemCode === itemCode && r.packingNumber === packingNumber && r.batch === batch && r.inventoryStatus === inventoryStatus)
if (items.length === 0) {
comMessage.value.showQuestionMessage(`包装【${packingNumber}】不在任务列表中,是否要添加到列表中?`, res => {
if (res) {
const detail = createAddDetailInfo(result.package, qty)
detail.countTime = new Date()
allDetails.value.push(detail)
updateList()
countQtyEdit.value.openEditPopupShowSeconds(detail, null)
} else {
scanPopupGetFocus()
}
})
} else {
const selectItem = items[0]
if (selectItem.scaned) {
comMessage.value.showQuestionMessage(`包装【${packingNumber}】已经完成盘点,是否要编辑盘点结果?`, res => {
if (res) {
currentEditItem.value = selectItem
countQtyEdit.value.openEditPopup(selectItem, null)
} else {
scanPopupGetFocus()
}
})
} else {
selectItem.scaned = true
selectItem.balanceQty = Number(qty)
selectItem.handleQty = Number(qty)
selectItem.packQty = result.package.packQty
selectItem.packUnit = result.package.packUnit
countQtyEdit.value.openEditPopupShowSeconds(selectItem, null)
selectItem.countTime = new Date()
updateList()
}
}
}
const editConfirm = (qty, inventoryStatus, mode) => {
if (mode === 'edit') {
currentEditItem.value.handleQty = qty
currentEditItem.value.inventoryStatus = inventoryStatus
}
currentEditItem.value.countTime = new Date()
updateList()
scanPopupGetFocus()
}
const updateList = () => {
allDetails.value.sort(compare('countTime'))
initList()
scanPopupLoseFocus()
calcAllCount()
calcScanCount()
}
const calcAllCount = () => {
allCount.value = allDetails.value.length
}
const calcScanCount = () => {
scanCount.value = allDetails.value.filter(r => r.scaned === true).length
}
const editClose = () => {
scanPopupGetFocus()
}
const createAddDetailInfo = (pack, qty) => {
return {
masterId: jobContent.value.id,
scaned: true,
countDetailNumber: '',
ownerCode: '',
packingNumber: pack.number,
containerNumber: '',
batch: pack.batch,
inventoryStatus: 'OK',
itemCode: pack.itemCode,
itemName: pack.itemName,
itemDesc1: pack.itemDesc1,
itemDesc2: pack.itemDesc2,
packQty: pack.packQty,
packUnit: pack.packUnit,
projectCode: '',
recommendQty: Number(qty),
qty: Number(qty),
handleQty: Number(qty),
uom: pack.uom,
number: pack.number,
remark: '',
countQty: 0,
balanceQty: 0,
fromLocationCode: fromLocationCode.value,
locationCode: fromLocationCode.value,
creator: store.id,
countTime: new Date()
}
}
const commit = () => {
calcAllCount()
calcScanCount()
if (scanCount.value === allCount.value) {
submitJob()
} else if (scanCount.value < allCount.value) {
if (jobContent.value.allowPartialComplete === 'TRUE') {
comMessage.value.showQuestionMessage(`已经扫描[${scanCount.value}]总共[${allCount.value}],是否把未扫描的盘点数量设置为0?`, res => {
if (res) {
allDetails.value.forEach(item => {
if (!item.scaned) {
item.scaned = true
item.handleQty = 0
}
})
submitJob()
}
})
} else {
comMessage.value.showErrorMessage(`请完成扫描后,再进行提交\n已经扫描[${scanCount.value}]总共[${allCount.value}]`, res => {
if (res) {
openScanPopup()
}
})
}
}
}
const submitJob = () => {
uni.showLoading({ title: '提交中....', mask: true })
const params = setParams()
console.log('提交参数', JSON.stringify(params))
countJobSubmit(params)
.then(res => {
uni.hideLoading()
if (res.data) {
showCommitSuccessMessage(`提交成功\n生成盘点记录\n${res.data}`)
} else {
showErrorMessage(`提交失败[${res.msg}]`)
}
})
.catch(error => {
uni.hideLoading()
showErrorMessage(error)
})
}
const setParams = () => {
const subList = []
const creator = store.id
allDetails.value.forEach(item => {
if (item.scaned) {
item.countQty = item.handleQty
}
subList.push(item)
})
jobContent.value.subList = subList
jobContent.value.creator = creator
return jobContent.value
}
const showMessage = (message) => {
comMessage.value.showMessage(message, res => {
if (res) {
afterCloseMessage()
}
})
}
const showErrorMessage = (message) => {
comMessage.value.showErrorMessage(message, res => {
if (res) {
afterCloseMessage()
}
})
}
const showScanMessage = (message) => {
comMessage.value.showScanMessage(message)
}
const afterCloseMessage = () => {
scanPopupGetFocus()
}
const closeScanMessage = () => {
scanPopupGetFocus()
}
const editItem = (item) => {
currentEditItem.value = item
countQtyEdit.value.openEditPopup(currentEditItem.value, null)
}
const showCommitSuccessMessage = (hint) => {
comMessage.value.showSuccessMessage(hint, res => {
navigateBack(1)
})
}
const getCountStageName = (value) => {
return getCountStageName(value)
}
const isOpenCount = (value) => {
return value === 'TRUE' ? '明盘' : '盲盘'
}
</script>
<style scoped lang="scss">
page {
width: 100%;
height: 100%;
background-color: #fff;
}
.page-wraper {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
}
.header {
position: fixed;
/* #ifdef H5 */
top: 88rpx;
/* #endif */
left: 0;
width: 100%;
background-color: #fff;
z-index: 10;
padding: 10rpx;
/* 确保头部在内容之上 */
}
.page-footer {
position: fixed;
bottom: 0;
left: 0;
right: 0;
}
.page-main {
flex: 1;
position: relative;
}
.page-main-scroll {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
.page-main-list {
/* height: 80rpx;
line-height: 80rpx; */
text-align: center;
background: #e0e0e0;
}
.item {
background-color: #fff;
}
.item_scaned {
background-color: antiquewhite;
}
</style>

525
src/pages/count/job/countDetail1.vue

@ -0,0 +1,525 @@
<template>
<view class="page-wraper">
<view class="header">
<view class="">
<job-top :dataContent="jobContent"></job-top>
</view>
<view class="cen_card" style="padding-top: 10rpx; padding-bottom: 10rpx">
<view class="cell_box uni-flex uni-row" style="font-weight: bold">
<view class="cell_info" style="color: #000">
<view class="text_lightblue" style="color: #000">阶段</view>
<view style="color: #000">{{ getCountStageName(jobContent.stage) }}</view>
</view>
<view class="cell_info">
<view class="text_lightblue" style="color: #000">策略</view>
<view style="color: #000">{{ isOpenCount(jobContent.isOpenCount) }}</view>
</view>
<view class="cell_info">
<view class="text_lightblue" style="color: #000">库位</view>
<view style="color: #000">{{ fromLocationCode }}</view>
</view>
<view class="cell_info">
<view class="text_lightblue" style="color: #000">总数</view>
<view style="color: #000"> {{ allCount }}</view>
</view>
<view class="cell_info">
<view class="text_lightblue" style="color: #000">已扫描</view>
<view style="color: #000">{{ scanCount }}</view>
</view>
</view>
</view>
</view>
<view style="margin-top: 170rpx; margin-bottom: 50rpx">
<u-line color="#D8D8D8" style="margin-bottom: 15rpx"></u-line>
<scroll-view scroll-y="true" class="" style="margin-bottom: 50px">
<view class="detail-list" v-for="(item, index) in showList" :key="item.id">
<u-swipe-action ref="swipeAction"
:options="item.scaned ? scanOptions : detailOptions"
@click="(...event)=>swipeClick(event, item)">
<view class="uni-flex uni-row" style="align-items: center" :class="item.scaned ? 'scan_view' : 'item'">
<view class="" style="font-size: 30rpx; font-weight: bold"> {{ index + 1 }}. </view>
<comCountDetailcards :ref="'countDetail_' + index" :dataContent="item" :index="index" @editItem="editItem" :settingParam="jobContent" @remove="updateData" @updateData="updateData"> </comCountDetailcards>
</view>
<view class="split_line"></view>
</u-swipe-action>
</view>
</scroll-view>
<u-loadmore :status="loadingType" v-if="showList.length > 0" />
</view>
<view class="page-footer">
<view class="uni-flex u-col-center space-between padding_10" style="background-color: ghostwhite; width: 100%">
<view class=""> </view>
<view class="uni-flex uni-row">
<button class="btn_single_commit" hover-class="btn_commit_after" @click="commit">提交</button>
</view>
</view>
</view>
<win-scan-button @goScan="openScanPopup"></win-scan-button>
<win-scan-pack-and-location ref="scanPopup" :noShowBalanceMessage="true" @getCountScanResult="getScanResult"> </win-scan-pack-and-location>
<count-qty-edit ref="countQtyEdit" @confirm="editConfirm" @close="editClose" :isShowStatus="true" :allowEditStatus="editInventoryStatus" :isShowBalance="jobContent.isOpenCount == 'TRUE'"> </count-qty-edit>
<detail-info-popup ref="detailInfoPopup"></detail-info-popup>
<comMessage ref="comMessage"></comMessage>
</view>
</template>
<script setup>
import { Decimal } from 'decimal.js' //
import { getCountJobDetail, takeCountJob, cancleTakeCountJob, countJobSubmit } from '@/api/request2.js'
import { calc } from '@/common/calc.js'
import { goHome, navigateBack, getPackingNumberAndBatch, compare } from '@/common/basic.js'
import { getCountStageName } from '@/common/directory.js'
import { getDetailOption, getDetailEditRemoveOption, getClearOption } from '@/common/array.js'
import winScanButton from '@/mycomponents/scan/winScanButton.vue'
import winScanPack from '@/mycomponents/scan/winScanPack.vue'
import comCountDetailcards from '@/pages/count/coms/comCountDetailcards.vue'
import winScanPackAndLocation from '@/mycomponents/scan/winScanPackAndLocation.vue'
import countQtyEdit from '@/mycomponents/qty/countQtyEdit.vue'
import jobTop from '@/mycomponents/job/jobTop.vue'
import detailInfoPopup from '@/pages/count/coms/detailInfoPopup.vue'
import { ref, onMounted } from 'vue'
import { onLoad, onPullDownRefresh, onReachBottom, onBackPress, onNavigationBarButtonTap } from '@dcloudio/uni-app'
import { useCountStore } from '@/store'
const store = useCountStore()
const id = ref(null)
const jobStatus = ref('')
const detailOptions = ref(getDetailOption())
const scanOptions = ref(getDetailEditRemoveOption())
const loadingType = ref('')
const index = ref(1)
const showList = ref([])
const allDetails = ref([])
const allCount = ref(0)
const fromLocationCode = ref('')
const jobContent = ref({})
const currentEditItem = ref(null)
const showItem = ref(null)
const detailInfoPopup = ref(null)
const scanPopup = ref(null)
const comMessage = ref(null)
const countQtyEdit = ref(null)
onLoad(option => {
id.value = option.id
if (id.value !== undefined) {
if (option.status === '1') {
receive(() => getDetail())
} else {
getDetail()
}
}
detailOptions.value = getDetailOption()
scanOptions.value = getDetailEditRemoveOption()
})
onNavigationBarButtonTap(e => {
if (e.index === 0) {
goHome()
}
})
onBackPress(e => {
if (e.from === 'backbutton') {
if (jobStatus.value === '2') {
cancleTakeCountJob(id.value)
.then(() => uni.navigateBack())
.catch(() => uni.navigateBack())
} else {
uni.navigateBack()
}
return true
}
})
onPullDownRefresh(() => {
initList()
uni.stopPullDownRefresh()
})
onReachBottom(() => {
console.log('onReachBottom')
if (loadingType.value === 'nomore') return
index.value++
const list = getDataPage(index.value, pageSize)
if (list.length > 0) {
showList.value = showList.value.concat(list)
} else {
loadingType.value = 'nomore'
}
})
const receive = (callback) => {
if (id.value !== null) {
takeCountJob(id.value)
.then(callback)
.catch(error => showErrorMessage(error))
}
}
const getDetail = () => {
uni.showLoading({ title: '加载中....', mask: true })
getCountJobDetail(id.value)
.then(res => {
uni.hideLoading()
if (res.data === null) {
showMessage('未获取到详情')
} else {
jobContent.value = res.data
jobStatus.value = res.data.status
fromLocationCode.value = jobContent.value.locationCode
res.data.subList.forEach(item => {
item.recommendQty = item.qty
item.handleQty = 0
item.countTime = new Date()
item.fromLocationCode = fromLocationCode.value
})
allDetails.value = res.data.subList
allCount.value = res.data.subList.length
initList()
}
})
.catch(error => {
uni.hideLoading()
showErrorMessage(error)
})
}
const initList = () => {
index.value = 1
showList.value = []
loadingType.value = ''
showList.value = getDataPage(index.value, pageSize)
}
const getDataPage = (pageNo, pageSize) => {
const totalPages = Math.ceil(allCount.value / pageSize)
const start = (pageNo - 1) * pageSize
const end = start + pageSize
return allDetails.value.slice(start, end)
}
const swipeClick = (e, item) => {
if (e.content.text === '详情') {
detail(item)
} else if (e.content.text === '编辑') {
editItem(item)
} else if (e.content.text === '移除') {
remove(item)
}
}
const detail = (item) => {
showItem.value = item
detailInfoPopup.value.openPopup(item)
}
const remove = (item, index) => {
comMessage.value.showQuestionMessage('确定移除扫描信息?', res => {
if (res) {
item.scaned = false
item.handleQty = 0
emit('removePack')
}
})
}
const updateData = () => {}
const openScanPopup = () => {
const fromlocationList = [fromLocationCode.value]
scanPopup.value.openScanPopupForJob(fromLocationCode.value, fromlocationList, jobContent.value)
}
const closeScanPopup = () => {
if (scanPopup.value !== undefined) {
scanPopup.value.closeScanPopup()
}
}
const scanPopupGetFocus = () => {
if (scanPopup.value !== undefined) {
scanPopup.value.packGetFocus()
}
}
const scanPopupLoseFocus = () => {
if (scanPopup.value !== undefined) {
scanPopup.value.packLoseFocus()
}
}
const getScanResult = (result) => {
const { itemCode, packingNumber, batch, inventoryStatus, qty } = result.label
const items = allDetails.value.filter(r => r.itemCode === itemCode && r.packingNumber === packingNumber && r.batch === batch && r.inventoryStatus === inventoryStatus)
if (items.length === 0) {
comMessage.value.showQuestionMessage(`包装【${packingNumber}】不在任务列表中,是否要添加到列表中?`, res => {
if (res) {
const detail = createAddDetailInfo(result.package)
detail.countTime = new Date()
allDetails.value.push(detail)
updateList()
countQtyEdit.value.openEditPopupShowSeconds(detail, null)
} else {
scanPopupGetFocus()
}
})
} else {
const selectItem = items[0]
if (selectItem.scaned) {
comMessage.value.showQuestionMessage(`包装【${packingNumber}】已经完成盘点,是否要编辑盘点结果?`, res => {
if (res) {
currentEditItem.value = selectItem
countQtyEdit.value.openEditPopup(selectItem, null)
} else {
scanPopupGetFocus()
}
})
} else {
selectItem.scaned = true
selectItem.handleQty = Number(qty)
selectItem.packQty = result.package.packQty
selectItem.packUnit = result.package.packUnit
countQtyEdit.value.openEditPopupShowSeconds(selectItem, null)
selectItem.countTime = new Date()
updateList()
}
}
}
const editConfirm = (qty, inventoryStatus, mode) => {
if (mode === 'edit') {
currentEditItem.value.handleQty = qty
currentEditItem.value.inventoryStatus = inventoryStatus
}
currentEditItem.value.countTime = new Date()
updateList()
scanPopupGetFocus()
}
const updateList = () => {
allDetails.value.sort(compare('countTime'))
initList()
scanPopupLoseFocus()
calcAllCount()
calcScanCount()
}
const calcAllCount = () => {
allCount.value = allDetails.value.length
}
const calcScanCount = () => {
scanCount.value = allDetails.value.filter(r => r.scaned === true).length
}
const editClose = () => {
scanPopupGetFocus()
}
const createAddDetailInfo = (pack) => {
return {
id: jobContent.value.masterId,
scaned: true,
countDetailNumber: '',
ownerCode: '',
packingNumber: pack.number,
containerNumber: '',
batch: pack.batch,
inventoryStatus: 'OK',
itemCode: pack.itemCode,
itemName: pack.itemName,
itemDesc1: pack.itemDesc1,
itemDesc2: pack.itemDesc2,
packQty: pack.packQty,
packUnit: pack.packUnit,
projectCode: '',
qty: 0,
handleQty: 0,
uom: pack.uom,
number: pack.number,
remark: '',
countQty: 0,
balanceQty: 0,
fromLocationCode: fromLocationCode.value,
creator: store.id,
countTime: new Date()
}
}
const commit = () => {
calcAllCount()
calcScanCount()
if (scanCount.value === allCount.value) {
submitJob()
} else if (scanCount.value < allCount.value) {
if (jobContent.value.allowPartialComplete === 'TRUE') {
comMessage.value.showQuestionMessage(`已经扫描[${scanCount.value}]总共[${allCount.value}],是否把未扫描的盘点数量设置为0?`, res => {
if (res) {
allDetails.value.forEach(item => {
if (!item.scaned) {
item.scaned = true
item.handleQty = 0
}
})
submitJob()
}
})
} else {
comMessage.value.showErrorMessage(`请完成扫描后,再进行提交\n已经扫描[${scanCount.value}]总共[${allCount.value}]`, res => {
if (res) {
openScanPopup()
}
})
}
}
}
const submitJob = () => {
uni.showLoading({ title: '提交中....', mask: true })
const params = setParams()
console.log('提交参数', JSON.stringify(params))
countJobSubmit(params)
.then(res => {
uni.hideLoading()
if (res.data) {
showCommitSuccessMessage(`提交成功\n生成盘点记录\n${res.data}`)
} else {
showErrorMessage(`提交失败[${res.msg}]`)
}
})
.catch(error => {
uni.hideLoading()
showErrorMessage(error)
})
}
const setParams = () => {
const subList = []
const creator = store.id
allDetails.value.forEach(item => {
if (item.scaned) {
item.countQty = item.handleQty
}
subList.push(item)
})
jobContent.value.subList = subList
jobContent.value.creator = creator
return jobContent.value
}
const showMessage = (message) => {
comMessage.value.showMessage(message, res => {
if (res) {
afterCloseMessage()
}
})
}
const showErrorMessage = (message) => {
comMessage.value.showErrorMessage(message, res => {
if (res) {
afterCloseMessage()
}
})
}
const showScanMessage = (message) => {
comMessage.value.showScanMessage(message)
}
const afterCloseMessage = () => {
scanPopupGetFocus()
}
const closeScanMessage = () => {
scanPopupGetFocus()
}
const editItem = (item) => {
currentEditItem.value = item
countQtyEdit.value.openEditPopup(currentEditItem.value, null)
}
const showCommitSuccessMessage = (hint) => {
comMessage.value.showSuccessMessage(hint, res => {
navigateBack(1)
})
}
const getCountStageName = (value) => {
return getCountStageName(value)
}
const isOpenCount = (value) => {
return value === 'TRUE' ? '明盘' : '盲盘'
}
</script>
<style scoped lang="scss">
page {
width: 100%;
height: 100%;
background-color: #fff;
}
.page-wraper {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
}
.header {
position: fixed;
top: 88rpx;
left: 0;
width: 100%;
background-color: #fff;
z-index: 10;
padding: 10rpx;
/* 确保头部在内容之上 */
}
.page-footer {
position: fixed;
bottom: 0;
left: 0;
right: 0;
}
.page-main {
flex: 1;
position: relative;
}
.page-main-scroll {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
.page-main-list {
/* height: 80rpx;
line-height: 80rpx; */
text-align: center;
background: #e0e0e0;
}
.item {
background-color: #fff;
}
.item_scaned {
background-color: antiquewhite;
}
</style>

662
src/pages/count/job/countLightDetail.vue

@ -0,0 +1,662 @@
<template>
<view class="page-wraper">
<view class="page-header">
<view class="header-view">
<view class="header_job_top">
<job-top :dataContent="jobContent"></job-top>
</view>
<view class="cen_card" style="padding:10rpx 0">
<view class="cell_box uni-flex uni-row" style="font-weight: bold">
<view class="cell_info" style="color: #000">
<view class="text_lightblue" style="color: #000">阶段</view>
<view style="color: #000">{{ getCountStageNameValue(jobContent.stage) }}</view>
</view>
<view class="cell_info">
<view class="text_lightblue" style="color: #000">策略</view>
<view style="color: #000">{{ isOpenCount(jobContent.isOpenCount) }}</view>
</view>
<view class="cell_info">
<view class="text_lightblue" style="color: #000">库位</view>
<view style="color: #000">{{ fromLocationCode }}</view>
</view>
<view class="cell_info">
<view class="text_lightblue" style="color: #000">总数</view>
<view style="color: #000"> {{ allCount }}</view>
</view>
<view class="cell_info">
<view class="text_lightblue" style="color: #000">已扫描</view>
<view style="color: #000">{{ scanCount }}</view>
</view>
</view>
</view>
</view>
</view>
<u-line color="#D8D8D8" style="margin-bottom: 10rpx"></u-line>
<view style="margin-top: 160rpx; padding-bottom: 130rpx">
<u-line color="#D8D8D8" style="margin-bottom: 15rpx"></u-line>
<scroll-view scroll-y="true" class="" style="margin-bottom: 0px">
<view class="detail-list" v-for="(item, index) in showList" :key="item.id">
<u-swipe-action ref="swipeAction"
:options="item.scaned ? scanOptions : detailOptions"
@click="(...event)=>swipeClick(event, item)">
<view class="uni-flex uni-row" style="align-items: center" :class="item.scaned ? 'scan_view' : 'item'">
<view class="" style="font-size: 30rpx; font-weight: bold"> {{ index + 1 }}. </view>
<comCountDetailcards :ref="'countDetail_'+index" :dataContent="item" :index="index" @editItem="editItem"
:settingParam="jobContent" @remove="updateData" @updateData="updateData">
</comCountDetailcards>
</view>
<view class="split_line"></view>
</u-swipe-action>
</view>
</scroll-view>
<u-loadmore :status="loadingType" v-if="showList.length > 0" />
</view>
<view class="page-footer">
<view class="uni-flex u-col-center space-between padding_10" style="background-color: ghostwhite; width: 100%">
<view class=""> </view>
<view class="uni-flex uni-row">
<button class="btn_single_commit" hover-class="btn_commit_after" @click="commit">提交</button>
</view>
</view>
</view>
<win-scan-button @goScan="openScanPopup"></win-scan-button>
<win-scan-pack-and-location :allowModifyLocation="false" ref="scanPopup" :noShowBalanceMessage="true" @getCountScanResult="getScanResult"> </win-scan-pack-and-location>
<count-qty-edit ref="countQtyEditRef" @confirm="editConfirm" @close="editClose" :isShowStatus="true" :allowEditStatus="editInventoryStatus" :isShowBalance="jobContent.isOpenCount == 'TRUE'"> </count-qty-edit>
<detail-info-popup ref="detailInfoPopupRef"></detail-info-popup>
<com-message ref="comMessageRef" />
</view>
</template>
<script setup lang="ts">
import { ref, getCurrentInstance, onMounted, nextTick, watch } from 'vue'
import { onShow, onNavigationBarButtonTap, onReady, onReachBottom, onPullDownRefresh, onLoad, onBackPress } from '@dcloudio/uni-app'
import { getCountJobDetail, takeCountJob, cancleTakeCountJob, countJobSubmit } from '@/api/request2.js'
import { goHome, navigateBack, getPackingNumberAndBatch ,compare } from '@/common/basic.js'
import { getDetailOption, getDetailEditRemoveOption } from '@/common/array.js'
import { getCountStageName } from '@/common/directory.js'
import {getManagementPrecisions,} from '@/common/balance.js';
import winScanButton from '@/mycomponents/scan/winScanButton.vue'
import comCountDetailcards from '@/pages/count/coms/comCountDetailcards.vue'
import winScanPackAndLocation from '@/mycomponents/scan/winScanPackAndLocation.vue'
import countQtyEdit from '@/mycomponents/qty/countQtyEdit.vue'
import jobTop from '@/mycomponents/job/jobTop.vue'
import detailInfoPopup from '@/pages/count/coms/detailInfoPopup.vue'
import { useCountStore } from '@/store'
// store
const store = useCountStore()
const { proxy } = getCurrentInstance()
const id = ref('')
const fromLocationCode = ref('')
const jobContent = ref({}) //
const editInventoryStatus = ref(false)
const currentEditItem = ref({})
const jobStatus = ref('')
const allCount = ref(0)
const scanCount = ref(0)
const index = ref(0)
const pageSize = ref(20)
const showList = ref([])
const loadingType = ref('')
const allDetails = ref([])
const scanOptions = ref([])
const detailOptions = ref([])
const detailInfoPopupRef = ref()
const showItem = ref()
const comMessageRef = ref()
const scanPopup = ref()
const countQtyEditRef = ref()
const managementList = ref([])
const managementType = ref('')
const emit = defineEmits(['removePack'])
onLoad((option) => {
uni.setNavigationBarTitle({
title: `${option.title}详情`
})
id.value = option.id
if (id.value != undefined) {
//
if (option.status == '1') {
receive((callback) => {
getDetail()
})
} else {
getDetail()
}
}
detailOptions.value = getDetailOption()
scanOptions.value = getDetailEditRemoveOption()
})
//
onNavigationBarButtonTap((e) => {
if (e.index === 0) {
goHome()
}
})
//
onBackPress((e) => {
//
if (e.from === 'backbutton') {
if (jobStatus.value == '2') {
//
cancleTakeCountJob(id.value)
.then((res) => {
uni.navigateBack()
})
.catch((error) => {
uni.navigateBack()
})
} else {
uni.navigateBack()
}
return true
}
})
onPullDownRefresh(() => {
initList()
uni.stopPullDownRefresh()
})
onReachBottom(() => {
console.log('onReachBottom')
//
if (loadingType.value == 'nomore') {
return
}
index.value++
const list = getDataPage(index.value, pageSize.value)
if (list.length > 0) {
showList.value = showList.value.concat(list)
} else {
//
loadingType.value = 'nomore'
}
})
//
const receive = (callback) => {
if (id.value != null) {
takeCountJob(id.value)
.then((res) => {
callback()
})
.catch((error) => {
showErrorMessage(error)
})
}
}
const getDetail = () => {
uni.showLoading({
title: '加载中....',
mask: true
})
getCountJobDetail(id.value)
.then(async (res) => {
uni.hideLoading()
if (res.data == null) {
showMessage('未获取到详情')
} else {
console.log(res);
jobContent.value = res.data
jobStatus.value = res.data.status
fromLocationCode.value = jobContent.value.countSplitCode
res.data.subList.forEach((item) => {
item.recommendQty = item.qty
item.handleQty = 0
item.countTime = new Date()
item.fromLocationCode = fromLocationCode.value
})
allDetails.value = res.data.subList
allCount.value = res.data.subList.length
//
let itemCodes = []
allDetails.value.forEach(item => {
itemCodes.push(item.itemCode)
item.scaned = false
})
await getManagementPrecisions(itemCodes, fromLocationCode.value, res => {
if (res.success) {
managementList.value = res.list;
managementType.value = managementList.value.some(item => item.ManagementPrecision ==
'BY_BATCH') ? 'BY_BATCH' : ''
if (managementType.value == 'BY_BATCH') {
allDetails.value.forEach(item => {
item.packingNumber = ''
item.toPackingNumber = ''
item.fromPackingNumber = ''
})
}
}
})
initList()
}
})
.catch((error) => {
uni.hideLoading()
showErrorMessage(error)
})
}
const initList = () => {
index.value = 1
showList.value = []
loadingType.value = ''
showList.value = getDataPage(index.value, pageSize.value)
}
const getDataPage = (pageNo, pageSize) => {
//
const totalPages = Math.ceil(allCount.value / pageSize)
//
const start = (pageNo - 1) * pageSize
const end = start + pageSize //
return allDetails.value.slice(start, end)
}
const swipeClick = (e, item) => {
if (e.content.text == '详情') {
detail(item)
} else if (e.content.text == '编辑') {
editItem(item)
} else if (e.content.text == '移除') {
remove(item)
}
}
const detail = (item) => {
showItem.value = item
detailInfoPopupRef.value.openPopup(item)
}
const remove = (item, index) => {
comMessageRef.value.showQuestionMessage('确定移除扫描信息?', (res) => {
if (res) {
item.scaned = false
item.handleQty = 0
showList.value.splice(index, 1)
emit('removePack')
}
})
}
const openScanPopup = () => {
const fromlocationList = []
fromlocationList.push(fromLocationCode.value)
scanPopup.value.openScanPopupForJob(fromLocationCode.value, fromlocationList, jobContent.value)
}
const closeScanPopup = () => {
if (scanPopup.value != undefined) {
scanPopup.value.closeScanPopup()
}
}
const scanPopupGetFocus = () => {
if (scanPopup.value != undefined) {
scanPopup.value.packGetFocus()
}
}
const scanPopupLoseFocus = () => {
if (scanPopup.value != undefined) {
scanPopup.value.packLoseFocus()
}
}
//
const getScanResult = (result) => {
const { itemCode } = result.label
const { packingNumber } = result.label
const pack = result.package
const { batch } = result.label
const inventoryStatus = result.balance ? result.balance.inventoryStatus : 'OK'
const qty = result.balance ? result.balance.qty : result.label.qty
//
const items = allDetails.value.filter((r) => r.itemCode === itemCode &&
// r.packingNumber === packingNumber &&
r.batch === batch &&
r.inventoryStatus === inventoryStatus)
// ,
if (items.length == 0) {
if(managementType.value == 'BY_BATCH'){
comMessageRef.value.showQuestionMessage(`批次【${result.label.batch}】不在任务列表中,是否要添加到列表中?`, (res) => {
//
if (res) {
const detail = createAddDetailInfo(pack, qty)
detail.countTime = new Date()
allDetails.value.push(detail)
updateList()
countQtyEditRef.value.openEditPopupShowSeconds(detail, null)
} else {
scanPopupGetFocus()
}
})
}else {
comMessageRef.value.showQuestionMessage(`包装【${result.label.packingNumber}】不在任务列表中,是否要添加到列表中?`, (res) => {
//
if (res) {
const detail = createAddDetailInfo(pack, qty)
detail.countTime = new Date()
allDetails.value.push(detail)
updateList()
countQtyEditRef.value.openEditPopupShowSeconds(detail, null)
} else {
scanPopupGetFocus()
}
})
}
} else {
const selectItem = items[0]
//
if (selectItem.scaned) {
//
if(managementType.value == 'BY_BATCH'){
comMessageRef.value.showQuestionMessage(`批次【${result.label.batch}】已经完成盘点,是否要编辑盘点结果?`, (res) => {
if (res) {
currentEditItem.value = selectItem
countQtyEditRef.value.openEditPopup(selectItem, null)
} else {
scanPopupGetFocus()
}
})
}else {
comMessageRef.value.showQuestionMessage(`包装【${result.label.packingNumber}】已经完成盘点,是否要编辑盘点结果?`, (res) => {
if (res) {
currentEditItem.value = selectItem
countQtyEditRef.value.openEditPopup(selectItem, null)
} else {
scanPopupGetFocus()
}
})
}
} else {
//
selectItem.scaned = true
selectItem.balanceQty = Number(qty)
selectItem.handleQty = Number(qty)
selectItem.packQty = pack.packQty
selectItem.packUnit = pack.packUnit
selectItem.parentPackingNumber = pack.parentPackingNumber
selectItem.locationCode = fromLocationCode.value
selectItem.fromLocationCode = fromLocationCode.value
countQtyEditRef.value.openEditPopupShowSeconds(selectItem, null)
selectItem.countTime = new Date()
updateList()
}
}
}
const editConfirm = (qty, inventoryStatus, mode) => {
//
if (mode == 'edit') {
currentEditItem.value.handleQty = qty
currentEditItem.value.inventoryStatus = inventoryStatus
}
//
currentEditItem.value.countTime = new Date()
updateList()
scanPopupGetFocus()
}
const updateList = () => {
allDetails.value.sort(compare('countTime')) //
initList()
scanPopupLoseFocus()
calcAllCount()
calcScanCount()
}
const calcAllCount = () => {
allCount.value = allDetails.value.length
}
const calcScanCount = () => {
scanCount.value = allDetails.value.filter((r) => r.scaned === true).length
}
const editClose = () => {
scanPopupGetFocus()
}
//
const createAddDetailInfo = (pack, qty) => {
const detail = {
id: jobContent.value.id, //
scaned: true,
countDetailNumber: '',
ownerCode: '',
packingNumber: pack.number,
containerNumber: '',
batch: pack.batch,
inventoryStatus: 'OK',
itemCode: pack.itemCode,
itemName: pack.itemName,
itemDesc1: pack.itemDesc1,
itemDesc2: pack.itemDesc2,
packQty: pack.packQty,
packUnit: pack.packUnit,
projectCode: '',
recommendQty: Number(qty),
qty: Number(qty),
handleQty: Number(qty),
uom: pack.uom,
number: pack.number,
remark: '',
countQty: Number(qty),
balanceQty: Number(qty),
fromLocationCode: fromLocationCode.value,
locationCode: fromLocationCode.value,
creator: store.id,
countTime: new Date()
}
return detail
}
const commit = () => {
calcAllCount()
calcScanCount()
// if(scanCount.value){
// comMessageRef.value.showErrorMessage(',');
// return
// }
if (scanCount.value == allCount.value) {
submitJob()
} else if (scanCount.value < allCount.value) {
//
if (jobContent.value.allowPartialComplete == 'TRUE') {
//
comMessageRef.value.showQuestionMessage(`已经扫描[${scanCount.value}]总共[${allCount.value}],是否把未扫描的盘点数量设置为0?`, (res) => {
if (res) {
allDetails.value.forEach((item) => {
if (!item.scaned) {
item.scaned = true
item.handleQty = 0
item.locationCode = fromLocationCode.value
item.fromLocationCode = fromLocationCode.value
}
})
submitJob()
}
})
} else {
//
comMessageRef.value.showErrorMessage('请完成扫描后,再进行提交\n' + `已经扫描[${scanCount.value}]总共[${getTotalCount()}]`, (res) => {
if (res) {
openScanPopup()
}
})
}
}
}
const submitJob = () => {
uni.showLoading({
title: '提交中....',
mask: true
})
//
let itemCodes = []
allDetails.value.forEach(item => {
itemCodes.push(item.itemCode)
// item.scaned = false
})
getManagementPrecisions(itemCodes, this.fromLocationCode, res => {
if (res.success) {
managementList.value = res.list
const params = setParams()
countJobSubmit(params)
.then((res) => {
uni.hideLoading()
const str = res.data || ''
showCommitSuccessMessage("提交成功\n生成盘点记录\n" + str)
// if (res.data) {
// showCommitSuccessMessage(`\n\n${res.data}`)
// } else {
// showErrorMessage(`[${res.msg}]`)
// }
})
.catch((error) => {
uni.hideLoading()
showErrorMessage(error)
})
}
})
}
const setParams = () => {
const subList = []
const creator = store.id
allDetails.value.forEach((item) => {
if (item.scaned) {
item.countQty = item.handleQty
let info = getPackingNumberAndBatch(this.managementList, item.itemCode, item.packingNumber, item.batch);
item.toPackingNumber = info.packingNumber;
item.packingNumber = info.packingNumber;
item.fromPackingNumber = info.packingNumber;
}
subList.push(item)
})
jobContent.value.subList = subList
jobContent.value.creator = creator
return jobContent.value
}
const showMessage = (message) => {
comMessageRef.value.showMessage(message, (res) => {
if (res) {
afterCloseMessage()
}
})
}
const showErrorMessage = (message) => {
comMessageRef.value.showErrorMessage(message, (res) => {
if (res) {
afterCloseMessage()
}
})
}
const showScanMessage = (message) => {
comMessageRef.value.showScanMessage(message)
}
const afterCloseMessage = () => {
scanPopupGetFocus()
}
const closeScanMessage = () => {
scanPopupGetFocus()
}
const editItem = (item) => {
currentEditItem.value = item
countQtyEditRef.value.openEditPopup(this.currentEditItem, null)
}
const showCommitSuccessMessage = (hint) => {
comMessageRef.value.showSuccessMessage(hint, (res) => {
navigateBack(1)
})
}
const getCountStageNameValue = (value) => {
return getCountStageName(value)
}
const isOpenCount = (value) => {
return value == 'TRUE' ? '明盘' : '盲盘'
}
</script>
<style scoped lang="scss">
page {
width: 100%;
height: 100%;
background-color: #fff;
}
.page-wraper {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
}
.header {
position: fixed;
/* #ifdef H5 */
top: 88rpx;
/* #endif */
left: 0;
width: 100%;
background-color: #fff;
z-index: 10;
padding: 10rpx;
/* 确保头部在内容之上 */
}
.page-footer {
position: fixed;
bottom: 0;
left: 0;
right: 0;
}
.page-main {
flex: 1;
position: relative;
}
.page-main-scroll {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
.page-main-list {
/* height: 80rpx;
line-height: 80rpx; */
text-align: center;
background: #e0e0e0;
}
.item {
background-color: #fff;
}
.item_scaned {
background-color: antiquewhite;
}
</style>

524
src/pages/count/job/fuzzyCountDetail.vue

@ -0,0 +1,524 @@
<template>
<view class="page-wraper">
<view class="page-header">
<view class="header_job_top">
<view class="header-view">
<job-top :dataContent="jobContent"></job-top>
<u-collapse ref="collapse">
<u-collapse-item :open="true">
<template v-slot:title>
<view class="card_itemName" style="padding: 3px 5px; font-size: 28rpx"> 盘点范围 </view>
</template>
<view v-for="(range, index) in jobContent.countRange" :key="index">
<view class="card_view">
<text class="card_packing_code">{{ getCountScopeName(range.type) }}</text>
<text class="card_content">{{ range.value }}</text>
</view>
</view>
</u-collapse-item>
</u-collapse>
</view>
</view>
<view class="card_view" v-if="fromLocationCode != ''">
<text class="card_location">盘点库位</text>
<text class="card_content">{{ fromLocationCode }}</text>
</view>
</view>
<com-blank-view @goScan="showFromLocationPopup" v-if="detailSource.length == 0"></com-blank-view>
<view class="page-main">
<scroll-view scroll-y="true" class="page-main-scroll">
<u-swipe-action ref="swipeAction"
v-for="(item, index) in detailSource" :key="item.id"
:options="editRemoveOption"
@click="(...event)=>swipeClick(event, item, index)">
<view class="detail-list">
<view class="">
<package-and-item-card :dataContent="item"></package-and-item-card>
</view>
<view class="split_line"></view>
</view>
</u-swipe-action>
</scroll-view>
</view>
<view class="page-footer" v-if="detailSource.length > 0">
<view class="uni-flex u-col-center space-between padding_10" style="background-color: ghostwhite; width: 100%">
<view class="uni-flex u-col-center space-between padding_10">
<view> 已扫描: </view>
<view class="card_packing_code" style="padding: 5px; font-weight: bold; font-size: 40rpx">
{{ detailSource.length }}
</view>
<view> () </view>
</view>
<view class="uni-flex uni-row space-between">
<button class="btn_single_commit" hover-class="btn_commit_after" @click="commit">提交</button>
</view>
</view>
</view>
<win-scan-button v-if="fromLocationCode != ''" @goScan="openScanPopup"></win-scan-button>
<win-scan-pack ref="scanPopup" @getResult="getScanResult"></win-scan-pack>
<win-scan-location ref="scanLocationCode" title="盘点库位" @getLocation="getLocation"></win-scan-location>
<count-qty-edit ref="countQtyEdit" @confirm="editConfirm" @close="editClose" :isShowStatus="true" :isShowDesc="false" :allowEditStatus="editInventoryStatus" :isShowBalance="jobContent.isOpenCount == 'TRUE'"> </count-qty-edit>
<comMessage ref="comMessageRef"></comMessage>
</view>
</template>
<script setup>
import { Decimal } from 'decimal.js' //
import { getFuuzyCountJobDetail, takeCountJob, cancleTakeCountJob, countJobSubmit } from '@/api/request2.js'
import { calc } from '@/common/calc.js'
import { getEditRemoveOption } from '@/common/array.js'
import { goHome, navigateBack, getPackingNumberAndBatch } from '@/common/basic.js'
import { getCountScopeType } from '@/common/directory.js'
import {getManagementPrecisions,} from '@/common/balance.js';
import winScanButton from '@/mycomponents/scan/winScanButton.vue'
import winScanPack from '@/mycomponents/scan/winScanPack.vue'
import comCountDetailCard from '@/pages/count/coms/comCountDetailCard.vue'
// import winScanPackAndLocation from "@/mycomponents/scan/winScanPackAndLocation.vue"
import winScanLocation from '@/mycomponents/scan/winScanLocation.vue'
import countQtyEdit from '@/mycomponents/qty/countQtyEdit.vue'
import jobTop from '@/mycomponents/job/jobTop.vue'
import comBlankView from '@/mycomponents/common/comBlankView.vue'
import PackageAndItemCard from '@/mycomponents/package/PackageAndItemCard.vue'
import { ref, nextTick } from 'vue'
import { onLoad, onPullDownRefresh, onBackPress, onNavigationBarButtonTap } from '@dcloudio/uni-app'
import {useCountStore} from '@/store'
const store = useCountStore()
const id = ref(null)
const jobStatus = ref('')
const editRemoveOption = ref(getEditRemoveOption())
const jobContent = ref({})
const itemRangeValue = ref('')
const fromLocation = ref({})
const fromLocationCode = ref('')
const detailSource = ref([])
const managementList = ref([])
const managementType = ref('')
const currentEditItem = ref(null)
const showItem = ref(null)
const scanLocationCode = ref(null)
const scanPopup = ref(null)
const comMessageRef = ref(null)
const countQtyEdit = ref(null)
const detailInfoPopup = ref(null)
onLoad(option => {
id.value = option.id
if (id.value !== undefined) {
if (option.status === '1') {
receive(() => getDetail(() => showFromLocationPopup()))
} else {
getDetail(() => showFromLocationPopup())
}
}
editRemoveOption.value = getEditRemoveOption()
})
onNavigationBarButtonTap(e => {
if (e.index === 0) {
goHome()
}
})
onBackPress(e => {
if (e.from === 'backbutton') {
if (jobStatus.value === '2') {
cancleTakeCountJob(id.value)
.then(() => uni.navigateBack())
.catch(() => uni.navigateBack())
} else {
uni.navigateBack()
}
return true
}
})
onPullDownRefresh(() => {
// uni.stopPullDownRefresh();
})
const receive = (callback) => {
if (id.value !== null) {
takeCountJob(id.value)
.then(callback)
.catch(error => showErrorMessage(error))
}
}
const getDetail = (callback) => {
uni.showLoading({ title: '加载中....', mask: true })
getFuuzyCountJobDetail(id.value)
.then(res => {
uni.hideLoading()
jobContent.value = res.data
jobStatus.value = res.data.status
const range = jobContent.value.countRange.find(r => r.type === 'ITEM_CODE')
if (range !== undefined) {
itemRangeValue.value = range.value
}
callback()
})
.catch(error => {
uni.hideLoading()
showErrorMessage(error)
})
}
const showFromLocationPopup = () => {
// this.$refs.scanLocationCode.openScanPopup();
nextTick(() => {
scanLocationCode.value.openScanPopup()
})
}
const getLocation = (location, code) => {
const { countRange } = jobContent.value
if (countRange !== null) {
let range = countRange.find(r => r.type === 'LOCATION_CODE')
if (range !== undefined) {
const rangeValue = range.value
const index = rangeValue.indexOf(location.code)
if (index < 0) {
afterScanLocation(`库位代码【${location.code}】,不在盘点库位范围【${rangeValue}】内`)
return
}
} else {
range = countRange.find(r => r.type === 'LOCATIONGROUP_CODE')
if (range !== undefined) {
const rangeValue = range.value
const index = rangeValue.indexOf(location.locationGroupCode)
if (index < 0) {
afterScanLocation(`库位组代码【${location.locationGroupCode}】,不在盘点库位组范围【${rangeValue}】内`)
return
}
} else {
range = countRange.find(r => r.type === 'AREABASIC_CODE')
if (range !== undefined) {
const rangeValue = range.value
const index = rangeValue.indexOf(location.areaCode)
if (index < 0) {
afterScanLocation(`库区代码【${location.areaCode}】,不在盘点库区范围【${rangeValue}】内`)
return
}
} else {
range = countRange.find(r => r.type === 'WAREHOUSE_CODE')
if (range !== undefined) {
const rangeValue = range.value
const index = rangeValue.indexOf(location.warehouseCode)
if (index < 0) {
afterScanLocation(`仓库代码【${location.warehouseCode}】,不在盘点仓库范围【${rangeValue}】内`)
return
}
}
}
}
}
}
getFromLocationCode(location, code)
}
const afterScanLocation = (message) => {
showErrorMessage(message)
showFromLocationPopup()
}
const getFromLocationCode = (location, code) => {
fromLocation.value = location
fromLocationCode.value = code
openScanPopup()
}
const openScanPopup = () => {
scanPopup.value.openScanPopup()
}
const scanPopupGetFocus = () => {
if (scanPopup.value !== undefined) {
scanPopup.value.getfocus()
}
}
const closeScanPopup = () => {
if (scanPopup.value !== undefined) {
scanPopup.value.closeScanPopup()
}
}
const scanPopupLoseFocus = () => {
if (scanPopup.value !== undefined) {
scanPopup.value.losefocus()
}
}
const getScanResult = (result) => {
const packInfo = result.package
if (itemRangeValue.value !== '') {
const index = itemRangeValue.value.indexOf(packInfo.itemCode)
if (index < 0) {
showErrorMessage(`物料代码【${packInfo.itemCode}】,不在盘点范围【${itemRangeValue.value}】内`)
} else {
onScan(packInfo)
}
} else {
onScan(packInfo)
}
}
const onScan = async (packInfo) => {
console.log(packInfo)
//
await getManagementPrecisions([packInfo.itemCode], packInfo.toLocationCode, res => {
if (res.success) {
managementList.value = res.list
managementType.value = managementList.value.some(item => item.ManagementPrecision === 'BY_BATCH') ? 'BY_BATCH' : ''
if (managementType.value === 'BY_BATCH') {
let detail = detailSource.value.find(r => r.itemCode === packInfo.itemCode && r.batch === packInfo.batch && r.inventoryStatus === 'OK')
if (detail === undefined) {
detail = createDetailInfo(packInfo)
detail.packingNumber = ''
detail.packUnit = ''
detailSource.value.unshift(detail)
scanPopupGetFocus()
} else {
let index = detailSource.value.findIndex(r => r.itemCode === packInfo.itemCode && r.batch === packInfo.batch && r.inventoryStatus === 'OK')
if (index >= 0) {
detailSource.value.unshift(detailSource.value.splice(index, 1)[0]) //
detailSource.value[0].qty = calc.add(detailSource.value[0].qty, packInfo.qty)
}
}
} else {
let detail = detailSource.value.find(r => r.itemCode === packInfo.itemCode && r.packingNumber === packInfo.number && r.batch === packInfo.batch && r.inventoryStatus === 'OK')
if (detail === undefined) {
detail = createDetailInfo(packInfo)
detailSource.value.unshift(detail)
scanPopupGetFocus()
} else {
let index = detailSource.value.findIndex(r => r.itemCode === packInfo.itemCode && r.packingNumber === packInfo.number && r.batch === packInfo.batch && r.inventoryStatus === 'OK')
if (index >= 0) {
detailSource.value.unshift(detailSource.value.splice(index, 1)[0]) //
//
comMessageRef.value.showQuestionMessage('该箱码已经扫描,是否要编辑盘点明细?', res => {
if (res) {
closeScanPopup()
edit(detail)
} else {
scanPopupGetFocus()
}
})
}
}
}
}
})
}
const createDetailInfo = (packInfo) => {
return {
scaned: true,
number: jobContent.value.number,
packingNumber: packInfo.number,
batch: packInfo.batch,
inventoryStatus: 'OK',
itemCode: packInfo.itemCode,
itemName: packInfo.itemName,
itemDesc1: packInfo.itemDesc1,
itemDesc2: packInfo.itemDesc2,
projectCode: '',
qty: packInfo.qty,
packUnit: packInfo.packUnit,
packQty: packInfo.packQty,
packUom: packInfo.packUom,
uom: packInfo.uom,
remark: '',
locationCode: fromLocationCode.value,
creator: store.id,
warehouseCode: fromLocation.value.warehouseCode,
areaCode: fromLocation.value.areaCode,
locationGroupCode: fromLocation.value.locationGroupCode,
createTime: new Date().getTime(),
countTime: new Date().getTime(),
countUser: store.id,
countDescription: '',
countQty: packInfo.qty
}
}
const swipeClick = (e, item, index) => {
if (e.content.text === '编辑') {
edit(item)
} else if (e.content.text === '移除') {
remove(item, index)
}
}
const edit = (item) => {
currentEditItem.value = item
item.handleQty = item.qty
countQtyEdit.value.openEditPopup(item, null)
}
const editConfirm = (qty, inventoryStatus, mode) => {
currentEditItem.value.countQty = qty
currentEditItem.value.qty = qty
currentEditItem.value.inventoryStatus = inventoryStatus
openScanPopup()
}
const editClose = () => {
scanPopupGetFocus()
}
const remove = (item, index) => {
scanPopupLoseFocus()
comMessageRef.value.showQuestionMessage('是否要移除扫描信息?', res => {
if (res) {
detailSource.value.splice(index, 1)
}
scanPopupGetFocus()
})
}
const detail = (item) => {
showItem.value = item
detailInfoPopup.value.openPopup(item)
}
const commit = () => {
if (detailSource.value.length === 0) {
comMessageRef.value.showMessage('还未扫描,是否要继续提交', res => {
if (res) {
commitJob()
}
})
} else {
commitJob()
}
}
const commitJob = () => {
uni.showLoading({ title: '提交中....', mask: true })
const params = setParams()
console.log('提交参数', JSON.stringify(params))
countJobSubmit(params)
.then(res => {
uni.hideLoading()
if (res.data === null) {
showCommitSuccessMessage('提交成功')
} else {
showErrorMessage(`提交失败[${res.msg}]`)
}
})
.catch(error => {
uni.hideLoading()
showErrorMessage(error)
})
}
const setParams = () => {
const creator = store.id
jobContent.value.subList = detailSource.value
// jobContent.value.creator = creator;
return jobContent.value
}
const showMessage = (message) => {
scanPopupLoseFocus()
comMessageRef.value.showMessage(message, res => {
if (res) {
afterCloseMessage()
}
})
}
const showErrorMessage = (message) => {
scanPopupLoseFocus()
comMessageRef.value.showErrorMessage(message, res => {
if (res) {
afterCloseMessage()
}
})
}
const showScanMessage = (message) => {
comMessageRef.value.showScanMessage(message)
}
const afterCloseMessage = () => {
scanPopupGetFocus()
}
const closeScanMessage = () => {
scanPopupGetFocus()
}
const showCommitSuccessMessage = (hint) => {
comMessageRef.value.showSuccessMessage(hint, res => {
fromLocationCode.value = ''
fromLocation.value = {}
detailSource.value = []
showFromLocationPopup()
})
}
const getCountStageName = (value) => {
return getCountStageName(value)
}
const isOpenCount = (value) => {
return value === 'TRUE' ? '明盘' : '盲盘'
}
const getCountScopeName = (value) => {
const item = getCountScopeType(value)
return item.label
}
const showQuestionMessage = (message, callback) => {
comMessageRef.value.showQuestionMessage(message, res => {
callback(res)
})
}
</script>
<style scoped lang="scss">
page {
width: 100%;
height: 100%;
background-color: #fff;
}
// .page-wraper {
// display: flex;
// flex-direction: column;
// width: 100%;
// height: 100%;
// }
// .page-main {
// flex: 1;
// position: relative;
// }
// .page-main-scroll {
// position: absolute;
// left: 0;
// right: 0;
// top: 0;
// bottom: 0;
// }
// .page-main-list {
// /* height: 80rpx;
// line-height: 80rpx; */
// text-align: center;
// background: #e0e0e0;
// }
</style>

438
src/pages/count/job/fuzzyCountJob.vue

@ -0,0 +1,438 @@
<template>
<view class="">
<com-empty-view v-if="jobList.length == 0"></com-empty-view>
<job-filter ref="filter" otherTitle="ASN" @switchChangeToday="switchChangeToday" @switchChangeWait="switchChangeWait" @onScanNumber="getScanNumber" :checkedToday="checkedToday" :checkedWaitTask="checkedWaitTask"> </job-filter>
<view v-if="jobList.length > 0">
<uni-swipe-action ref="swipeAction" v-for="(item, index) in jobList" :key="index"
@click="(...event)=>swipeClick(event, item)"
:options="item.status == '2' ? detailGiveupOptions : detailOptions">
<com-fuzzy-count-job-card :dataContent="item" @click="openJobDetail(item)"></com-fuzzy-count-job-card>
</uni-swipe-action>
<job-list-popup ref="jobListPopup" @selectedItem="selectedItem"></job-list-popup>
<job-info-popup ref="jobInfoPopup"></job-info-popup>
<u-loadmore :status="loadingType" />
</view>
<win-scan-button @goScan="openScanPopup" v-if="jobList.length > 0"></win-scan-button>
<winScanPackJob title="库位" ref="scanPopup" @getResult="getScanResult"> </winScanPackJob>
<jobList ref="jobList" @selectItem="selectItem"></jobList>
<comMessage ref="comMessage"></comMessage>
</view>
</template>
<script>
import { cancleTakeCountJob, getFuzzyCountJobList } from '@/api/request2.js'
import { goHome, updateTitle } from '@/common/basic.js'
import { getDetailOption, getDetailGiveupOption } from '@/common/array.js'
import { getCountScopeType } from '@/common/directory.js'
import comEmptyView from '@/mycomponents/common/comEmptyView.vue'
import jobFilter from '@/mycomponents/job/jobFilter.vue'
import comFuzzyCountJobCard from '@/pages/count/coms/comFuzzyCountJobCard.vue'
import jobListPopup from '@/pages/count/coms/jobListPopup.vue'
import jobInfoPopup from '@/pages/count/coms/jobInfoPopup.vue'
import jobList from '@/mycomponents/jobList/jobList.vue'
import winScanButton from '@/mycomponents/scan/winScanButton.vue'
import winScanPackJob from '@/mycomponents/scan/winScanPackJob.vue'
export default {
name: 'receipt',
components: {
comEmptyView,
jobFilter,
comFuzzyCountJobCard,
jobListPopup,
jobInfoPopup,
winScanPackJob,
jobList,
winScanButton
},
data() {
return {
jobList: [],
pageNo: 1,
pageSize: 10,
totalCount: 0,
loadingType: 'nomore',
checkedToday: false,
checkedWaitTask: false,
todayTime: '',
status: '1,2', //
detailOptions: [],
detailGiveupOptions: [],
title: '',
countScopeTypeDic: []
}
},
onLoad(option) {
this.title = option.title
},
onShow() {
this.getList('refresh')
},
onReady() {
this.detailOptions = getDetailOption()
this.detailGiveupOptions = getDetailGiveupOption()
this.countScopeTypeDic = getCountScopeType()
},
onReachBottom() {
//
if (this.loadingType == 'loading' || this.loadingType == 'nomore') {
return
}
this.getList('more')
},
onPullDownRefresh() {
this.getList('refresh')
},
// 退
onBackPress(options) {
if (options.from === 'navigateBack') {
uni.navigateBack({
delta: 1
})
return false
}
},
//
onNavigationBarButtonTap(e) {
if (e.index === 0) {
goHome()
} else if (e.index == 1) {
this.$refs.filter.openFilter()
}
},
methods: {
getList(type) {
const that = this
uni.showLoading({
title: '加载中­....',
mask: true
})
this.loadingType = 'loading'
if (type === 'refresh') {
this.pageNo = 1
this.jobList = []
}
const filters = []
if (this.checkedToday) {
filters.push({
column: 'create_time',
action: 'between',
value: this.todayTime
})
}
filters.push({
column: 'status',
action: 'in',
value: this.status
})
filters.push({
column: 'isOpenCount',
action: '==',
value: 'FALSE'
})
// filters.push({
// column: "accept_user_id",
// action: "==",
// value: this.$store.state.user.id
// })
const params = {
filters,
pageNo: this.pageNo,
pageSize: this.pageSize,
sort: 'number',
by: 'DESC'
}
getFuzzyCountJobList(params)
.then((res) => {
uni.hideLoading()
if (type === 'refresh') {
uni.stopPullDownRefresh()
}
const { list } = res.data
this.totalCount = res.data.total
updateTitle(`${this.title}(${this.totalCount})`)
this.loadingType = 'loadmore'
if (list == null || list.length == 0) {
this.loadingType = 'nomore'
return
}
this.jobList = type === 'refresh' ? list : this.jobList.concat(list)
// this.jobList[0].countRange = [{
// type: "LOCATION_CODE",
// value: "902,903"
// }, {
// type: "ITEMS_CODE",
// value: "123"
// }]
// this.jobList[1].countRange = [{
// type: "AREABASIC_CODE",
// value: "101"
// }, {
// type: "ITEMS_CODE",
// value: "123"
// }];
this.pageNo++
})
.catch((error) => {
if (type === 'refresh') {
uni.stopPullDownRefresh()
}
updateTitle(this.title)
this.loadingType = ''
uni.hideLoading()
that.showMessage(error)
})
},
getCountRange(value) {
if (value == undefined || value == null) return ''
const rangeList = []
value.forEach((r) => {
const item = rangeList.find((l) => l.type == r.type)
if (item != undefined) {
item.value = `${item.value},${r.value}`
} else {
const data = {
typeCode: r.type,
typeName: getDescFromDic(r.type),
value: r.value
}
rangeList.push(r)
}
})
return rangeList
},
openJobDetail(item) {
uni.navigateTo({
url: `./fuzzyCountDetail?id=${item.id}&status=${item.status}&title=${this.title}`
})
},
showItemList(itemList) {
this.$refs.jobListPopup.openPopup(itemList)
},
selectedItem(item) {
this.openJobDetail(item)
},
openScanPopup() {
this.$refs.scanPopup.openScanPopup()
},
selectItem(item) {
this.$refs.scanPopup.closeScanPopup()
this.openJobDetail(item)
},
swipeClick(e, dataContent) {
if (e.content.text == '详情') {
this.openjobInfoPopup(dataContent)
} else if (e.content.text == '放弃') {
this.$refs.comMessage.showQuestionMessage('确定要放弃当前任务?', (res) => {
if (res) {
this.cancleJob(dataContent.id)
}
})
}
},
openjobInfoPopup(item) {
this.$refs.jobInfoPopup.openPopup(item)
},
cancleJob(id) {
cancleTakeCountJob(id)
.then((res) => {
if (res.data) {
this.getList('refresh')
uni.showToast({
title: '放弃任务成功'
})
} else {
this.showMessage('放弃任务失败')
}
})
.catch((error) => {
this.showMessage(error)
})
},
switchChangeToday(state, creationTime) {
this.checkedToday = state
this.todayTime = creationTime
this.getList('refresh')
},
switchChangeWait(state, jobStatus) {
this.checkedWaitTask = state
this.status = jobStatus
this.getList('refresh')
},
getScanNumber(code) {
this.getDataListByType(code)
},
getDataListByType(code) {
const that = this
uni.showLoading({
title: '加载中....',
mask: true
})
const filters = []
filters.push({
column: 'status',
action: 'in',
value: '1,2'
})
filters.push({
column: 'number',
action: '==',
value: code
})
filters.push({
column: 'isOpenCount',
action: '==',
value: 'FALSE'
})
// filters.push({
// column: "countSplitType",
// action: "==",
// value: "locationCode"
// })
// filters.push({
// column: "accept_user_id",
// action: "==",
// value: this.$store.state.user.id
// })
const params = {
filters,
pageNo: 1,
pageSize: 100,
sort: 'number',
by: 'DESC'
}
getFuzzyCountJobList(params)
.then((res) => {
uni.hideLoading()
if (res.data.list.length == 0) {
that.showMessage('未查找到' + `${code}】的收货任务`)
} else if (res.data.list.length == 1) {
that.openJobDetail(res.data.list[0])
}
})
.catch((error) => {
uni.hideLoading()
that.showMessage(error)
})
},
showMessage(message) {
this.$refs.comMessage.showErrorMessage(message, (res) => {
if (res) {
}
})
},
getScanResult(result) {
const that = this
uni.showLoading({
title: '加载中....',
mask: true
})
const filters = []
filters.push({
column: 'status',
action: 'in',
value: '1,2'
})
filters.push({
column: 'isOpenCount',
action: '==',
value: 'FALSE'
})
// filters.push({
// column: "countSplitType",
// action: "==",
// value: "locationCode"
// })
// filters.push({
// column: "countSplitCode",
// action: "==",
// value: result.label.code
// })
// filters.push({
// column: "accept_user_id",
// action: "==",
// value: this.$store.state.user.id
// })
const params = {
filters,
pageNo: 1,
pageSize: 1000,
sort: 'number',
by: 'DESC'
}
getFuzzyCountJobList(params)
.then((res) => {
uni.hideLoading()
const resultList = res.data.list
resultList.forEach((item) => {
item.title = item.number
item.selected = false
})
const list = []
resultList.forEach((item) => {
if (!list.find((subItem) => subItem.title == item.title)) {
list.push(item)
}
})
if (list.length == 0) {
that.showMessage('未查找到库位' + `${result.label.code}】的盘点任务`)
} else if (list.length == 1) {
that.selectItem(list[0])
} else {
that.$refs.jobList.openList(list)
}
})
.catch((error) => {
uni.hideLoading()
that.showMessage(error)
})
}
}
}
</script>
<style scoped lang="scss"></style>
s

21
src/pages/customerReturn/coms/comReturnRecordCard.vue

@ -0,0 +1,21 @@
<template>
<recordComMainCard :dataContent="dataContent">
<recordComDetailCard :dataContent="dataContent"></recordComDetailCard>
</recordComMainCard>
</template>
<script setup lang="ts">
import recordComMainCard from '@/mycomponents/receive/recordComMainCard.vue'
import recordComDetailCard from '@/mycomponents/receive/recordComDetailCard.vue'
const props = defineProps({
dataContent: {
type: Object,
default: {}
}
})
</script>
<style lang="scss">
</style>

306
src/pages/customerReturn/record/recordList.vue

@ -0,0 +1,306 @@
<template>
<view class="uni-flex" style="flex-direction: column;;">
<job-filter ref="filter" otherTitle="ASN" :isShowProductionLineCode="false" :isShowItemCode="false"
:isShowQurery='true' @onQuery="getListByFilter">
</job-filter>
<com-empty-view v-if="recordList.length==0"></com-empty-view>
<view v-if="recordList.length>0">
<u-swipe-action ref="swipeAction" v-for="(item, index) in recordList" :key="index">
<comReturnRecordCard :dataContent="item" @click='openJobDetail(item)'></comReturnRecordCard>
</u-swipe-action>
<job-list-popup ref="jobListPopup" @selectedItem="selectedItem"></job-list-popup>
<job-info-popup ref='jobInfoPopup'></job-info-popup>
<u-loadmore :status="loadingType" />
</view>
<win-scan-button @goScan='openScanPopup' v-if="recordList.length>0"></win-scan-button>
<winScanPackJob ref="scanPopup" @getResult='getScanResult'></winScanPackJob>
<jobList ref="recordList" @selectItem="selectItem"></jobList>
<comMessage ref="comMessageRef"></comMessage>
</view>
</template>
<script setup lang="ts">
import {getCustomerReturnRecordList, cancleTakeProductionReceiptJob,} from '@/api/request2.js';
import {goHome, updateTitle} from '@/common/basic.js';
import {
planRefreshTime,
productionReceiptJobFilter
} from '@/common/config.js';
import {getDetailOption, getDetailGiveupOption} from '@/common/array.js';
import comEmptyView from '@/mycomponents/common/comEmptyView.vue'
import jobFilter from '@/mycomponents/job/jobFilter.vue'
import comReturnRecordCard from '@/pages/customerReturn/coms/comReturnRecordCard.vue'
import jobListPopup from '@/pages/productionReceipt/coms/jobListPopup.vue'
import jobInfoPopup from '@/pages/productionReceipt/coms/jobInfoPopup.vue'
import winScanButton from '@/mycomponents/scan/winScanButton.vue'
import winScanPackJob from "@/mycomponents/scan/winScanPackJob.vue"
import jobList from '@/mycomponents/jobList/jobList.vue'
import { ref,} from 'vue';
import { onLoad, onShow, onReady, onReachBottom, onPullDownRefresh, onBackPress, onNavigationBarButtonTap } from '@dcloudio/uni-app';
const recordList = ref([]);
const pageNo = ref(1);
const pageSize = ref(10);
const totalCount = ref(0);
const loadingType = ref("nomore");
const checkedToday = ref(false);
const checkedWaitTask = ref(false);
const todayTime = ref("");
const detailOptions = ref([]);
const detailGiveupOptions = ref([]);
const title = ref('');
const scanMessage = ref("");
const filterItemCode = ref("");
const queryParams = ref({
creationTime: "",
receiveStatus: "",
itemCode: ""
});
const filter = ref(null);
const jobListPopup = ref(null);
const jobInfoPopup = ref(null);
const comMessageRef = ref(null);
const scanPopup = ref(null);
const recordListRef = ref(null);
onLoad((option) => {
title.value = option.title;
});
onShow(() => {
getList('refresh');
});
onReady(() => {
detailOptions.value = getDetailOption();
detailGiveupOptions.value = getDetailGiveupOption();
});
onReachBottom(() => {
//
if (loadingType.value === 'loading' || loadingType.value === 'nomore') return;
getList('more');
});
onPullDownRefresh(() => {
getList('refresh');
});
onBackPress((options) => {
if (options.from === 'navigateBack') {
uni.navigateBack({ delta: 1 });
return false;
}
});
onNavigationBarButtonTap((e) => {
if (e.index === 0) {
goHome();
} else if (e.index === 1) {
filter.value.openFilter();
}
});
const setQueryParam = () => {
const filterParams = [];
//
if (queryParams.value.creationTime) {
filterParams.push({
column: "create_time",
action: "between",
value: queryParams.value.creationTime
});
}
//
if (queryParams.value.receiveStatus) {
filterParams.push({
column: "receiveStatus",
action: "in",
value: queryParams.value.receiveStatus
});
} else {
filterParams.push({
column: "receiveStatus",
action: "in",
value: "0"
});
}
//
if (queryParams.value.itemCode) {
filterParams.push({
column: "itemCode",
action: "like",
value: queryParams.value.itemCode
});
filterItemCode.value = queryParams.value.itemCode;
} else if (filterItemCode.value) {
filterParams.push({
column: "itemCode",
action: "like",
value: filterItemCode.value
});
}
return filterParams;
};
const getList = (type) => {
uni.showLoading({ title: "加载中­....", mask: true });
loadingType.value = "loading";
if (type === "refresh") {
pageNo.value = 1;
recordList.value = [];
}
const queryFiltersParams = setQueryParam();
const params = {
filters: queryFiltersParams,
pageNo: pageNo.value,
pageSize: pageSize.value,
};
console.log("查询条件", JSON.stringify(params));
getCustomerReturnRecordList(params).then((res) => {
uni.hideLoading();
if (type === "refresh") {
uni.stopPullDownRefresh();
}
const list = res.data.list;
totalCount.value = res.data.total;
updateTitle(`${title.value} (${totalCount.value})`);
loadingType.value = "loadmore";
if (!list || list.length === 0) {
loadingType.value = "nomore";
return;
}
list.forEach((item) => {
item.packingNumber = item.toPackingNumber;
});
recordList.value = type === "refresh" ? list : [...recordList.value, ...list];
pageNo.value++;
}).catch((error) => {
if (type === "refresh") {
uni.stopPullDownRefresh();
}
loadingType.value = "";
updateTitle(title.value);
uni.hideLoading();
showMessage(error);
});
};
const openJobDetail = (item, scanMessage = '') => {
uni.navigateTo({
url: `./recordListDetail?id=${item.masterId}&receiveStatus=${item.receiveStatus}&scanMessage=${scanMessage}&title=${title.value}`
});
scanMessage.value = "";
};
const showItemList = (itemList) => {
jobListPopup.value.openPopup(itemList);
};
const selectedItem = (item) => {
openJobDetail(item);
};
const openjobInfoPopup = (item) => {
jobInfoPopup.value.openPopup(item);
};
const showMessage = (message) => {
if (scanPopup.value) {
scanPopup.value.packLoseFocus();
}
comMessageRef.value.showErrorMessage(message, (res) => {
if (res && scanPopup.value) {
scanPopup.value.packGetFocus();
}
});
};
const openScanPopup = () => {
scanPopup.value.openScanPopup();
};
const selectItem = (item) => {
scanPopup.value.closeScanPopup();
openJobDetail(item, scanMessage.value);
};
const getScanResult = (result) => {
try {
scanMessage.value = "";
const filters = [
{ column: "toPackingNumber", action: "in", value: `${result.package.number},${result.package.parentNumber}` },
{ column: "receiveStatus", action: "in", value: '0' },
{ column: "toBatch", action: "==", value: result.label.batch },
{ column: "itemCode", action: "==", value: result.label.itemCode },
];
getCustomerReturnRecordList({
filters: filters,
pageNo: 1,
pageSize: 100,
}).then((res) => {
scanMessage.value = result.scanMessage;
const resultList = res.data.list;
if (resultList.length > 0) {
resultList.forEach((item) => {
item.title = item.number;
item.selected = false;
});
const list = [];
resultList.forEach((item) => {
if (!list.find((subItem) => subItem.title === item.title)) {
list.push(item);
}
});
if (list.length > 1) {
recordListRef.value.openList(list);
} else {
selectItem(list[0]);
}
} else {
showMessage(`未查找到任务\n扫描[${result.scanMessage}]`);
}
}).catch((error) => {
showMessage(`${error}\n扫描[${result.scanMessage}]`);
});
} catch (e) {
showMessage(e.message);
}
};
const getListByFilter = (params) => {
queryParams.value.creationTime = params.creationTime;
queryParams.value.receiveStatus = params.receiveStatus;
queryParams.value.itemCode = params.itemCode;
getList('refresh');
};
</script>
<style scoped lang="scss">
</style>

401
src/pages/customerReturn/record/recordListDetail.vue

@ -0,0 +1,401 @@
<template>
<view class="page-wraper">
<view class="page-main">
<view class="page-header">
<view class="header-view">
<view class="header_job_top">
<receive-top :dataContent="recordContent"></receive-top>
</view>
</view>
</view>
<view v-if="detailSource.length>0" class="uni-flex uni-row "
style=";margin-top: 15rpx; margin-bottom: 15rpx; margin-left: 20rpx; text-align: right;">
<view class="font_default" style="display: block; font-weight: bold;">
整单接收
</view>
<view class="uni-flex" style="margin-left: 20rpx; align-items: center; text-align: center;">
<u-switch v-model="isAllReceived" active-color="#5FCB94" inactive-color="#eee" size="35"
@change="switchChange"></u-switch>
</view>
</view>
<scroll-view scroll-y="true">
<view class="detail-list" v-for="(item, index) in detailSource" :key="item.id">
<view class="">
<com-detail-card :dataContent="item" :index="index" :settingParam="recordContent"
@remove="updateData" :isShowToLocation="true" @updateData="updateData"
@openDetail="openDetail">
</com-detail-card>
<view class='split_line'></view>
</view>
</view>
</scroll-view>
</view>
<view class="page-footer">
<view class="uni-flex u-col-center space-between padding_10"
style="background-color:ghostwhite; width: 100%; ">
<view class=" uni-flex uni-row">
<button class="btn_single_commit" style="width: 280rpx;" hover-class="btn_commit_after"
@click="reject">拒绝
</button>
</view>
<view class=" uni-flex uni-row">
<button class="btn_single_commit" style="width: 280rpx;" hover-class="btn_commit_after"
@click="receive" :disabled="receiveDisable">接收
</button>
</view>
</view>
</view>
<win-scan-button @goScan='openScanPopup'></win-scan-button>
<win-scan-pack ref="scanPopup" @getResult='getScanResult' headerType="HPQ,HMQ">></win-scan-pack>
<detail-info-popup ref="detailInfoPopup"></detail-info-popup>
<comMessage ref="comMessageRef"></comMessage>
</view>
</template>
<script setup lang="ts">
import {
getCustomerReturnRecordDetail,
customerReturnRecordRefuse,
customerReturnRecordReceive,
} from '@/api/request2.js';
import {
goHome,
navigateBack,
getCurrDateTime,
getInventoryStatusName,
getSwitchInfoByCode
} from '@/common/basic.js';
import {
getDataSource,
calcHandleQty,
getScanCount
} from '@/common/detail.js';
import winScanButton from '@/mycomponents/scan/winScanButton.vue'
import comDetailCard from "@/mycomponents/detail/comDetailCard.vue"
import detailInfoPopup from '@/pages/productionReceipt/coms/detailInfoPopup.vue'
import receiveTop from '@/mycomponents/receive/receiveTop.vue'
import winScanPack from '@/mycomponents/scan/winScanPack.vue'
import {ref} from 'vue';
import {
onLoad,
onBackPress,
onNavigationBarButtonTap
} from '@dcloudio/uni-app';
const id = ref(null);
const isAllReceived = ref(false);
const receiveDisable = ref(true);
const recordContent = ref(null);
const subList = ref([]);
const detailSource = ref([]);
const scanCount = ref(0);
const detailInfoPopup = ref(null);
const scanPopup = ref(null);
const comMessageRef = ref(null);
onLoad((option) => {
uni.setNavigationBarTitle({
title: option.title + '详情'
});
id.value = option.id;
if (id.value !== undefined) {
//
if (option.receiveStatus === "0") {
getDetail();
}
}
});
onNavigationBarButtonTap((e) => {
if (e.index === 0) {
goHome();
}
});
onBackPress((e) => {
//
if (e.from === 'backbutton') {
uni.navigateBack();
return true;
}
});
//
const getDetail = () => {
uni.showLoading({title: "加载中....", mask: true});
getCustomerReturnRecordDetail(id.value).then((res) => {
uni.hideLoading();
isAllReceived.value = false;
receiveDisable.value = true;
if (res.data == null) {
showMessage('未获取到详情');
} else {
if (res.data.list.length > 0) {
recordContent.value = res.data.list[0];
subList.value = res.data.list;
subList.value.forEach((item) => {
item.batch = item.toBatch;
item.packingNumber = item.toPackingNumber;
});
detailSource.value = getDataSource(subList.value);
} else {
showMessage('列表数据为0');
}
}
}).catch((error) => {
uni.hideLoading();
showErrorMessage(error);
});
};
const calcHandleQty = () => {
calcHandleQty(detailSource.value);
updateBtn();
continueScan();
};
const updateBtn = () => {
scanCount.value = getScanCount(subList.value);
//
if (scanCount.value === subList.value.length) {
receiveDisable.value = false;
} else {
receiveDisable.value = true;
}
};
const continueScan = () => {
scanCount.value = getScanCount(subList.value);
if (scanCount.value === subList.value.length) {
closeScanPopup();
} else {
scanPopupGetFocus();
}
};
const updateData = () => {
calcHandleQty();
updateBtn();
};
const openDetail = (item) => {
detailInfoPopup.value.openPopup(item);
};
const openScanPopup = () => {
scanPopup.value.openScanPopup();
};
const closeScanPopup = () => {
scanPopup.value.closeScanPopup();
};
const getScanResult = (result) => {
try {
const itemCode = result.label.itemCode;
const packingNumber = result.package.number;
const batch = result.label.batch;
const detail = detailSource.value.find((r) => r.itemCode === itemCode);
if (detail === undefined) {
showErrorMessage(`物料号【${itemCode}】不在列表中`);
} else {
const itemDetail = detail.subList.find((r) => r.packingNumber === packingNumber && r.batch === batch);
if (itemDetail === undefined) {
showErrorMessage(`箱码[${packingNumber}]批次[${batch}]不在列表中`);
} else {
if (itemDetail.scaned) {
showErrorMessage(`箱码[${packingNumber}]批次[${batch}]已经扫描`);
} else {
itemDetail.scaned = true;
itemDetail.handleQty = Number(itemDetail.qty);
calcHandleQty();
}
}
}
} catch (e) {
showMessage(e.message);
}
};
const reject = () => {
showQuestionMessage("是否拒绝接收?", (res) => {
if (res) {
uni.showLoading({title: "提交中....", mask: true});
customerReturnRecordRefuse(id.value).then((res) => {
uni.hideLoading();
if (res.data) {
showCommitSuccessMessage("拒绝成功");
} else {
showErrorMessage(`拒绝失败[${res.msg}]`);
}
}).catch((error) => {
uni.hideLoading();
showErrorMessage(error);
});
}
});
};
const receive = () => {
scanCount.value = getScanCount(subList.value);
if (scanCount.value === 0) {
showErrorMessage("扫描数为0,请先扫描");
return;
}
if (scanCount.value < subList.value.length) {
showErrorMessage("还有未扫描的数据,请先扫描");
return;
}
//
if (scanCount.value === subList.value.length) {
receiveSubmit();
}
};
const showMessageHint = (hint, callback) => {
comMessageRef.value.showErrorMessage(hint, (res) => {
if (res) {
callback();
}
});
};
const receiveSubmit = () => {
uni.showLoading({title: "提交中....", mask: true});
customerReturnRecordReceive(id.value).then((res) => {
uni.hideLoading();
if (res.data) {
showCommitSuccessMessage("接收成功");
} else {
showErrorMessage(`接收失败[${res.msg}]`);
}
}).catch((error) => {
uni.hideLoading();
showErrorMessage(error);
});
};
const showMessage = (message) => {
setTimeout(() => {
scanPopupLoseFocus();
comMessageRef.value.showMessage(message, (res) => {
if (res) {
afterCloseMessage();
}
});
});
};
const showErrorMessage = (message) => {
setTimeout(() => {
scanPopupLoseFocus();
comMessageRef.value.showErrorMessage(message, (res) => {
if (res) {
afterCloseMessage();
}
});
});
};
const showQuestionMessage = (message, callback) => {
setTimeout(() => {
scanPopupLoseFocus();
comMessageRef.value.showQuestionMessage(message, (res) => {
if (res) {
callback(res);
}
});
});
};
const scanPopupGetFocus = () => {
if (scanPopup.value) {
scanPopup.value.getfocus();
}
};
const scanPopupLoseFocus = () => {
if (scanPopup.value) {
scanPopup.value.losefocus();
}
};
const afterCloseMessage = () => {
scanPopupGetFocus();
};
const showCommitSuccessMessage = (hint) => {
comMessageRef.value.showSuccessMessage(hint, (res) => {
navigateBack(1);
});
};
const switchChange = (isOn) => {
isAllReceived.value = isOn;
if (isAllReceived.value) {
detailSource.value.forEach((item) => {
item.subList.forEach((info) => {
info.scaned = true;
info.handleQty = Number(info.qty);
});
});
calcHandleQty();
} else {
comMessageRef.value.showQuestionMessage("是否要关闭整单收货?", (res) => {
if (res) {
getDetail();
} else {
isAllReceived.value = true;
}
});
}
};
</script>
<style scoped lang="scss">
page {
width: 100%;
height: 100%;
background-color: #fff;
}
.page-wraper {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
}
.page-main {
flex: 1;
position: relative;
}
.page-main-scroll {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
.page-main-list {
/* height: 80rpx;
line-height: 80rpx; */
text-align: center;
background: #e0e0e0;
}
</style>

150
src/pages/deliver/coms/comDeliverDetailCardBatch.vue

@ -0,0 +1,150 @@
<template>
<view>
<u-collapse ref="collapse">
<u-collapse-item :open="true" :class="dataContent.scaned?'scan_view':''">
<template #title>
<view class="split_line"></view>
<item-qty :dataContent="item" :handleQty="item.handleQty" :isShowBalanceQty="false"></item-qty>
</template>
<view v-for="(item,index) in dataContent.subList" style="margin-top: 10px;">
<u-swipe-action ref="swipeAction"
:options="(item.scaned&&isEdit)?editAndRemoveOptions : item.scaned? removeOptions:options"
@click="(...event)=>itemCoceClick(event,item,index)">
<view class="" :class="item.scaned?'scan_view':''">
<recommend :detail="item" :isShowLocation="false" :isShowFromLocation="true" :isShowToLocation="settingParam.allowModifyLocation=='TRUE'"></recommend>
</view>
</u-swipe-action>
</view>
</u-collapse-item>
</u-collapse>
<!-- <requiredLocation title="需求库位" :locationCode="dataContent.toLocationCode"
:isShowEdit="dataContent.allowModifyLocation==1"></requiredLocation> -->
</view>
<recommend-qty-edit ref="receiptEdit" :dataContent="editItem" :settingParam="settingParam" @confirm="confirm">
</recommend-qty-edit>
<detail-info-popup ref="detailInfoPopup"></detail-info-popup>
<comMessage ref="message"></comMessage>
</template>
<script setup lang="ts">
import itemQty from '@/mycomponents/item/itemQty.vue'
import recommend from '@/mycomponents/recommend/recommend.vue'
import RecommendBalance from '@/mycomponents/balance/recommendBalance.vue'
import handleBalance from '@/mycomponents/balance/handleBalance.vue'
import RecommendQtyEdit from '@/mycomponents/qty/recommendQtyEdit.vue'
import jobDetailPopup from '@/mycomponents/job/jobDetailPopup.vue'
import requiredLocation from '@/mycomponents/location/requiredLocation.vue'
import balanceQtyEdit from '@/mycomponents/qty/balanceQtyEdit.vue'
import location from '@/mycomponents/balance/location.vue'
import detailInfoPopup from '@/pages/productionReceipt/coms/detailInfoPopup.vue'
import comIssueRequestInfo from '@/pages/issue/coms/comIssueRequestInfo.vue'
import batch from '@/mycomponents/balance/batch.vue'
import qtyEdit from '@/mycomponents/qty/qtyEdit.vue'
import {
getDetailOption,
getRemoveOption,
getEditRemoveOption
} from '@/common/array.js';
import {ref, nextTick, onMounted} from 'vue';
const props = defineProps({
dataContent: {
type: Array,
default: () => ([])
},
settingParam: {
type: Object,
default: () => ({})
},
isEdit: {
type: Boolean,
default: true
}
});
const emit = defineEmits(['updateData','removeItemCode']);
const option = ref([]);
const showItem = ref({});
const editItem = ref({});
const batchItem = ref({});
const detailOptions = ref([]);
const scanOptions = ref([]);
const removeOptions = ref([]);
const editAndRemoveOptions = ref([]);
const collapse = ref(null);
const receiptEdit = ref(null);
const receiptHint = ref(null);
const message = ref(null);
onMounted(() => {
detailOptions.value = getDetailOption();
scanOptions.value = getEditRemoveOption();
removeOptions.value = getRemoveOption();
editAndRemoveOptions.value = getEditRemoveOption();
});
const resizeCollapse = () => {
nextTick(() => {
collapse.value.init()
collapse.value.childrens.forEach(r => {
r.init();
});
});
};
const swipeClick = (e, batch,
record,recordIndex,
batchIndex,
Batchs,
locatonIndex,
Locations) => {
if (e.content.text == "编辑") {
edit(batch, record)
} else if (e.content.text == "移除") {
remove(batch, record, recordIndex,batchIndex,Batchs,locatonIndex,Locations)
}
}
const itemCoceClick = (e, item, index) => {
if (e.content.text === "编辑") {
edit(item);
} else if (e.content.text === "移除") {
item.scaned = false
item.handleQty=0
emit('updateData')
}
};
const edit = (item) => {
editItem.value = item;
receiptEdit.value.openTaskEditPopup(item.qty, item.handleQty, item.labelQty);
};
const detail = (item) => {
showItem.value = item;
receiptHint.value.openScanPopup();
};
const remove = (batch, record, recordIndex,batchIndex,Batchs,locatonIndex,Locations) => {
message.value.showQuestionMessage("确定移除扫描信息?", (res) => {
if (res) {
batch.Records.splice(recordIndex, 1);
if(batch.Records.length==0&&Batchs[batchIndex].isNewAdd){
Batchs.splice(batchIndex,1)
}
if(batch.Records.length==0&&Locations[locatonIndex].isNewAdd){
Locations.splice(locatonIndex,1)
}
resizeCollapse();
emit('updateData', record)
}
});
};
const confirm = (val) => {
editItem.value.handleQty = Number(val);
emit('updateData', editItem.value);
};
</script>
<style>
</style>

780
src/pages/deliver/coms/comScanDeliverPackBatch.vue

@ -0,0 +1,780 @@
<template>
<view>
<u-popup v-model="show" mode="bottom" :maskClick='false'>
<view class="">
<view class="popup_box">
<view class="pop_title uni-flex space-between">
<view class="" style="font-size: 35rpx;">
扫描箱码
</view>
<view class="">
<image class="fr icons_scan_close" src="/static/icons/icons_scan_close.svg"
@click="closeScanPopup()"></image>
</view>
</view>
<!-- <view class="uni-flex uni-row" style="align-items: center;
background-color: #fff;
margin-left: 20rpx;
margin-right: 20rpx;
padding:20rpx;
border-radius: 8rpx;">
<view class="uni-center">
位置 :
</view>
<view class="" style="width: 75%;padding: 0rpx">
<view class="uni-flex u-col-center uni-row" @click="showSelect">
<view class="" style="margin-left: 15rpx;font-size: 30rpx;">
{{positionInfo}}
</view>
<u-select v-model="show" mode="mutil-column-auto" :list="positionList" :defaultValue="defaultValueList"
@confirm="confirmSelect"></u-select>
</view>
</view>
</view>
<u-line class='line_color'></u-line> -->
<!--<view class="uni-flex uni-row" style="align-items: center;
background-color: #fff;
margin-left: 20rpx;
margin-right: 20rpx;
margin-top: 8rpx;
border-radius: 8rpx;">
<view class="uni-center" style="width: 25%; ">
来源库位
</view>
<view class="" style="width: 75%; padding: 8rpx;">
<uni-combox :candidates="fromLocationList" v-model="fromLocationCode" placeholder="请选择库位"
@confirm="fromLocationUpdate"></uni-combox>
</view>
</view>-->
<view class="">
<view class="">
<win-com-scan ref="comscan" placeholder="箱标签" @getResult="onScan" :clearResult="true"
headerType="HPQ,HMQ" :isShowHistory="false" :locationCode='locationCode'>
</win-com-scan>
<view style="width: 100%;">
<view style="width: 100%;" v-if="issueRecord.length>0">
<view class="uni-flex uni-row space-between u-col-center">
<view class="" style="padding: 10rpx;">
历史记录
</view>
<view class="" style="padding-right: 10rpx;">
<u-icon :name="expendIcon" size="35rpx" @click="expands()"></u-icon>
</view>
</view>
<u-line class='line_color' style='padding-top: 10rpx;padding-bottom: 20rpx;'>
</u-line>
<scroll-view scroll-y="true" class="scroll-view"
v-if="expand&&issueRecord.length>0">
<view class="uni-flex u-col" v-for="(record,index) in issueRecord">
<view style="width: 100%;">
<u-swipe-action ref="swipeAction" :options="scanOptions"
@click="(...event)=>swipeClick(event,record,index)">
<view style="padding: 0px 10px">
<balance :dataContent="record" :isShowFromLocation="false"
:isShowStdPack="false"></balance>
</view>
</u-swipe-action>
<u-line class='line_color'></u-line>
</view>
</view>
</scroll-view>
</view>
</view>
</view>
</view>
</view>
</view>
</u-popup>
<balance-select ref="balanceSelect" @onSelectItem='selectBalanceItem'></balance-select>
<comMessage ref="comMessage"></comMessage>
<balance-qty-edit ref="balanceQtyEdit" @confirm="confirm" :isShowStatus="true"></balance-qty-edit>
<!-- 模拟扫描功能 -->
<!-- <win-com-scan v-show="false" ref="comscansimulate" placeholder="箱标签" @getResult="onScan" :clearResult="true"
headerType="HPQ,HMQ" :isShowHistory="false">
</win-com-scan> -->
</view>
</template>
<script setup lang="ts">
import winComScan from '@/mycomponents/scan/winComScan.vue'
import balance from '@/mycomponents/balance/balance.vue'
import balanceQtyEdit from '@/mycomponents/qty/balanceQtyEdit.vue'
import BalanceSelect from '@/mycomponents/balance/balanceSelect.vue'
import {
getDetailOption,
getDetailEditRemoveOption
} from '@/common/array.js';
import {
getDirectoryItemArray,
getListLocationAreaTypeDesc,
getInventoryStatusDesc
} from '@/common/directory.js';
import {
getLabelInfo
} from '@/common/label.js';
import {
calc
} from '@/common/calc.js';
import {
getWorkShopLineStation,
getBalanceByFilter,
getBalanceByParams,
} from '@/api/request2.js';
import {
uniqueArray
} from '@/common/basic.js';
import {
getBalanceByManagementPrecision
} from '@/common/balance.js';
import {ref, onMounted} from 'vue';
const props = defineProps({
title: {
type: String,
default: ''
},
locationCode:{
type: String,
default: ''
}
})
const emit = defineEmits(['closeScan','afterScan'])
const detailOptions = ref(getDetailOption());
const scanOptions = ref(getDetailEditRemoveOption());
const issueRecord = ref([]);
const dataContent = ref(null);
const jobContent = ref(null);
const positionInfo = ref('');
const show = ref(false)
const toLocation = ref([]);
const toLocationCode = ref('');
const fromLocationList = ref([]);
const fromLocationCode = ref('');
const packageInfo = ref(null);
const label = ref(null);
const expand = ref(false);
const expendIcon = ref('arrow-up');
const editItem = ref(null);
const showItem = ref(null);
const fromInventoryStatuses = ref();
const balanceSelect = ref(null)
const comMessage = ref(null)
const toLocationCombox = ref(null)
const comscan = ref(null)
const balanceQtyEdit = ref(null)
const receiptHint = ref(null)
const inputStyleObject = ref({
fontSize: "100rpx"
})
const bussinessCode = ref('Issue')
const toLocationAreaTypeList = ref([])
onMounted(() => {
detailOptions.value = getDetailOption();
scanOptions.value = getDetailEditRemoveOption();
});
const openScanPopupForJobSimulate = (content, jobcontent, scanMessage)=> {
issueRecord.value = [];
dataContent.value = content;
jobContent.value = jobcontent;
initData();
getLabelInfo(scanMessage, "HPQ,HMQ", callback => {
if (callback.success) {
onScan(callback);
} else {
showErrorMessage(callback.message, res => {})
}
})
}
const openScanPopup = (content, jobcontent) => {
issueRecord.value = [];
dataContent.value = content;
jobContent.value = jobcontent;
initData();
// positionInfo.value = jobContent.value.workShopCode + "-" + jobContent.value.subList[0].productionLineCode +
// "-" + jobContent.value.subList[0].workStationCode;
show.value = true
setTimeout(() => {
getfocus();
}, 500);
};
const closeScanPopup = () => {
losefocus();
show.value = false
emit("closeScan");
//
// Object.assign(data, options.data());
};
const initData = () => {
fromLocationList.value = [];
if (dataContent.value != null) {
fromInventoryStatuses.value = getDirectoryItemArray(jobContent.value.outInventoryStatuses);
toLocation.value = dataContent.value.subList;
toLocationCode.value = dataContent.value.subList[0].toLocationCode;
toLocationAreaTypeList.value = getDirectoryItemArray(jobContent.value.toAreaTypes)
// fromLocationList.value = getFromLocationList();
}
};
const showBalanceSelect = (items) => {
balanceSelect.value.openPopup(items);
};
// const getFromLocationList = () => {
// let list = [];
// let location = dataContent.value.subList.find(r => r.toLocationCode == toLocationCode.value);
// if (location != undefined) {
// dataContent.value.subList.forEach(item => {
// list.push(item.fromLocationCode);
// });
// fromLocationCode.value = list[0];
// return list;
// } else {
// comMessage.value.showErrorMessages('' + toLocationCode.value + '', res => {
// toLocationCode.value = '';
// });
// }
// };
const fromLocationUpdate = (fromlocation) => {
let location = fromLocationList.value.find(r => r == fromlocation)
if (location == undefined) {
fromLocationCode.value = ''
showErrorMessage('发货库位【' + fromlocation + '】不存在')
}
};
const queryBalance = (result) => {
try {
// if (fromLocationCode.value == '') {
// showErrorMessage('', res => {
// toLocationCombox.value.onFocus();
// });
// return;
// }
let packageInfoValue = result.package;
let itemCode = result.label.itemCode;
let packingCode = result.label.packingNumber;
let lot = result.label.batch;
let item = toLocation.value.Items.find(r => r.itemCode == itemCode);
if (item == undefined) {
showErrorMessage('未查找到物料【' + itemCode + '】的发货明细', res => {
getfocus();
});
return;
} else {
const params = {
itemCode: result.package.itemCode,
batch: result.label.batch,
packingNumber: result.label.packingNumber,
parentPackingNumber: result.package.parentNumber,
inventoryStatus: jobContent.value.outInventoryStatuses.split(','),
areaType: jobContent.value.fromAreaTypes.split(','),
bussinessCode: jobContent.value.businessType
}
uni.showLoading({
title: '查询中',
mask: true
});
getBalanceByParams(params).then(res => {
if (res.data.length == 0) {
const status = getInventoryStatusDesc(params.inventoryStatus)
const areaType = getListLocationAreaTypeDesc(params.areaType)
const hint =
"按物料号 [" + params.itemCode + "] \n" +
"包装号 [" + params.packingNumber + "] \n" +
"批次 [" + params.batch + "] \n" +
"状态 [" + status + "] \n" +
"库区 [" + areaType + "] \n" +
"未查找到库存余额"
showErrorMessage(hint,
res => {
getfocus();
})
} else if (res.data.length == 1) {
result.balance = res.data[0]
if (result.label.packingNumber != result.balance.packingNumber) {
result.balance.qty = Number(result.label.qty)
} else {
result.balance.qty = Number(result.balance.qty)
}
afterGetBalance(result.label, result.balance, result.package);
} else {
//
balanceSelect.value.openPopup(res.data);
}
uni.hideLoading()
}).catch(error => {
uni.hideLoading()
showErrorMessage(error,
res => {
getfocus();
})
})
}
} catch (e) {
showErrorMessage(e.stack,res=>{
getfocus()
});
uni.hideLoading();
}
};
const getBalance = (label, packageInfo, callback)=> {
let filters = []
if (packageInfo.parentNumber) {
const packingNumber = packageInfo.parentNumber + "," + label.packingNumber;
filters.push({
column: "packingNumber",
action: "in",
value: packingNumber
})
} else {
filters.push({
column: "packingNumber",
action: "==",
value: label.packingNumber
})
}
filters.push({
column: "itemCode",
action: "==",
value: label.itemCode
})
filters.push({
column: "batch",
action: "==",
value: label.batch
})
if (fromInventoryStatuses.value != null && fromInventoryStatuses.value != "") {
filters.push({
column: "inventoryStatus",
action: "in",
value: fromInventoryStatuses.value
})
}
const params = {
filters: filters,
pageNo: 1,
pageSize: 100,
}
getBalanceByFilter(params).then(res => {
callback(res.data)
}).catch(err => {
showErrorMessage(err.message);
})
}
const onScan = (result)=> {
if (!result.package) {
showErrorMessage('扫描数据错误[' + result.label.code + "]",
res => {
getfocus();
}
)
return;
}
if (toLocation.value) {
let item = toLocation.value.Items.find(r => r.itemCode == result.package.itemCode);
if (!item) {
showErrorMessage('扫描物料代码不属于该任务');
return
}
getToLocationBalance(result)
}
}
//
const getToLocationBalance = (result)=> {
uni.showLoading({
title: '查询中',
mask: true
})
let filters = []
if (result.package.parentNumber) {
const packingNumber = result.package.parentNumber + "," + result.package.number;
filters.push({
column: "packingNumber",
action: "in",
value: packingNumber
})
} else {
filters.push({
column: "packingNumber",
action: "==",
value: result.package.number
})
}
filters.push({
column: "itemCode",
action: "==",
value: result.package.itemCode
})
filters.push({
column: "batch",
action: "==",
value: result.package.batch
})
filters.push({
column: "areaType",
action: "in",
value: toLocationAreaTypeList.value.join(',')
})
const params = {
filters: filters,
pageNo: 1,
pageSize: 100,
}
getBalanceByFilter(params).then(res => {
uni.hideLoading()
if (res.data.list.length > 0) {
showErrorMessage("包装在库位【" + res.data.list[0].locationCode + "】已有库存余额");
} else {
queryBalance(result);
}
// callback(res.data)
}).catch(err => {
uni.hideLoading()
showErrorMessage(err.message);
})
}
const selectBalanceItem = (balance) => {
afterGetBalance(balance, balance, packageInfo.value);
};
const afterGetBalance = (labelValue, balance, packageInfoValue) => {
try {
let itemCode = labelValue.itemCode;
let packingCode = labelValue.packingNumber;
let lot = labelValue.batch;
let item = toLocation.value.Items.find(r => r.itemCode == itemCode);
fromLocationCode.value = balance.locationCode;
let fromLocation = item.Locations.find(l => l.fromLocationCode == fromLocationCode.value);
if (fromLocation) {
let batch = fromLocation.Batchs.find(r => r.batch == lot);
if(batch != undefined){
if (batch.Records == undefined) {
batch.Records = [];
}
let record = batch.Records.find(r => r.packingNumber == packingCode);
if (record == undefined) {
//
if (batch.Recommends != undefined && batch.Recommends.length > 0) {
let recommend = batch.Recommends.find(r => r.packingNumber == packingCode);
if (recommend != undefined) {
addRecord(batch, label, balance, packageInfo)
} else {
//
if (this.jobContent.allowModifyPackingNumber == 'TRUE') {
addRecord(batch, label, balance, packageInfo);
} else {
showErrorMessage('未查找到该箱码【' + packingCode + '】的明细',
res => {
getfocus();
return;
}
)
}
}
} else {
addRecord(batch, label, balance, packageInfo)
}
} else {
addRecord(batch, label, balance, packageInfo)
}
}else {
if (jobContent.value.allowModifyBatch == "TRUE") {
showQuestionMessage('在【' + fromLocationCode.value + '】库位下,未查找到批次【' + lot +
'】的发货明细,是否要继续发货?', res => {
if (res) {
let batch = createBatchInfo(label, balance, packageInfo);
//details
if (fromLocation.Batchs.length > 0) {
batch.detail = fromLocation.Batchs[0].detail;
}
fromLocation.Batchs.unshift(batch);
getfocus();
emit("afterScan");
}
})
} else {
showErrorMessage('未查找到批次【' + lot + '】的发货明细',
res => {
getfocus();
});
}
}
}else {
//
if (jobContent.value.allowModifyLocation == "TRUE") {
showQuestionMessage("扫描物料[" + itemCode + "]的库位【" + fromLocationCode.value +
"】与推荐的库位不一致,是否要继续发货?", res => {
if (res) {
let locaion = createLocationInfo(label, balance, packageInfo);
item.Locations.push(locaion);
getfocus();
emit("afterScan");
}
})
} else {
showErrorMessage("扫描物料[" + itemCode + "]的库位【" + fromLocationCode.value +
"】与推荐的库位不一致,不允许继续发货?")
}
}
} catch (e) {
showErrorMessage(e.stack, res => {
getfocus();
});
}
};
//
const createLocationInfo = (label, balance, packageInfoValue)=> {
let location = {
fromLocationCode: balance.locationCode,
qty: balance.qty,
uom: balance.uom,
handleQty: 0,
isNewAdd: true,
Batchs: []
}
let batch = createBatchInfo(label, balance, packageInfoValue);
batch.detail = balance;
batch.detail.fromLocationCode = balance.locationCode;
location.Batchs.push(batch);
return location;
}
const createBatchInfo = (data, balance, packageInfoValue) => {
let batch = {
isNewAdd: true,
batch: data.batch,
qty: 0,
uom: data.uom,
handleQty: Number(balance.qty),
Records: [],
};
let record = creatRecord(data, balance, packageInfoValue);
batch.Records.push(record);
issueRecord.value.unshift(record);
return batch;
};
const creatRecord = (labelValue, balance, packageInfoValue) => {
balance.packQty = packageInfoValue.packQty;
balance.packUnit = packageInfoValue.packUnit;
let record = {
scaned: true,
itemCode: labelValue.itemCode,
packingNumber: labelValue.packingNumber,
parentPackingNumber: packageInfoValue.parentNumber,
batch: labelValue.batch,
qty: Number(balance.qty),
handleQty: Number(balance.qty),
uom: balance.uom,
inventoryStatus: balance.inventoryStatus,
balance: balance,
toLocationCode: toLocationCode.value,
supplierCode: labelValue.supplierCode,
packUnit: packageInfoValue.packUnit,
packQty: packageInfoValue.packQty,
};
return record;
};
const calcBatchHandleQty = (batch) => {
let handleQty = 0;
batch.Records.forEach(res => {
handleQty = calc.add(handleQty, res.qty)
})
batch.handleQty = handleQty;
};
const addRecord = (batch, labelValue, balance, packageInfoValue) => {
if(packageInfoValue.parentNumber){
let checkData = batch.Records.find(r => {
if (r.packingNumber == packageInfoValue.parentNumber && r.batch == balance.batch) {
return r;
}
});
if (checkData) {
showErrorMessage("箱码[" + packageInfoValue.number + "]批次[" + balance.batch +
"]的父包装已经扫描")
} else {
let record = creatRecord(labelValue, balance, packageInfoValue);
batch.Records.push(record);
issueRecord.value.unshift(record)
dataContent.value.subList.push(record);
calcBatchHandleQty(batch);
getfocus();
emit("afterScan");
}
}else {
//
let checkData = batch.Records.find(r => {
if (r.parentPackingNumber == packageInfoValue.number &&
r.batch == balance.batch) {
return r;
}
})
if (checkData) {
//
comMessage.value.showQuestionMessage("扫描箱码[" + checkData.parentPackingNumber + "]" + "批次[" +
balance
.batch + "]是父包装,是否移除子包装", res => {
if (res) {
batch.Records = [];
let record = creatRecord(label, balance, packageInfoValue);
batch.Records.push(record);
issueRecord.value.unshift(record)
calcBatchHandleQty(batch);
getfocus();
emit("afterScan");
}
})
} else {
let record = creatRecord(label, balance, packageInfoValue);
batch.Records.push(record);
issueRecord.value.unshift(record)
calcBatchHandleQty(batch);
getfocus();
emit("afterScan");
}
}
};
const getfocus = () => {
if (comscan.value != undefined) {
comscan.value.getfocus();
}
};
const losefocus = () => {
if (comscan.value != undefined) {
comscan.value.losefocus();
}
};
const expands = () => {
expand.value = !expand.value;
expendIcon.value = expand.value ? "arrow-down" : "arrow-up";
};
const swipeClick = (e, item, index) => {
if (e.content.text == "详情") {
detail(item);
} else if (e.content.text == "编辑") {
edit(item);
} else if (e.content.text == "移除") {
remove(item, index);
}
};
const edit = (item) => {
editItem.value = item;
item.balance.balanceQty = item.balance.qty;
balanceQtyEdit.value.openEditPopup(item.balance, item.qty);
};
const detail = (item) => {
showItem.value = item;
receiptHint.value.openScanPopup();
};
const remove = (record, index) => {
showQuestionMessage("确定移除扫描信息?", res => {
if (res) {
record.qty = 0;
issueRecord.value.splice(index, 1);
let item = toLocation.value.Items.find(r => r.itemCode == record.itemCode);
if (item != undefined) {
item.Locations.forEach(l => {
let batch = l.Batchs.find(b => b.packingNumber == record.packingNumber && b.batch == record.batch);
if (batch && batch.Records && batch.Records.length > 0) {
let rIndex = batch.Records.findIndex(r => r.packingNumber == record.packingNumber && r.batch == record.batch);
batch.Records.splice(rIndex, 1);
}
});
}
emit('updateData', item);
}
});
};
const packGetFocus = () => {
if (comscan.value) {
comscan.value.getfocus();
}
};
const packLoseFocus = () => {
if (comscan.value) {
comscan.value.losefocus();
}
};
const showMessage = (message, callback) => {
setTimeout(r => {
packLoseFocus();
comMessage.value.showMessage(message, callback);
});
};
const showErrorMessage = (message, callback) => {
setTimeout(r => {
packLoseFocus();
comMessage.value.showErrorMessage(message, callback);
});
};
const showQuestionMessage = (message, callback) => {
setTimeout(r => {
packLoseFocus();
comMessage.value.showQuestionMessage(message, callback);
});
};
const confirm = (val) => {
editItem.value.qty = Number(val);
emit('updateData', editItem.value);
};
const cancle = () => {
closeScanPopup();
};
</script>
<style lang="scss">
button {
border: none;
}
button::after {
border: none
}
.scroll-view {
overflow-y: scroll;
height: auto;
max-height: 300rpx;
padding: 10rpx;
}
.my-combox {
font-size: 50px;
}
</style>

554
src/pages/deliver/coms/comScanDeliverPackss.vue

@ -0,0 +1,554 @@
<template>
<view>
<u-popup v-model="show" mode="bottom" :maskClick='false'>
<view class="">
<view class="popup_box">
<view class="pop_title uni-flex space-between">
<view class="" style="font-size: 35rpx;">
扫描箱码
</view>
<view class="">
<image class="fr icons_scan_close" src="/static/icons/icons_scan_close.svg"
@click="closeScanPopup()"></image>
</view>
</view>
<!-- <view class="uni-flex uni-row" style="align-items: center;
background-color: #fff;
margin-left: 20rpx;
margin-right: 20rpx;
padding:20rpx;
border-radius: 8rpx;">
<view class="uni-center">
位置 :
</view>
<view class="" style="width: 75%;padding: 0rpx">
<view class="uni-flex u-col-center uni-row" @click="showSelect">
<view class="" style="margin-left: 15rpx;font-size: 30rpx;">
{{positionInfo}}
</view>
<u-select v-model="show" mode="mutil-column-auto" :list="positionList" :defaultValue="defaultValueList"
@confirm="confirmSelect"></u-select>
</view>
</view>
</view>
<u-line class='line_color'></u-line> -->
<view class="uni-flex uni-row" style="align-items: center;
background-color: #fff;
margin-left: 20rpx;
margin-right: 20rpx;
margin-top: 8rpx;
border-radius: 8rpx;">
<view class="uni-center" style="width: 25%; ">
来源库位
</view>
<view class="" style="width: 75%; padding: 8rpx;">
<uni-combox :candidates="fromLocationList" v-model="fromLocationCode" placeholder="请选择库位"
@confirm="fromLocationUpdate"></uni-combox>
</view>
</view>
<view class="">
<view class="">
<win-com-scan ref="comscan" placeholder="箱标签" @getResult="onScan" :clearResult="true"
:headerType="headerType" :isShowHistory="false">
</win-com-scan>
<view style="width: 100%;">
<view style="width: 100%;" v-if="issueRecord.length>0">
<view class="uni-flex uni-row space-between u-col-center">
<view class="" style="padding: 10rpx;">
历史记录
</view>
<view class="" style="padding-right: 10rpx;">
<u-icon :name="expendIcon" size="35rpx" @click="expands()"></u-icon>
</view>
</view>
<u-line class='line_color' style='padding-top: 10rpx;padding-bottom: 20rpx;'>
</u-line>
<scroll-view scroll-y="true" class="scroll-view"
v-if="expand&&issueRecord.length>0">
<view class="uni-flex u-col" v-for="(record,index) in issueRecord">
<view style="width: 100%;">
<u-swipe-action ref="swipeAction" :options="scanOptions"
@click="(...event)=>swipeClick(event,record,index)">
<view style="padding: 0px 10px">
<balance :dataContent="record" :isShowLocation="false"
:isShowStdPack="false"></balance>
u
</view>
</u-swipe-action>
<u-line class='line_color'></u-line>
</view>
</view>
</scroll-view>
</view>
</view>
</view>
</view>
</view>
</view>
</u-popup>
<balance-select ref="balanceSelectRef" @onSelectItem='selectBalanceItem'></balance-select>
<comMessage ref="comMessageRef"></comMessage>
<balance-qty-edit ref="balanceQtyEditRef" @confirm="confirm" :isShowStatus="true"></balance-qty-edit>
</view>
</template>
<script setup lang="ts">
import winComScan from '@/mycomponents/scan/winComScan.vue'
import balance from '@/mycomponents/balance/balance.vue'
import balanceQtyEdit from '@/mycomponents/qty/balanceQtyEdit.vue'
import BalanceSelect from '@/mycomponents/balance/balanceSelect.vue'
import {
getDetailOption,
getDetailEditRemoveOption
} from '@/common/array.js';
import {
getDirectoryItemArray,
} from '@/common/directory.js';
import {
calc
} from '@/common/calc.js';
import {
getWorkShopLineStation
} from '@/api/request2.js';
import {
getBalanceByManagementPrecision
} from '@/common/balance.js';
import {ref, onMounted} from 'vue';
const props = defineProps({
title: {
type: String,
default: ''
},
headerType: {
type: String,
default: "HPQ,HMQ"
}
});
const emit = defineEmits(['closeScan','updateData'])
const dataContent = ref({});
const jobContent = ref({});
const expendIcon = ref('arrow-down');
const show = ref(false);
const scanList = ref([]);
const toLocation = ref(null);
const toLocationCode = ref('');
const fromLocationList = ref([]);
const fromLocationCode = ref('');
const fromLocation = ref(null);
const issueRecord = ref([]); //
const expand = ref(true);
const scanOptions = ref({});
const editItem = ref({});
const positionInfo = ref("请选择位置");
const positionList = ref([]);
const defaultValueList = ref([]);
const label = ref({});
const fromInventoryStatuses = ref([]);
const packageInfo = ref({});
const balanceSelectRef = ref(null);
const comscan = ref(null);
const comMessageRef = ref(null);
const receiptHint = ref(null);
const balanceQtyEditRef = ref(null);
const detailOptions = ref('')
const toLocationCombox = ref('')
const showItem = ref('')
onMounted(() => {
detailOptions.value = getDetailOption();
scanOptions.value = getDetailEditRemoveOption();
});
//
const openScanPopup = (content, jobcontent) => {
issueRecord.value = [];
dataContent.value = content;
jobContent.value = jobcontent;
initData();
positionInfo.value = jobContent.value.workShopCode + "-" + jobContent.value.subList[0].productionLineCode +
"-" + jobContent.value.subList[0].workStationCode;
show.value = true
setTimeout(() => {
getfocus();
}, 500);
};
const closeScanPopup = () => {
losefocus();
show.value = false
emit('closeScan');
//
// Object.assign(this.$data, this.$options.data());
};
const initData = () => {
fromLocationList.value = [];
if (dataContent.value != null) {
fromInventoryStatuses.value = getDirectoryItemArray(jobContent.value.outInventoryStatuses);
toLocation.value = dataContent.value[0];
toLocationCode.value = dataContent.value[0].toLocationCode;
fromLocationList.value = getFromLocationList();
}
};
const showBalanceSelect = (items, packageInfo) => {
packageInfo.value = packageInfo;
balanceSelectRef.value.openPopup(items);
};
const getFromLocationList = () => {
let list = [];
let location = dataContent.value.find(r => r.toLocationCode == toLocationCode.value);
if (location != undefined) {
location.Items.forEach(item => {
item.Locations.forEach(f => {
list.push(f.fromLocationCode);
});
});
fromLocationCode.value = list[0];
return list;
} else {
comMessageRef.value.showErrorMessages('需求库位【' + toLocationCode.value + '】不存在', res => {
toLocationCode.value = '';
});
}
};
const fromLocationUpdate = (fromlocation) => {
let location = fromLocationList.value.find(r => r == fromlocation);
fromLocationCode.value = fromlocation;
};
const onScan = (result) => {
try {
if (fromLocationCode.value == '') {
showErrorMessage('请选择来源库位', res => {
toLocationCombox.value.onFocus();
});
return;
}
let packageInfo = result.package;
let itemCode = result.label.itemCode;
let packingCode = result.label.packingNumber;
let lot = result.label.batch;
let item = toLocation.value.Items.find(r => r.itemCode == itemCode);
if (item == undefined) {
showErrorMessage('未查找到物料【' + itemCode + '】的发货明细', res => {
getfocus();
});
return;
} else {
uni.showLoading({
title: '加载中',
mask: true
});
getBalanceByManagementPrecision(result.label, fromLocationCode.value, fromInventoryStatuses.value, balanceRes => {
if (balanceRes.success) {
if (balanceRes.data.list.length == 0) {
showErrorMessage('在来源库位[' + fromLocationCode.value + '],未查找到该包装的库存记录', res => {
packGetFocus();
});
} else if (balanceRes.data.list.length == 1) {
let balance = balanceRes.data.list[0];
afterGetBalance(result.label, balance, packageInfo);
} else {
label.value = result.label;
showBalanceSelect(balanceRes.data.list, packageInfo);
}
} else {
showErrorMessage(balanceRes.message.message);
}
uni.hideLoading();
});
}
} catch (e) {
showErrorMessage(e.stack);
uni.hideLoading();
}
};
const selectBalanceItem = (balance) => {
afterGetBalance(balance, balance, packageInfo.value);
};
const afterGetBalance = (label, balance, packageInfo) => {
try {
let itemCode = label.itemCode;
let packingCode = label.packingNumber;
let lot = label.batch;
let item = toLocation.value.Items.find(r => r.itemCode == itemCode);
let fromLocation = item.Locations.find(l => l.fromLocationCode == fromLocationCode.value);
// --
if (!fromLocation) {
fromLocation = {
Batchs: [{
Recommends: [],
Records: [],
batch: label.batch,
detail: {
...packageInfo,
fromLocationCode: balance.locationCode,
toLocationCode: toLocationCode.value
},
handleQty: 0,
packingNumber: null,
qty: label.qty,
uom: label.uom
}],
toLocationCode: toLocationCode.value,
fromLocationCode: balance.locationCode,
handleQty: 0,
qty: label.qty,
uom: label.uom
};
item.Locations.push(fromLocation);
}
if (fromLocation != undefined) {
let batch = fromLocation.Batchs.find(r => r.batch == lot);
if (batch != undefined) {
if (batch.Records == undefined) {
batch.Records = [];
}
let record = batch.Records.find(r => r.packingNumber == packingCode);
if (record == undefined) {
//
if (batch.Recommends && batch.Recommends.length > 0) {
let recommend = batch.Recommends.find(r => r.packingNumber == packingCode);
if (recommend != undefined) {
addRecord(batch, label, balance, packageInfo);
} else {
//
if (jobContent.value.allowModifyPackingNumber == 'TRUE') {
addRecord(batch, label, balance, packageInfo);
} else {
showErrorMessage('未查找到该箱码【' + packingCode + '】的明细', res => {
getfocus();
});
}
}
} else {
addRecord(batch, label, balance, packageInfo);
}
} else {
showErrorMessage('箱码【' + packingCode + '】已经扫描,请继续扫描下一箱', res => {
getfocus();
});
}
} else {
if (jobContent.value.allowModifyBatch == "TRUE") {
showQuestionMessage('在【' + fromLocationCode.value + '】库位下,未查找到批次【' + lot +
'】的发货明细,是否要继续发货?', res => {
if (res) {
let batch = createBatchInfo(label, balance, packageInfo);
fromLocation.Batchs.unshift(batch);
}
});
} else {
showErrorMessage('未查找到批次【' + lot + '】的发货明细', res => {
getfocus();
});
}
}
} else {
showErrorMessage('未查找到推荐库位【' + fromLocationCode.value + '】的发货明细', res => {
getfocus();
});
}
} catch (e) {
showErrorMessage(e.stack, res => {
getfocus();
});
}
};
const createBatchInfo = (data, balance, packageInfo) => {
let batch = {
batch: data.lot || data.batch,
qty: 0,
uom: data.uom,
handleQty: Number(data.qty),
Records: [],
detail: {
fromLocationCode: fromLocationCode.value, //balance.locationCode
toLocationCode: toLocationCode.value,
itemCode: data.itemCode,
handleQty: Number(data.qty),
packingNumber: data.packingNumber,
qty: 0,
uom: data.uom,
itemName: packageInfo.itemName,
itemDesc1: packageInfo.itemDesc1,
itemDesc2: packageInfo.itemDesc2,
singlePrice: balance.singlePrice,
amount: balance.amount
}
};
let record = creatRecord(data, balance, packageInfo);
batch.Records.push(record);
issueRecord.value.unshift(record);
return batch;
};
const creatRecord = (label, balance, packageInfo) => {
balance.packQty = packageInfo.packQty;
balance.packUnit = packageInfo.packUnit;
let record = {
scaned: true,
itemCode: label.itemCode,
packingNumber: label.packingNumber,
batch: label.batch,
qty: Number(label.qty) > Number(balance.qty) ? Number(balance.qty) : Number(label.qty),
uom: balance.uom,
inventoryStatus: balance.inventoryStatus,
balance: balance,
toLocationCode: toLocationCode.value,
supplierCode: label.supplierCode,
packUnit: packageInfo.packUnit,
packQty: packageInfo.packQty,
singlePrice: balance.singlePrice,
amount: balance.amount
};
return record;
};
const calcBatchHandleQty = (batch) => {
let handleQty = 0;
batch.Records.forEach(res => {
handleQty = calc.add(handleQty, res.qty);
});
batch.handleQty = handleQty;
};
const addRecord = (batch, label, balance, packageInfo) => {
let record = creatRecord(label, balance, packageInfo);
batch.Records.push(record);
issueRecord.value.unshift(record);
calcBatchHandleQty(batch);
getfocus();
};
const getfocus = () => {
if (comscan.value != undefined) {
comscan.value.getfocus();
}
};
const losefocus = () => {
if (comscan.value != undefined) {
comscan.value.losefocus();
}
};
const expands = () => {
expand.value = !expand.value;
expendIcon.value = expand.value ? "arrow-down" : "arrow-up";
};
const swipeClick = (e, item, index) => {
if (e.content.text == "详情") {
detail(item);
} else if (e.content.text == "编辑") {
edit(item);
} else if (e.content.text == "移除") {
remove(item, index);
}
};
const edit = (item) => {
editItem.value = item;
item.balance.balanceQty = item.balance.qty;
balanceQtyEditRef.value.openEditPopup(item.balance, item.qty);
};
const detail = (item) => {
showItem.value = item;
receiptHint.value.openScanPopup();
};
const remove = (record, index) => {
showQuestionMessage("确定移除扫描信息?", res => {
if (res) {
record.qty = 0;
issueRecord.value.splice(index, 1);
let item = toLocation.value.Items.find(r => r.itemCode == record.itemCode);
if (item != undefined) {
item.Locations.forEach(l => {
let batch = l.Batchs.find(b => b.packingNumber == record.packingNumber && b.batch == record.batch);
let rIndex = batch.Records.findIndex(r => r.packingNumber == record.packingNumber && r.batch == record.batch);
batch.Records.splice(rIndex, 1);
});
}
emit('updateData', item);
}
});
};
const packGetFocus = () => {
comscan.value.getfocus();
};
const packLoseFocus = () => {
comscan.value.losefocus();
};
const showMessage = (message, callback) => {
setTimeout(() => {
packLoseFocus();
comMessageRef.value.showMessage(message, callback);
});
};
const showErrorMessage = (message, callback) => {
setTimeout(() => {
packLoseFocus();
comMessageRef.value.showErrorMessage(message, callback);
});
};
const showQuestionMessage = (message, callback) => {
setTimeout(() => {
packLoseFocus();
comMessageRef.value.showQuestionMessage(message, callback);
});
};
const confirm = (val) => {
editItem.value.qty = Number(val);
emit('updateData', editItem.value);
};
const cancle = () => {
closeScanPopup();
};
</script>
<style lang="scss">
button {
border: none;
}
button::after {
border: none
}
.scroll-view {
overflow-y: scroll;
height: auto;
max-height: 300rpx;
padding: 10rpx;
}
</style>

727
src/pages/deliver/job/deliverDetailBatch.vue

@ -0,0 +1,727 @@
<template>
<view class="page-wraper">
<view class="page-header">
<view class="header-view">
<view class="header_job_top">
<job-top :dataContent="jobContent"></job-top>
</view>
<view class="cen_card" style="padding: 5rpx;">
<view class="cell_box uni-flex uni-row">
<view class="cell_info">
<view class="text_lightblue">发货类型</view>
<view>{{ jobContent.deliverType }}</view>
</view>
<view class="cell_info">
<view class="text_lightblue">客户代码</view>
<view>{{ jobContent.customerCode }}</view>
</view>
<view class="cell_info">
<view class="text_lightblue">目标库位</view>
<view>{{ toLocationCode }}</view>
</view>
</view>
</view>
</view>
</view>
<view class="page-main">
<scroll-view scroll-y="true" class="page-main-scroll">
<view>
<view v-for="(toLocation, index) in detailSource" :key="index">
<comDeliverDetailCardBatch ref='comIssueDetailCardBatch' :dataContent="toLocation" :settingParam="jobContent"
@updateData='updateData' :allowBiggerQty='allowBiggerQty'>
</comDeliverDetailCardBatch>
<view class="split_line"></view>
</view>
</view>
</scroll-view>
</view>
<view class="page-footer">
<view class="uni-flex u-col-center space-between padding_10" style="background-color:ghostwhite; width: 100%; ">
<view class="">
</view>
<view class=" uni-flex uni-row">
<button class="btn_single_commit" hover-class="btn_commit_after" @click="submit()">提交</button>
</view>
</view>
</view>
<win-scan-button @goScan='openScanPopup'></win-scan-button>
<!-- <comScanDeliverPackBatch ref="comScanIssuePack" @closeScan='closeScan' @updateData='updateData'></comScanDeliverPackBatch>-->
<winScanPackAndLocation :balanceFromInventoryStatuses="false" :toLocationCode="jobToLocationCode" ref="scanPopup"
@getResult='getScanResult' :noShowBalanceMessage="false" @confirm='confirmFromLocation'>
</winScanPackAndLocation>
<comMessage ref="comMessageRef"></comMessage>
</view>
</template>
<script setup lang="ts">
import {
getDeliverDetail,
takeDeliverJob,
cancleTakeDeliverJob,
deliverJobSubmit
} from '@/api/request2.js';
import {
calc
} from '@/common/calc.js';
import {
goHome,
navigateBack,
getRemoveOption,
getCurrDateTime,
getPackingNumberAndBatch,
deepCopyData,
compareAsc
} from '@/common/basic.js';
import {
getTreeDataSource,
calcTreeHandleQty,
getScanCount,
getThreeDataSource,
getDataSource,
calcHandleQty,
} from '@/common/detail.js';
import {
getManagementPrecisions
} from '@/common/balance.js';
import jobDetailPopup from '@/mycomponents/job/jobDetailPopup.vue'
import WinScanButton from '@/mycomponents/scan/winScanButton.vue'
import ComDeliverDetailCardBatch from '@/pages/deliver/coms/comDeliverDetailCardBatch.vue'
import comScanDeliverPackBatch from '@/pages/deliver/coms/comScanDeliverPackBatch.vue'
import JobTop from '@/mycomponents/job/jobTop.vue'
import WinScanPackAndLocation from "@/mycomponents/scan/winScanPackAndLocation.vue"
import {ref,nextTick} from 'vue';
import {onLoad, onNavigationBarButtonTap, onBackPress} from '@dcloudio/uni-app';
const id = ref('');
const jobContent = ref({});
const subList = ref([]);
const detailSource = ref([]);
const detailOptions = ref([]);
const scanOptions = ref([]);
const status = ref("");
const toLocationCode = ref("");
const jobStatus = ref("");
const dataContent = ref('')
const allowBiggerQty = ref('TRUE')
const managementType = ref('')
const scanCount = ref('')
const balanceinfo = ref('')
const fromLocationCode = ref('')
const managementList = ref([]);
const comMessageRef = ref(null);
const scanPopup = ref(null);
const comScanIssuePack = ref(null);
const comIssueDetailCardBatch = ref(null)
import {useCountStore} from '@/store'
const store = useCountStore();
onLoad((option) => {
uni.setNavigationBarTitle({
title: option.title + '详情'
});
id.value = option.id;
if (id.value != undefined) {
//
if (option.status == "1") {
receive(() => {
getDetail();
});
} else {
getDetail();
}
}
});
onNavigationBarButtonTap((e) => {
if (e.index === 0) {
goHome();
}
});
onBackPress((e) => {
//
if (e.from == 'backbutton') {
if (jobStatus.value == "2") {
//
cancleTakeDeliverJob(id.value).then(() => {
uni.navigateBack();
}).catch(() => {
uni.navigateBack();
});
} else {
uni.navigateBack();
}
return true;
}
});
const receive = (callback) => {
if (id.value != null) {
takeDeliverJob(id.value).then(() => {
callback();
}).catch((error) => {
showErrorMessage(error);
});
}
};
const getDetail = () => {
uni.showLoading({
title: "加载中....",
mask: true
});
getDeliverDetail(id.value).then((res) => {
uni.hideLoading();
if (res.data && res.data.subList.length > 0) {
jobContent.value = res.data;
jobStatus.value = res.data.status;
subList.value = res.data.subList;
// detailSource.value = res.data;
detailSource.value = getThreeDataSource(jobContent.value)
toLocationCode.value = subList.value[0].toLocationCode;
allowBiggerQty.value = res.data.allowBiggerQty;
resizeCollapse();
} else {
showMessage('未获取到详情');
}
}).catch((error) => {
uni.hideLoading();
showErrorMessage(error);
});
};
const closeScan = () => {
resizeCollapse();
};
const resizeCollapse = () => {
nextTick(r => {
comIssueDetailCardBatch.value.forEach(r => {
r.resizeCollapse();
})
});
};
const getScanResult = (result, managementTypeParams)=> {
managementType.value = managementTypeParams
if(managementTypeParams == "BY_BATCH" ||managementTypeParams == "BY_QUANTITY" ){
setDataBatch(result)
}else{
//TODO
// setData(result)
}
}
const setDataBatch = (result)=> {
try {
balanceinfo.value = result.balance
let packingNumber = result.label.packingNumber;
let batch = result.label.batch;
let qty = result.label.qty;
let itemCode = result.label.itemCode;
let locationCode = result.fromLocationCode;
if (!result.balance) {
showMessage("没有库存余额")
return;
}
// var inventoryStatus = "OK";
let detail = detailSource.value.find(r => r.itemCode == itemCode);
if (detail == undefined) {
showErrorMessage("物料号【" + itemCode + "】不在列表中")
} else {
let itemDetail = detail.subList.find(r => {
return r.batch == batch &&
r.fromLocationCode == result.fromLocationCode
})
if (itemDetail == undefined) {
let isExit;
for (let subItem of detail.subList) {
let item;
// for (let pack of subItem.packList) {
// if (pack.batch == batch) {
// item = pack;
// isExit = pack;
// break;
// }
// }
// if (item != undefined) {
// subItem.scaned = true
// subItem.handleQty = 0;
// item = undefined
// }
}
if (isExit == undefined) {
// this.showErrorMessage("" + batch + "" + result
// .fromLocationCode + "")
detail.subList.push({
scaned:true,
fromLocationCode:fromLocationCode.value,
toLocationCode:toLocationCode.value,
batch:result.label.batch,
handleQty:result.label.qty,
qty:result.balance.qty,
inventoryStatus:result.balance.inventoryStatus,
toLocation:result.balance.toLocation,
balance:result.balance,
balanceQty:result.balance.qty,
packQty:result.package.packQty,
packUnit:result.package.packUnit,
uom:result.balance.uom,
// packList:[{
// scaned : true,
// handleQty : Number(result.label.qty),
// toLocationCode : result.balance.toLocationCode,
// }]
})
detail.handleQty = 0
detail.qty = 0
detail.subList.forEach(item=>{
detail.handleQty = calc.add(detail.handleQty,item.handleQty)
detail.qty = calc.add(detail.qty,item.qty)
// item.packList.forEach(cur=>{
// cur.handleQty = calc.add(detail.handleQty,item.handleQty)
// })
})
setTimeout(r => {
resizeCollapse();
}, 100)
} else {
if (!isExit.cancleScanedHiht && isExit.scaned) {
// this.showMessage("" + batch + "")
} else {
isExit.scaned = true
let qty = 0;
if (result.balance != null) {
qty = Number(result.balance.qty);
} else {
qty = Number(result.label.qty);
}
isExit.handleQty = Number(result.label.qty);
isExit.toLocationCode = toLocationCode.value;
}
itemDetail.handleQty = calc.add(itemDetail.handleQty,result.label.qty);
detail.handleQty = 0
detail.balance = result.balance
detail.subList.forEach(item=>{
detail.handleQty = calc.add(detail.handleQty,item.handleQty)
})
// calcHandleQtyAdd(this.detailSource, result.label);
}
continueScan()
} else {
let scanedLength = 0;
// itemDetail.packList.forEach(res => {
// if (res.scaned) {
// scanedLength++;
// }
// })
//
itemDetail.fromInventoryStatus = result.balance.inventoryStatus;
if (itemDetail.scaned ) {
// this.showMessage("" + packingNumber + "")
// calcHandleQtyAdd(this.detailSource, result.label);
itemDetail.balance=result.balance
itemDetail.balanceQty=result.balance.qty
itemDetail.uom=result.balance.uom
itemDetail.handleQty = calc.add(itemDetail.handleQty,result.label.qty);
detail.handleQty = 0
detail.subList.forEach(item=>{
detail.handleQty = calc.add(detail.handleQty,item.handleQty)
})
} else {
itemDetail.scaned = true;
detailSource.value[0].subList.sort(compareAsc('scaned')); //
itemDetail.handleQty = result.label.qty;
itemDetail.scaned = true
itemDetail.balance=result.balance
itemDetail.balanceQty=result.balance.qty
itemDetail.uom=result.balance.uom
itemDetail.packQty=result.package.packQty
itemDetail.packUnit=result.package.packUnit
itemDetail.fromlocationCode=fromLocationCode.value
itemDetail.toLocationCode=toLocationCode.value
// itemDetail.toInventoryStatus = "OK"
// itemDetail.packList.forEach(pac => {
// pac.scaned = true
// pac.handleQty = Number(result.label.qty);
// pac.toLocationCode = result.balance.toLocationCode;
// })
detail.handleQty = 0
detail.subList.forEach(item=>{
detail.handleQty = calc.add(detail.handleQty,item.handleQty)
// item.packList.forEach(cur=>{
// cur.handleQty = calc.add(detail.handleQty,item.handleQty)
// })
})
// calcTreeHandleQty(this.detailSource);
continueScan()
}
}
}
detailSource.value.forEach(item => {
item.subList.forEach(detail => {
detail.packingNumber = ''
})
})
} catch (e) {
showMessage(e.message)
}
}
//
const continueScan = ()=> {
scanCount.value = getScanCount(subList.value);
if (scanCount.value == subList.value.length) {
closeScanPopup();
} else {
scanPopupGetFocus();
}
}
const submit = () => {
uni.showLoading({
title: "提交中....",
mask: true
});
//
const itemCodes = [];
const locationCode = detailSource.value[0].subList[0].toLocationCode;
detailSource.value.forEach((item) => {
itemCodes.push(item.itemCode);
});
//
getManagementPrecisions(itemCodes, locationCode, (res) => {
if (res.success) {
managementList.value = res.list;
managementType.value = managementList.value && managementList.value[0] ? managementList.value[0].ManagementPrecision : 'BY_PACKAGING'
submitJob();
} else {
uni.hideLoading();
// showErrorMessage(res.message);
}
});
};
const checkCount = () => {
let str = "";
detailSource.value.forEach((item) => {
let taskQty = 0;
item.taskQty = calc.add(taskQty,item.qty)
let totalQty = 0;
item.Locations.forEach(lco => {
lco.Batchs.forEach(batch => {
batch.Records.forEach(record => {
if(record){
const hanleQty = record.qty?record.qty:0
totalQty = calc.add(totalQty,hanleQty)
}
})
})
})
//
item.totalQty = totalQty;
});
//
detailSource.value.forEach((detail) => {
detail.Items.forEach(item=>{
if(jobContent.value.allowPartialComplete=="FALSE"){
if(item.taskQty!=item.totalQty){
str += `物料号【${item.itemCode}】任务数量【${item.taskQty}】与实际提交数量【${item.totalQty}】不一致\n`
}
}
})
});
if (str) {
str = '不允许提交\n' + str;
showErrorMessage(str);
}
return str ? false : true;
};
const checkCountBatch = ()=> {
let str = ""
let str1 = ""
let str2 = ""
detailSource.value.forEach(detail => {
let taskQty = 0;
let totalQty = 0;
detail.subList.forEach(item => {
if (item.scaned) {
item.taskQty = 0
item.totalQty = 0
item.taskQty = calc.add(item.taskQty, item.qty)
item.totalQty = calc.add(item.totalQty, item.handleQty)
if (jobContent.value.allowPartialComplete == "FALSE") {
if (item.handleQty != item.taskQty) {
str += `批次【${item.batch}】提交数量【${item.handleQty}】与任务物料数量【${item.taskQty}】不一致\n`
}
}
if (allowBiggerQty.value == 'FALSE') {
if (item.taskQty < item.totalQty) {
str1 += '数量[' + item.totalQty + ']不允许大于任务数量[' + item.taskQty + ']'
}
}
if (item.handleQty > item.balance.qty) {
str2 += `批次【${item.batch}】提交数量【${item.handleQty}】不可以大于库存数量【${item.balance.qty}`
}
}
})
})
if (str) {
str = '不允许提交\n' + str
showErrorMessage(str)
}
if (str1) {
str1 = '不允许提交\n' + str1
showErrorMessage(str1)
}
if (str2) {
str2 = '不允许提交\n' + str2
showErrorMessage(str2)
}
return !(str || str1 || str2)
}
const submitJob = () => {
const params = setParams()
console.log("提交参数", params);
const isTrue = params.subList.some(item=>{
console.log(item.recordList.some(cur=>cur.scaned))
return item.recordList.some(cur=>cur.scaned) == true
})
if(!isTrue){
uni.hideLoading()
showErrorMessage("请扫描您需要提交的发货任务")
return
}
if(managementType.value == "BY_BATCH" || managementType.value == "BY_QUANTITY" ){
if (!checkCountBatch()) {
uni.hideLoading()
return;
}
}else{
if (!checkCount()) {
uni.hideLoading()
return;
}
}
deliverJobSubmit(params).then(res => {
uni.hideLoading()
if (res.data) {
showCommitSuccessMessage("提交成功\n生成发货记录\n" + res.data)
} else {
showErrorMessage("提交失败[" + res.msg + "]")
}
}).catch(error => {
uni.hideLoading()
showErrorMessage(error)
})
};
const setParams = () => {
const subList = [];
const createTime = getCurrDateTime();
const creator = store.id;
detailSource.value.forEach(toLocationCode => {
let obj = {...toLocationCode}
delete obj.subList
obj.recordList = []
let obj1 ={}
let arr = toLocationCode.subList.filter(item=>item.scaned)
arr.forEach(record=>{
obj1.scaned =record.scaned;
obj1.handleQty =record.handleQty;
obj1.fromLocationCode =record.fromLocationCode;
obj1.fromInventoryStatus =record.fromInventoryStatus;
obj1.copyContent =record.copyContent;
obj1.toContainerNumber = record.ContainerNumber;
obj1.toInventoryStatus =record.inventoryStatus;
obj1.toLocationCode = record.toLocationCode;
obj1.supplierCode = record.supplierCode;
obj1.toPackingNumber ='';
obj1.packingNumber = ''
obj1.fromPackingNumber = '';
obj1.toBatch = record.batch;
obj1.toPackingNumber = '';
obj1.packingNumber = '';
obj1.fromPackingNumber ='';
obj.recordList.push(obj1)
})
subList.push(obj)
})
jobContent.value.subList = subList;
jobContent.value.createTime = createTime;
jobContent.value.creator = creator;
return jobContent.value;
};
const cancel = () => {
comMessageRef.value.showQuestionMessage('是否要清空已扫描的物料和目标库位信息?', (res) => {
if (res) {
clearInfo();
}
});
};
const clearInfo = () => {
dataContent.value.itemCodeList.forEach((res) => {
if (res.recommendList != null) {
res.recommendList.forEach((res1) => {
if (res1.locationCodeList != null) {
res1.locationCodeList.forEach((res2) => {
if (res2.packingCodeList != null) {
res2.packingCodeList.forEach((res3) => {
res3.itemCode = "";
res3.qty = 0;
});
}
});
}
});
}
});
};
const updateData = (record) => {
calcHandleQty(detailSource.value)
};
const scanPopupGetFocus = () => {
if (scanPopup.value != undefined) {
scanPopup.value.packGetFocus();
}
};
const showMessage = (message) => {
comMessageRef.value.showMessage(message, (res) => {
if (res) {
afterCloseMessage();
}
});
};
const showErrorMessage = (message) => {
comMessageRef.value.showErrorMessage(message, (res) => {
if (res) {
afterCloseMessage();
}
});
};
const showScanMessage = (message) => {
comMessageRef.value.showScanMessage(message);
};
const showCommitSuccess = () => {
comMessageRef.value.showCommitSuccess();
};
const showCommitSuccessMessage = (hint) => {
comMessageRef.value.showSuccessMessage(hint, (res) => {
navigateBack(1);
});
};
const showRescanMessage = (message) => {
comMessageRef.value.showRescanMessage(message);
};
const afterCloseMessage = () => {
scanPopupGetFocus();
};
const closeScanMessage = () => {
scanPopupGetFocus();
};
const confirm = (data) => {
dataContent.value = data;
};
const confirmResult = (result) => {
dataContent.value = result;
};
// const openScanDetailPopup = () => {
// const datacontent = {...detailSource.value}; //
// comScanIssuePack.value.openScanPopup(datacontent, jobContent.value);
// };
const closeScanPopup = () => {
// updateCommitBtn();
};
const openScanPopup = ()=> {
let fromLocationCodeMes = '';
let fromlocationList = [];
for (let i = 0; i < detailSource.value.length; i++) {
let item = detailSource.value[i];
item.subList.forEach(l => {
//
let location = fromlocationList.find(res => res == l.fromLocationCode)
if (location == undefined) {
fromlocationList.push(l.fromLocationCode);
}
//
if (fromLocationCode == '') {
if (!l.scaned) {
fromLocationCodeMes = l.fromLocationCode;
}
}
})
}
fromLocationCode.value = fromLocationCodeMes
scanPopup.value.openScanPopupForJob(fromLocationCodeMes, fromlocationList,jobContent.value);
}
const confirmFromLocation = (fromLocationCodeParams)=>{
fromLocationCode.value = fromLocationCodeParams
}
</script>
<style scoped lang="scss">
.uni-numbox__value {
width: 40px;
}
button[disabled] {
background-color: #3C9CFF;
color: #fff;
opacity: 0.7;
}
// /deep/ .input-value {
// font-size: 16px;
// }
// /deep/ .uni-collapse-item__title-text {
// font-size: 16px;
// }
// /deep/ .uni-collapse-item--border {
// border-bottom-width: 0px;
// border-bottom-color: #ebeef5;
// }
// /deep/ .uni-collapse-item--border {
// border-bottom-width: 1px;
// border-bottom-color: #ebeef5;
// }
</style>

522
src/pages/fg/coms/comNoReceiptPopup.vue

@ -0,0 +1,522 @@
<template>
<view class="">
<u-popup v-model="show" mode="bottom" :maskClick="false">
<view class="uni-flex uni-column pop_customer">
<view class="" style="padding:10rpx">
<view class="uni-flex u-col-center uni-row space-between" style="padding: 10rpx 10rpx 20rpx 10rpx">
<view class="" style="font-size: 35rpx;">
{{title}}
</view>
<image style="width: 35rpx;height: 35rpx;" src="/static/icons/icons_close.svg"
@click="closeRequestPopup()"></image>
</view>
<view class='split_line'></view>
<view class="uni-flex uni-column" style="background-color: white; ">
<view class="uni-flex uni-column">
<view class="title " style="display: flex; align-items: center;padding: 10rpx;">
<text style=" flex-shrink: 0;width: 25%;">生产线</text>
<view class="customerBorder" @click="showSelectLine">
{{productionLineName}}
</view>
<u-select v-model="showProductLineSelect" mode="mutil-column-auto"
:list="productLineList" @confirm="confirmSelectLine" title="生产线-工位"></u-select>
<view class="">
<image src="/static/icons/down.svg" mode=""
style=" width: 40rpx;height: 40rpx;margin-left: 20rpx;" @click="showSelectLine">
</image>
</view>
</view>
<!-- <view class='split_line'></view>
<view class="title " style="display: flex; align-items: center;padding: 10rpx;">
<text style=" flex-shrink: 0;width: 25%;">计划日期</text>
<view class="customerBorder" @click="showSelectDate">
{{planDate}}
</view>
<u-select v-model="showDateSelect" mode="mutil-column-auto" :list="planDateList"
@confirm="confirmSelectDate"></u-select>
<view class="">
<image src="/static/icons/down.svg" mode=""
style=" width: 40rpx;height: 40rpx;margin-left: 20rpx;" @click="showSelectDate">
</image>
</view>
</view>
-->
<view class='split_line'></view>
<view class="title " style="display: flex;align-items: center;padding: 10rpx;">
<text style=" flex-shrink: 0; width: 25%;">物料代码</text>
<view class="customerBorder">
{{itemCode}}
</view>
<view v-if="bomVersion" class="" style="min-width: 160rpx;text-align: center;">
Bom版本{{bomVersion}}
</view>
<u-select v-model="showItemCodeSelect" mode="mutil-column-auto" :list="itemCodeList"
@confirm="confirmSelectItem" title="物料代码-Bom版本"></u-select>
<view class="">
<image src="/static/icons/down.svg" mode=""
style=" width: 40rpx;height: 40rpx;margin-left: 20rpx;"
@click="showSelectItemCode">
</image>
</view>
</view>
<view class='split_line'></view>
<view class="title " style="display: flex;align-items: center;padding: 10rpx;">
<text style=" flex-shrink: 0; width: 25%;">数量</text>
<u-input v-model="planQty"></u-input>
<view v-if="uom">({{getUomInfo(uom)}})</view>
<view class="">
<image src="" mode="" style=" width: 40rpx;height: 40rpx;margin-left: 20rpx;">
</image>
</view>
</view>
<view class='split_line'></view>
<view class="title " style="display: flex;align-items: center;padding: 10rpx;">
<text style=" flex-shrink: 0; width: 25%;">包装规格</text>
<view class="customerBorder">
{{packUnitName}}
</view>
<u-select v-model="showPackUnitSelect" mode="single-column" :list="packUnitList"
@confirm="confirmSelectPackUnit"></u-select>
<view class="">
<image src="/static/icons/down.svg" mode=""
style=" width: 40rpx;height: 40rpx;margin-left: 20rpx;"
@click="showSelectPackUnit">
</image>
</view>
</view>
<view class='split_line'></view>
<view class="title " style="display: flex;align-items: center;padding: 10rpx;">
<text style=" flex-shrink: 0; width: 25%;">批次</text>
<u-input v-model="batch"></u-input>
<view class="">
<image src="" mode="" style=" width: 40rpx;height: 40rpx;margin-left: 20rpx;">
</image>
</view>
</view>
</view>
</view>
<view class='split_line'></view>
<view class="uni-flex uni-row" style="align-items: center; margin-top: 20rpx; margin-bottom: 20rpx; margin-left: 10rpx;justify-content: space-between;">
<view class="title" >
创建上架申请
</view>
<view class="" style="margin-right: 20rpx;">
<u-switch v-model="putAwayRequestSwitch" active-color="#4DD865" inactive-color="#eee" size="35"
@change="switchPutAwayRequest"></u-switch>
</view>
</view>
<view class='split_line'></view>
<view class="uni-flex uni-row" style="align-items: center; margin-top: 20rpx; margin-bottom: 20rpx; margin-left: 10rpx; justify-content: space-between;" v-if="EnableQms">
<view class="title" >
创建检验申请
</view>
<view class="" style="margin-right: 20rpx;">
<u-switch v-model="putAwayInspectSwitch" active-color="#4DD865" inactive-color="#eee" size="35"
@change="switchPutAwayInspect"></u-switch>
</view>
</view>
</view>
<view class="uni-flex uni-row hide_border">
<button class="btn_edit_big_cancle" hover-class="btn_edit_big_after" @click="cancel()">取消</button>
<button class="btn_edit_big_confirm" hover-class="btn_edit_big_after" @click="confirm()">确认</button>
</view>
</view>
</u-popup>
<comMessage ref="comMessageRef"></comMessage>
</view>
</template>
<script setup lang="ts">
import {
getIssueJobByProductionline,
getPlaneInfoByproductLine,
getPackUnitByItemCode,
getProductionlineAndWorkStation,
getBomVersionByProductionline
} from '@/api/request2.js';
import {
getPackUnitName,
getUomInfo
} from '@/common/directory.js';
import {
getCurrDate,
getBatch8,
dateFormatData,
lastThreeDays,
getSwitchInfoByCode
} from '@/common/basic.js';
import {
calc
} from '@/common/calc.js';
import uom from '@/mycomponents/qty/uom.vue'
import packQty from '@/mycomponents/qty/packQty.vue'
import balanceStatus from '@/mycomponents/status/balanceStatus.vue'
import winScanItem from '@/mycomponents/scan/winScanItem.vue'
import { ref, onMounted } from 'vue';
const props = defineProps({
title: {
type: String,
default: '开工阶段'
},
itemCodeTypeList: {
type: Array,
default: () => []
}
});
const emit = defineEmits(['confirm']);
const itemCode = ref('');
const itemName = ref('请选择物料信息');
const uom = ref('');
const qty = ref(null);
const planQty = ref(0);
const goodQty = ref(0);
const planNumber = ref('');
const productLineCode = ref('');
const showProductLineSelect = ref(false);
const productLineList = ref([]);
const productionLineName = ref('请选择生产线');
const batch = ref('');
const packUnitName = ref('请选择包装规格');
const packUnit = ref('');
const packUnitList = ref([]);
const packQtyHint = ref('');
const packQty = ref(0);
const showPackUnitSelect = ref(false);
const itemCodeList = ref([]);
const showItemCodeSelect = ref(false);
const workStationCode = ref('');
const planDate = ref('');
const showDateSelect = ref(false);
const planDateList = ref([]);
const fgLocationCode = ref('');
const rawLocationCode = ref('');
const workshop = ref('');
const bomVersion = ref('');
const putAwayRequestSwitch = ref(true);
const putAwayInspectSwitch = ref(true);
const EnableQms = ref(true);
const show = ref(false)
const comMessageRef = ref(null);
const itemCodeFocus = ref(false);
onMounted(() => {
EnableQms.value = getSwitchInfoByCode('EnableQms');
});
const openRequestPopup = () => {
initData();
planDate.value = getCurrDate();
batch.value = planDate.value.replace('-', '').replace('-', '');
show.value = true
};
const initData = () => {
itemCode.value = '请选择物料信息';
uom.value = '';
planQty.value = 0;
goodQty.value = 0;
packQty.value = 0;
planNumber.value = '';
productLineCode.value = '';
showProductLineSelect.value = false;
productLineList.value = [];
productionLineName.value = '请选择生产线';
productLineCode.value = '';
batch.value = '';
packUnitName.value = '请选择包装规格';
packUnit.value = '';
packQtyHint.value = '';
showPackUnitSelect.value = false;
itemCodeList.value = [];
showItemCodeSelect.value = false;
workStationCode.value = '';
planDate.value = '';
showDateSelect.value = false;
planDateList.value = [];
fgLocationCode.value = '';
rawLocationCode.value = '';
workshop.value = '';
bomVersion.value = '';
putAwayRequestSwitch.value = true;
putAwayInspectSwitch.value = true;
};
const closeRequestPopup = () => {
show.value = false
};
const itemCodeLoseFocus = () => {
itemCodeFocus.value = false;
};
const confirm = () => {
if (!planDate.value) {
showErrorMessage('请先选择计划日期');
return;
}
if (productionLineName.value === '请选择生产线') {
showErrorMessage('请选择生产线');
return;
}
if (!batch.value) {
showErrorMessage('请输入批次例如:20200101');
return;
}
if (itemCode.value === '请选择物料信息') {
showErrorMessage('请选择物料信息');
return;
}
if (planQty.value <= 0) {
showErrorMessage('请输入完工数量');
return;
}
if (packUnitName.value === '请选择包装规格') {
showErrorMessage('请选择包装规格');
return;
}
if (!EnableQms.value) {
putAwayInspectSwitch.value = false;
}
callback();
};
const callback = () => {
const item = {
productionLineName: '',
productionLine: productLineCode.value, // 线
itemCode: itemCode.value,
itemName: itemName.value,
uom: getUomInfo(uom.value),
batch: batch.value,
packUnitName: packUnitName.value,
packUnit: packUnit.value,
packQtyHint: packQtyHint.value,
packQty: packQty.value,
planQty: planQty.value,
goodQty: goodQty.value,
planNumber: '',
workStationCode: workStationCode.value,
fgLocationCode: fgLocationCode.value,
rawLocationCode: rawLocationCode.value,
workshop: workshop.value,
bomVersion: bomVersion.value,
putAwayRequestSwitch: putAwayRequestSwitch.value,
putAwayInspectSwitch: putAwayInspectSwitch.value
};
closeRequestPopup();
emit('confirm', item);
};
const showErrorMessage = (message, type) => {
setTimeout(() => {
comMessageRef.value.showErrorMessage(message, (res) => {});
});
};
const cancel = (e) => {
closeRequestPopup();
};
const confirmSelectLine = (data) => {
productionLineName.value = data[0].label + '—' + data[1].label;
productLineCode.value = data[0].value;
workStationCode.value = data[1].value;
const parent = productLineList.value.filter((res) => res.value === productLineCode.value);
const fgLocation = parent[0].children.filter((children) => children.value === workStationCode.value);
fgLocationCode.value = fgLocation[0].fgLocationCode;
workshop.value = parent[0].workshop;
clearItemCode();
clearPackUnit();
};
const clearItemCode = () => {
planDate.value = getCurrDate();
itemCode.value = '请选择物料信息';
uom.value = '';
planQty.value = 0;
goodQty.value = 0;
planNumber.value = '';
bomVersion.value = '';
};
const confirmSelectDate = (data) => {
planDate.value = data[0].label;
batch.value = planDate.value.replace('-', '').replace('-', '');
};
const showSelectDate = () => {
showDateSelect.value = true;
const list = lastThreeDays(3);
planDateList.value = [];
list.forEach((res) => {
planDateList.value.push({
label: res,
value: ''
});
});
};
const showSelectLine = () => {
if (productLineList.value.length === 0) {
uni.showLoading({
title: '加载中',
mask: true
});
getProductionlineAndWorkStation().then((res) => {
uni.hideLoading();
if (res.data && res.data.length > 0) {
productLineList.value = res.data;
showProductLineSelect.value = true;
} else {
showErrorMessage('未查找到生产线信息');
}
}).catch((error) => {
uni.hideLoading();
showErrorMessage(error);
});
} else {
showProductLineSelect.value = true;
}
};
const showSelectItemCode = () => {
if (!productLineCode.value) {
showErrorMessage('请先选择生产线');
return;
}
uni.showLoading({
title: '加载中',
mask: true
});
getBomVersionByProductionline(productLineCode.value).then((res) => {
uni.hideLoading();
if (res.data && res.data.length > 0) {
itemCodeList.value = res.data;
showItemCodeSelect.value = true;
} else {
showErrorMessage('未查找到物料信息');
}
}).catch((error) => {
uni.hideLoading();
showErrorMessage(error);
});
};
const confirmSelectItem = (data) => {
itemCode.value = data[0].label;
bomVersion.value = data[1].value;
uom.value = data[0].uom;
clearPackUnit();
uni.showLoading({
title: '加载中',
mask: true
});
getPackUnitByItemCode(itemCode.value).then((res) => {
uni.hideLoading();
if (res.data && res.data.list.length > 0) {
res.data.list.forEach((item) => {
item.value = item.packUnit;
item.label = getPackUnitName(item.packUnit) + '(' + item.packQty + getUomInfo(item.uom) + ')';
});
packUnitList.value = res.data.list;
const defaultData = res.data.list.filter((item) => item.defaultPackageunit === 'TRUE');
confirmSelectPackUnit(defaultData);
}
}).catch((error) => {
uni.hideLoading();
});
};
const clearPackUnit = () => {
packUnitName.value = '请选择包装规格';
packUnit.value = '';
const pack = packUnitList.value.filter((r) => r.packUnit === packUnit.value);
packQtyHint.value = '';
packQty.value = 0;
};
const showSelectPackUnit = () => {
if (itemCode.value === '请选择物料信息') {
showErrorMessage('请先选择物料');
return;
}
uni.showLoading({
title: '加载中',
mask: true
});
getPackUnitByItemCode(itemCode.value).then((res) => {
uni.hideLoading();
if (res.data && res.data.list.length > 0) {
res.data.list.forEach((item) => {
item.value = item.packUnit;
item.label = getPackUnitName(item.packUnit) + '(' + item.packQty + getUomInfo(item.uom) + ')';
});
packUnitList.value = res.data.list;
showPackUnitSelect.value = true;
} else {
showErrorMessage('未查找到包装信息');
}
}).catch((error) => {
uni.hideLoading();
showErrorMessage(error);
});
};
const confirmSelectPackUnit = (data) => {
packUnitName.value = data[0].label;
packUnit.value = data[0].value;
const pack = packUnitList.value.filter((r) => r.packUnit === packUnit.value);
packQtyHint.value = pack[0].packQty + '(' + getUomInfo(pack[0].uom) + ')';
uom.value = getUomInfo(pack[0].uom);
packQty.value = pack[0].packQty;
};
const getUomInfo = (uom) => {
const item = getUomInfo(uom);
return item === '' ? uom : item.label;
};
const switchPutAwayRequest = (value) => {
console.log(value);
console.log('打印' + putAwayRequestSwitch.value);
putAwayRequestSwitch.value = value;
};
const switchPutAwayInspect = (value) => {
console.log(value);
putAwayInspectSwitch.value = value;
};
</script>
<style lang="scss">
.title {
font-size: 30rpx;
}
.customerBorder {
width: 100%;
border: 1rpx solid lightgray;
border-radius: 5rpx;
padding: 15rpx;
}
</style>

524
src/pages/fg/coms/comReceiptPopup.vue

@ -0,0 +1,524 @@
<template>
<view class="">
<u-popup v-model="show" mode="bottom" :maskClick="false">
<view class="uni-flex uni-column pop_customer">
<view class="" style="padding: 10rpx">
<view class="uni-flex u-col-center uni-row space-between" style="padding: 10rpx 10rpx 20rpx 10rpx">
<view class="" style="font-size: 35rpx">
{{ title }}
</view>
<image style="width: 35rpx; height: 35rpx" src="/static/icons/icons_close.svg" @click="closeRequestPopup()"></image>
</view>
<view class="split_line"></view>
<view class="uni-flex uni-column" style="background-color: white">
<view class="uni-flex uni-column">
<view class="title" style="display: flex; align-items: center; padding: 10rpx">
<text style="flex-shrink: 0; width: 25%">生产线</text>
<view class="customerBorder" @click="showSelectLine">
{{ productionLineName }}
</view>
<u-select v-model="showProductLineSelect" mode="mutil-column-auto" :list="productLineList" @confirm="confirmSelectLine"></u-select>
<view class="">
<image src="/static/icons/down.svg" mode="" style="width: 40rpx; height: 40rpx; margin-left: 20rpx" @click="showSelectLine"> </image>
</view>
</view>
<view class="split_line"></view>
<view class="title" style="display: flex; align-items: center; padding: 10rpx">
<text style="flex-shrink: 0; width: 25%">计划日期</text>
<view class="customerBorder" @click="showSelectDate">
{{ planDate }}
</view>
<u-select v-model="showDateSelect" mode="mutil-column-auto" :list="planDateList" @confirm="confirmSelectDate"></u-select>
<view class="">
<image src="/static/icons/down.svg" mode="" style="width: 40rpx; height: 40rpx; margin-left: 20rpx" @click="showSelectDate"> </image>
</view>
</view>
<view class="split_line"></view>
<view class="title" style="display: flex; align-items: center; padding: 10rpx">
<text style="flex-shrink: 0; width: 25%">物料代码</text>
<view class="customerBorder">
{{ itemCode }}
</view>
<view v-if="planQty > 0">{{ planQty }}({{ getUomInfo(uom) }})</view>
<u-select v-model="showItemCodeSelect" mode="single-column" :list="itemCodeList" @confirm="confirmSelectItem"></u-select>
<view class="">
<image src="/static/icons/down.svg" mode="" style="width: 40rpx; height: 40rpx; margin-left: 20rpx" @click="showItemList"> </image>
</view>
</view>
<!-- <view class="title " style="display: flex;align-items: center;padding: 10rpx;">
<text style=" flex-shrink: 0; width: 25%;">计划数量</text>
<view class="customerBorder">
{{planQty}}
</view>
<view class="">
<image src="" mode="" style=" width: 40rpx;height: 40rpx;margin-left: 20rpx;">
</image>
</view>
</view> -->
<view class="split_line"></view>
<view class="title" style="display: flex; align-items: center; padding: 10rpx">
<text style="flex-shrink: 0; width: 25%">包装规格</text>
<view class="customerBorder">
{{ packUnitName }}
</view>
<u-select v-model="showPackUnitSelect" mode="single-column" :list="packUnitList" @confirm="confirmSelectPackUnit"></u-select>
<view class="">
<image src="/static/icons/down.svg" mode="" style="width: 40rpx; height: 40rpx; margin-left: 20rpx" @click="showSelectPackUnit"> </image>
</view>
</view>
<view class="split_line"></view>
<view class="title" style="display: flex; align-items: center; padding: 10rpx">
<text style="flex-shrink: 0; width: 25%">批次</text>
<u-input v-model="batch"></u-input>
<view class="">
<image src="" mode="" style="width: 40rpx; height: 40rpx; margin-left: 20rpx" @click="showSelectLine"> </image>
</view>
</view>
<view class='split_line'></view>
<view class="uni-flex uni-row" style="align-items: center; margin-top: 20rpx; margin-bottom: 20rpx; margin-left: 10rpx;justify-content: space-between;">
<view class="title" >
创建上架申请
</view>
<view class="" style="margin-right: 20rpx;">
<u-switch v-model="putAwayRequestSwitch" active-color="#4DD865" inactive-color="#eee" size="35"
@change="switchPutAwayRequest"></u-switch>
</view>
</view>
<view class='split_line'></view>
<view class="uni-flex uni-row" style="align-items: center; margin-top: 20rpx; margin-bottom: 20rpx; margin-left: 10rpx; justify-content: space-between;" v-if="EnableQms">
<view class="title" >
创建检验申请
</view>
<view class="" style="margin-right: 20rpx;">
<u-switch v-model="putAwayInspectSwitch" active-color="#4DD865" inactive-color="#eee" size="35"
@change="switchPutAwayInspect"></u-switch>
</view>
</view>
</view>
</view>
</view>
<view class="uni-flex uni-row hide_border">
<button class="btn_edit_big_cancle" hover-class="btn_edit_big_after" @click="cancel()">取消</button>
<button class="btn_edit_big_confirm" hover-class="btn_edit_big_after" @click="confirm()">确认</button>
</view>
</view>
</u-popup>
<comMessage ref="comMessageRef"></comMessage>
</view>
</template>
<script setup lang="ts">
import { getIssueJobByProductionline, getPlaneInfoByproductLine, getPackUnitByItemCode, getProductionlineAndWorkStation } from '@/api/request2.js'
import { getPackUnitName, getUomInfo } from '@/common/directory.js'
import { getCurrDate, getBatch8, dateFormatData, lastThreeDays, getSwitchInfoByCode } from '@/common/basic.js'
import { calc } from '@/common/calc.js'
import uom from '@/mycomponents/qty/uom.vue'
import PackQty from '@/mycomponents/qty/packQty.vue'
import BalanceStatus from '@/mycomponents/status/balanceStatus.vue'
import WinScanItem from '@/mycomponents/scan/winScanItem.vue'
import { ref, onMounted } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
const props = defineProps({
title: {
type: String,
default: '开工阶段'
},
itemCodeTypeList: {
type: Array,
default: () => []
}
});
const emit = defineEmits(['confirm'])
const itemCode = ref('请选择物料信息');
const uom = ref('');
const qty = ref(null);
const planQty = ref(0);
const goodQty = ref(0);
const planNumber = ref('');
const productLineCode = ref('');
const showProductLineSelect = ref(false);
const productLineList = ref([]);
const productionLineName = ref('请选择生产线');
const productionLineCode = ref('');
const batch = ref('');
const packUnitName = ref('请选择包装规格');
const packUnit = ref('');
const packUnitList = ref([]);
const packQtyHint = ref('');
const packQty = ref(0);
const showPackUnitSelect = ref(false);
const itemCodeList = ref([]);
const showItemCodeSelect = ref(false);
const workStationCode = ref('');
const planDate = ref('');
const showDateSelect = ref(false);
const planDateList = ref([]);
const fgLocationCode = ref('');
const rawLocationCode = ref('');
const putAwayRequestSwitch = ref(true);
const putAwayInspectSwitch = ref(true);
const EnableQms = ref(true);
const show = ref(false)
const itemCodeFocus = ref(false)
const comMessageRef = ref(null);
onMounted(() => {
EnableQms.value = getSwitchInfoByCode('EnableQms');
console.log(777, EnableQms.value);
});
const openRequestPopup = () => {
initData();
planDate.value = getCurrDate();
batch.value = planDate.value.replace('-', '').replace('-', '');
show.value = true
};
const initData = () => {
itemCode.value = '请选择物料信息';
uom.value = '';
planQty.value = 0;
goodQty.value = 0;
packQty.value = 0;
planNumber.value = '';
productLineCode.value = '';
showProductLineSelect.value = false;
productLineList.value = [];
productionLineName.value = '请选择生产线';
productionLineCode.value = '';
batch.value = '';
packUnitName.value = '请选择包装规格';
packUnit.value = '';
packQtyHint.value = '';
showPackUnitSelect.value = false;
itemCodeList.value = [];
showItemCodeSelect.value = false;
workStationCode.value = '';
planDate.value = '';
showDateSelect.value = false;
planDateList.value = [];
fgLocationCode.value = '';
rawLocationCode.value = '';
putAwayRequestSwitch.value = true;
putAwayInspectSwitch.value = true;
};
const closeRequestPopup = () => {
show.value = false
};
const itemCodeLoseFocus = () => {
itemCodeFocus.value = false;
};
const confirm = () => {
if (!planDate.value) {
showErrorMessage('请先选择计划日期');
return;
}
if (productionLineName.value == '请选择生产线') {
showErrorMessage('请选择生产线');
return;
}
if (!batch.value) {
showErrorMessage('请输入批次例如:20200101');
return;
}
if (itemCode.value == '请选择物料信息') {
showErrorMessage('请选择物料信息');
return;
}
if (packUnitName.value == '请选择包装规格') {
showErrorMessage('请选择包装规格');
return;
}
if (!EnableQms.value) {
putAwayInspectSwitch.value = false;
}
callback();
};
const callback = () => {
const item = {
productionLineName: productionLineName.value,
productionLineCode: productionLineCode.value, // 线
itemCode: itemCode.value,
uom: getUomInfo(uom.value),
batch: batch.value,
packUnitName: packUnitName.value,
packUnit: packUnit.value,
packQtyHint: packQtyHint.value,
packQty: packQty.value,
planQty: planQty.value,
goodQty: goodQty.value,
planNumber: planNumber.value,
workStationCode: workStationCode.value,
fgLocationCode: fgLocationCode.value,
rawLocationCode: rawLocationCode.value,
putAwayRequestSwitch: putAwayRequestSwitch.value,
putAwayInspectSwitch: putAwayInspectSwitch.value
};
closeRequestPopup();
emit('confirm', item);
};
const showErrorMessage = (message) => {
setTimeout(() => {
comMessageRef.value.showErrorMessage(message, () => {});
});
};
const cancel = (e) => {
closeRequestPopup();
};
const confirmSelectLine = (data) => {
productionLineName.value = `${data[0].label}${data[1].label}`;
productionLineCode.value = data[0].value;
workStationCode.value = data[1].value;
const parent = productLineList.value.filter((res) => res.value == productionLineCode.value);
const fgLocation = parent[0].children.filter((children) => children.value == workStationCode.value);
fgLocationCode.value = fgLocation[0].fgLocationCode;
showProductLineSelect.value = false;
showSelectItemCode();
};
const clearItemCode = () => {
planDate.value = getCurrDate();
itemCode.value = '请选择物料信息';
uom.value = '';
planQty.value = 0;
goodQty.value = 0;
planNumber.value = '';
packUnit.value = '';
packQty.value = 0;
};
const confirmSelectDate = (data) => {
planDate.value = data[0].label;
batch.value = planDate.value.replace('-', '').replace('-', '');
afterSelectPlanData();
};
const showSelectDate = () => {
showDateSelect.value = true;
const list = lastThreeDays(3);
planDateList.value = [];
list.forEach((res) => {
planDateList.value.push({
label: res,
value: ''
});
});
};
const showSelectLine = () => {
if (productLineList.value.length == 0) {
uni.showLoading({
title: '加载中',
mask: true
});
getProductionlineAndWorkStation()
.then((res) => {
uni.hideLoading();
if (res.data && res.data.length > 0) {
productLineList.value = res.data;
showProductLineSelect.value = true;
} else {
showErrorMessage('未查找到生产线信息');
}
})
.catch((error) => {
uni.hideLoading();
showErrorMessage(error);
});
} else {
showProductLineSelect.value = true;
}
};
const afterSelectPlanData = () => {
itemCode.value = '请选择物料信息';
packUnit.value = '';
packQty.value = 0;
planQty.value = 0;
itemCode.value = '请选择物料信息';
uom.value = '';
packUnitName.value = '请选择包装规格';
packUnit.value = '';
packQtyHint.value = '';
itemCodeList.value = [];
showSelectItemCode();
putAwayRequestSwitch.value = true;
putAwayInspectSwitch.value = true;
};
const showItemList = () => {
showItemCodeSelect.value = true;
};
const showSelectItemCode = () => {
if (!planDate.value) {
showErrorMessage('请先选择计划日期');
return;
}
if (!productionLineCode.value) {
showErrorMessage('请先选择生产线');
return;
}
uni.showLoading({
title: '加载中',
mask: true
});
getPlaneInfoByproductLine(productionLineCode.value, planDate.value)
.then((res) => {
uni.hideLoading();
if (res.data && res.data.length > 0) {
res.data.forEach((item) => {
item.label = `${item.itemCode}${item.planQty}${getUomInfo(item.uom)})`;
item.value = item;
});
itemCodeList.value = res.data;
if (itemCodeList.value.length == 1) {
confirmSelectItem([itemCodeList.value[0]]);
} else {
showItemCodeSelect.value = true;
}
} else {
showErrorMessage(`未查找到该生产线在【${planDate.value}】日期的生产计划`);
}
})
.catch((error) => {
uni.hideLoading();
showErrorMessage(error);
});
};
const confirmSelectItem = (data) => {
const productionPlan = data[0].value;
itemCode.value = productionPlan.itemCode;
uom.value = productionPlan.uom;
planQty.value = productionPlan.planQty;
goodQty.value = productionPlan.goodQty;
planNumber.value = productionPlan.number;
clearPackUnit();
uni.showLoading({
title: '加载中',
mask: true
});
getPackUnitByItemCode(itemCode.value)
.then((res) => {
uni.hideLoading();
if (res.data && res.data.list.length > 0) {
res.data.list.forEach((item) => {
item.value = item.packUnit;
item.label = `${getPackUnitName(item.packUnit)}(${item.packQty}${getUomInfo(item.uom)})`;
});
packUnitList.value = res.data.list;
const defaultData = res.data.list.filter((item) => item.defaultPackageunit == 'TRUE');
confirmSelectPackUnit(defaultData);
}
})
.catch((error) => {
uni.hideLoading();
});
};
const clearPackUnit = () => {
packUnitName.value = '请选择包装规格';
packUnit.value = '';
const pack = packUnitList.value.filter((r) => r.packUnit == packUnit.value);
packQtyHint.value = '';
packQty.value = 0;
};
const showSelectPackUnit = () => {
if (itemCode.value == '请选择物料信息') {
showErrorMessage('请先选择物料');
return;
}
uni.showLoading({
title: '加载中',
mask: true
});
getPackUnitByItemCode(itemCode.value)
.then((res) => {
uni.hideLoading();
if (res.data && res.data.list.length > 0) {
res.data.list.forEach((item) => {
item.value = item.packUnit;
item.label = `${getPackUnitName(item.packUnit)}(${item.packQty}${getUomInfo(item.uom)})`;
});
packUnitList.value = res.data.list;
showPackUnitSelect.value = true;
} else {
showErrorMessage('未查找到包装信息');
}
})
.catch((error) => {
uni.hideLoading();
showErrorMessage(error);
});
};
const confirmSelectPackUnit = (data) => {
packUnitName.value = data[0].label;
packUnit.value = data[0].value;
const pack = packUnitList.value.filter((r) => r.packUnit == packUnit.value);
packQtyHint.value = `${pack[0].packQty}(${getUomInfo(pack[0].uom)})`;
packQty.value = pack[0].packQty;
};
const getUomInfo = (uom) => {
const item = getUomInfo(uom);
if (item == '') {
return uom;
}
return item.label;
};
const switchPutAwayRequest = (value) => {
console.log(value);
console.log("打印" + putAwayRequestSwitch.value);
putAwayRequestSwitch.value = value;
};
const switchPutAwayInspect = (value) => {
console.log(value);
putAwayInspectSwitch.value = value;
};
</script>
<style lang="scss">
.title {
font-size: 30rpx;
}
.customerBorder {
width: 100%;
border: 1rpx solid lightgray;
border-radius: 5rpx;
padding: 15rpx;
}
</style>

397
src/pages/fg/fgChange.vue

@ -0,0 +1,397 @@
<template>
<view class="page-wraper">
<view class="">
<com-blank-view @goScan="openScanPopup" v-if="currentPackage == null"></com-blank-view>
</view>
<view class="page-wraper" v-if="currentPackage != null">
<view class="page-main">
<u-collapse>
<u-collapse-item :open="true">
<template v-slot:title>
<view class="card_itemName" style="padding: 3px 5px; font-size: 28rpx"> 变更信息 </view>
</template>
<view class="">
<view class="uni-flex uni-row u-col-center padding_10">
<text style="font-size: 28rpx">变更前物料</text>
<view class="card_itemCode" style="margin-left: 20rpx">
{{ currentPackage.itemCode }}
</view>
</view>
<view class="uni-flex uni-row u-col-center padding_10">
<text style="font-size: 28rpx">变更后物料</text>
<view class="uni-flex u-col-center uni-row" @click="showSelect">
<view class="card_itemCode" style="margin-left: 20rpx; color: blue">
{{ toItemCode }}
</view>
<view class="">
<image src="/static/icons/down.svg" mode="" style="width: 40rpx; height: 40rpx; margin-left: 20rpx"> </image>
</view>
<u-select v-model="show" mode="single-column" :list="toItemList" @confirm="confirmSelect"></u-select>
</view>
</view>
<view class="uni-flex uni-row u-col-center padding_10"
><text style="font-size: 28rpx">变更原因</text>
<view class="uni-flex uni-row">
<u-input style="margin-left: 20px" v-model="reason"></u-input>
</view>
</view>
</view>
</u-collapse-item>
</u-collapse>
<balance style="margin-top: 5px" :dataContent="currentPackage" :isShowFromLocation="false"></balance>
<view style="margin-left: 30rpx; margin-top: 10rpx; margin-bottom: 10rpx" v-for="(item, index) in fgList" :key="index">
<uni-swipe-action :options="options">
<view :class="item.scaned == true ? 'scan_view' : 'auto-wrap'">
<light :lightCode="item.remark"></light>
</view>
</uni-swipe-action>
</view>
</view>
<view class="page-footer">
<view class="uni-flex u-col-center space-between padding_10" style="background-color: ghostwhite; width: 100%">
<view></view>
<view class="uni-flex uni-row">
<button class="btn_single_commit" hover-class="btn_commit_after" @click="commit">提交</button>
</view>
</view>
</view>
<win-scan-button @goScan="openScanFgPopup"></win-scan-button>
</view>
<win-com-scan-balance ref="scanPopup" @getBalance="getPackScanResult"
:bussinessCode="bussinessCode" :verifyCategory="true"
:isCheckLocationBalance="false">
</win-com-scan-balance>
<win-scan-fg-label ref="scanFgPopup" @getResult="getFgScanResult" title="灯码"></win-scan-fg-label>
<!-- <win-scan-pack ref="scanPopup" @getResult='getScanResult' title="制品标签" headerType="HMQ"></win-scan-pack> -->
<comMessage ref="comMessageRef"></comMessage>
</view>
</template>
<script setup lang="ts">
import { Decimal } from 'decimal.js' //
import { getSpareitemcode, getProductreceiptDetailbByPackingNumber, fgChangeCommit } from '@/api/request2.js'
import { getPrecisionStrategyList } from '@/common/balance.js'
import { goHome, getPackingNumberAndBatchByList, deepCopyData, getRemoveOption } from '@/common/basic.js'
import { calc } from '@/common/calc.js'
import { getInventoryStatusDesc, getDirectoryItemArray } from '@/common/directory.js'
import { getBusinessType } from '@/common/record.js'
import winScanButton from '@/mycomponents/scan/winScanButton.vue'
import winScanPack from '@/mycomponents/scan/winScanPack.vue'
import comProductRecord from '@/pages/productReceipt/coms/comProductRecord.vue'
import comBlankView from '@/mycomponents/common/comBlankView.vue'
import PackageAndItemCard from '@/mycomponents/package/PackageAndItemCard.vue'
import winComScanBalance from '@/mycomponents/scan/winComScanBalance.vue'
import winScanFgLabel from '@/mycomponents/scan/winScanFgLabel.vue'
import balance from '@/mycomponents/balance/balance.vue'
import light from '@/mycomponents/balance/light.vue'
import { ref } from 'vue';
import { onLoad, onNavigationBarButtonTap, onBackPress, onPullDownRefresh } from '@dcloudio/uni-app';
import {useCountStore} from '@/store'
const bussinessCode = ref('Relegate');
const businessType = ref({});
const show = ref(false);
const toItemCode = ref('请选择变更后物料');
const toItemInfo = ref({});
const toItemList = ref([]);
const fgList = ref([]);
const currentPackage = ref(null);
const reason = ref('');
const options = ref([]);
const comMessageRef = ref(null);
const scanPopup = ref(null);
const scanFgPopup = ref(null);
const store = useCountStore()
onLoad((option) => {
uni.setNavigationBarTitle({
title: option.title
});
getBusinessType();
});
onNavigationBarButtonTap((e) => {
if (e.index === 0) {
goHome();
}
});
onBackPress((e) => {});
onPullDownRefresh(() => {});
const getBusinessType = () => {
getBusinessType(bussinessCode.value, (res) => {
if (res.success) {
businessType.value = res.businessType;
const fromInventoryStatuses = getDirectoryItemArray(res.fromInventoryStatuses);
const fromLocationAreaTypeList = res.fromLocationAreaTypeList;
openScanPopup();
} else {
showErrorMessage(res.message);
}
});
};
const getPackScanResult = (result) => {
const { label } = result;
const pack = result.package;
uni.showLoading({
title: '加载中...',
mask: true
});
const params = {
available: 'TRUE',
changeBeforeCode: pack.itemCode,
pageSize: 20,
pageNo: 1
};
getSpareitemcode(params)
.then((res) => {
uni.hideLoading();
if (res.data.list.length == 0) {
showErrorMessage('未查找到变更后的物料,请在《量产件备件关系中进行配置》');
} else {
closeScanPopup();
res.data.list.forEach((r) => {
r.value = r.code;
r.label = `${r.code}(${r.name})`;
});
toItemList.value = res.data.list;
if (res.data.list.length == 1) {
toItemCode.value = res.data.list[0].code;
} else {
show.value = true;
}
//
getProductreceiptDetailbByPackingNumber(pack.number)
.then((res) => {
if (res.data.length > 0) {
fgList.value = res.data;
const pack = result.package;
const { balance } = result;
currentPackage.value = result.package;
currentPackage.value.packingNumber = pack.number;
currentPackage.value.locationCode = balance.locationCode;
currentPackage.value.inventoryStatus = balance.inventoryStatus;
} else {
showErrorMessage(`箱码【${pack.number}】未查找到绑定的灯码信息`);
}
})
.catch((res) => {
showErrorMessage(res.message);
});
}
})
.catch((res) => {
showErrorMessage(res.message);
});
};
const getFgScanResult = (result) => {
const item = fgList.value.find((r) => r.remark == result.content);
if (item != undefined) {
const index = fgList.value.findIndex((r) => r.remark == result.content);
if (item.scaned == true) {
comMessageRef.value.showQuestionMessage(`灯码【${result.content}】已经扫描,是否移除`, (res) => {
if (res) {
item.scaned = false;
fgList.value.splice(index, 1);
fgList.value.push(item); //
}
});
} else {
item.scaned = true;
fgList.value.unshift(fgList.value.splice(index, 1)[0]); //
}
calcHandleQty();
} else {
showErrorMessage('扫描的灯码不在灯码列表中');
}
};
const calcHandleQty = () => {
if (fgList.value.length > 0) {
currentPackage.value.handleQty = fgList.value.filter((r) => r.scaned == true).length;
}
};
const openScanPopup = () => {
setTimeout(() => {
scanPopup.value.openScanPopup(businessType.value);
scanPopupGetFocus();
});
};
const openScanFgPopup = () => {
setTimeout(() => {
scanFgPopup.value.openScanPopup(currentPackage.value.itemCode);
scanFgPopupGetFocus();
});
};
const commit = () => {
if (toItemCode.value == '请选择变更后物料') {
showMessage('请选择变更后物料');
return;
}
if (currentPackage.value.handleQty == null) {
comMessageRef.value.showQuestionMessage('是否要将全部灯码进行变更?', (res) => {
if (res) {
commitChange();
}
});
} else {
comMessageRef.value.showQuestionMessage(`是否要将已扫描的【${currentPackage.value.handleQty}】个灯码进行变更?`, (res) => {
if (res) {
commitChange();
}
});
}
};
const commitChange = () => {
uni.showLoading({
title: '提交中...',
mask: true
});
const params = setParams();
console.log('params', JSON.stringify(params));
fgChangeCommit(params)
.then((res) => {
uni.hideLoading();
currentPackage.value = null;
})
.catch((err) => {
uni.hideLoading();
showErrorMessage(err.message);
});
};
const setParams = () => {
const creator = store.id;
let subList = fgList.value.filter((r) => r.scaned == true);
if (currentPackage.value.handleQty == undefined) {
subList = fgList.value;
}
const item = {};
item.fromItemCode = currentPackage.value.itemCode;
item.fromItemName = currentPackage.value.itemName;
item.fromItemDesc1 = currentPackage.value.itemDesc1;
item.fromItemDesc2 = currentPackage.value.itemDesc2;
item.toItemCode = toItemCode.value;
item.toItemName = toItemInfo.value.itemName;
item.toItemDesc1 = toItemInfo.value.itemDesc1;
item.toItemDesc2 = toItemInfo.value.itemDesc2;
item.fromInventoryStatus = currentPackage.value.inventoryStatus;
item.fromQty = currentPackage.value.handleQty;
item.fromParentPackingNumber = currentPackage.value.parentNumber;
item.fromPackingNumber = currentPackage.value.packingNumber;
item.fromBatch = currentPackage.value.batch;
item.fromLocationCode = currentPackage.value.locationCode;
item.fromPackUnit = currentPackage.value.packUnit;
item.fromPackQty = currentPackage.value.packQty;
item.toPackQty = currentPackage.value.packUnit;
item.toPackUnit = currentPackage.value.packUnit;
item.subList = subList;
item.creator = creator;
return item;
};
const showMessage = (message) => {
setTimeout(() => {
scanPopupLoseFocus();
comMessageRef.value.showMessage(message, (res) => {
if (res) {
scanPopupGetFocus();
}
});
});
};
const showErrorMessage = (message) => {
setTimeout(() => {
scanPopupLoseFocus();
comMessageRef.value.showErrorMessage(message, (res) => {
if (res) {
scanPopupGetFocus();
}
});
});
};
const closeScanPopup = () => {
scanPopup.value.closeScanPopup();
};
const scanPopupGetFocus = () => {
if (scanPopup.value != undefined) {
scanPopup.value.getfocus();
}
};
const scanFgPopupGetFocus = () => {
if (scanFgPopup.value != undefined) {
scanFgPopup.value.getfocus();
}
};
const scanPopupLoseFocus = () => {
if (scanPopup.value != undefined) {
scanPopup.value.losefocus();
}
};
const afterCloseMessage = () => {
scanPopupGetFocus();
};
const closeScanMessage = () => {
scanPopupGetFocus();
};
const showCommitSuccessMessage = (hint) => {
comMessageRef.value.showSuccessMessage(hint, (res) => {
clearData();
openScanPopup();
});
};
const clearData = () => {
toItemCode.value = '请选择变更后物料';
toItemList.value = [];
fgList.value = [];
currentPackage.value = null;
reason.value = '';
};
const showSelect = () => {
show.value = !show.value;
};
const confirmSelect = (e) => {
toItemCode.value = e[0].value;
toItemInfo.value = e[0];
};
</script>
<style scoped lang="scss"></style>

506
src/pages/fg/receiptByPlan.vue

@ -0,0 +1,506 @@
<template>
<view class="page-wraper" style="background-color: #fff;">
<view class="header">
<view class="">
<com-blank-view @goScan='openFg' v-if="!dataContent"></com-blank-view>
</view>
<view class="" v-if="dataContent">
<view class="page-header">
<view class="header-view">
<view class="" style="font-size: 35rpx;padding: 10rpx; padding-left: 15rpx;">
生产计划{{dataContent.planNumber}}
</view>
<view class="cell_box uni-flex uni-row">
<view class="cell_info">
<view class="text_lightblue">完工库位</view>
<view style="font-size: 30rpx; margin-top: 13rpx;">{{dataContent.fgLocationCode}}
</view>
</view>
<view class="cell_info">
<view class="text_lightblue">计划数</view>
<view>{{dataContent.planQty}}{{dataContent.uom}}</view>
</view>
<view class="cell_info">
<view class="text_lightblue">已完工</view>
<view>{{ dataContent.goodQty }}{{dataContent.uom}}</view>
</view>
<view class="cell_info">
<view class="text_lightblue">未完工</view>
<view>{{dataContent.noGoodQty}}{{dataContent.uom}}</view>
</view>
</view>
</view>
</view>
<view class="" style="padding: 10rpx; margin-left: 10rpx;">
<item :dataContent="dataContent"></item>
</view>
<view class='split_line'></view>
<view class="uni-flex uni-row space-between" style="align-items: center;padding: 0 10rpx;">
<view style="word-break: break-all;">
<batch :batch="dataContent.batch"></batch>
<view class="card_view ">
<text style="color: #FFA500;padding: 5px;font-size: 30rpx;">包装规格</text>
<text class="card_content ">{{dataContent.packUnit}} </text>
</view>
</view>
<view style="word-break: break-all; font-size: 35rpx; font-weight: bold;">
<text v-if="dataContent.handleQty>0" style="color: #FFA500;">{{dataContent.handleQty}}/</text>
<text class="text_recommend">{{dataContent.packQtyHint}}</text>
</view>
</view>
<view class='split_line' v-if="dataContent"></view>
</view>
</view>
<view style="padding-bottom: 160rpx;" v-if="dataContent">
<scroll-view scroll-y="true" class="">
<view class="scan_view" v-for="(item, index) in showList" :key="index">
<u-swipe-action :options="options" @click="(...event)=>swipeClick(event,item,index)">
<view class="uni-flex uni-row "
style="margin-left: 30rpx; margin-top: 10rpx; margin-bottom: 10rpx;">
<light :lightCode='item.content'></light>
<!-- <view class="auto-wrap" style="font-size: 35rpx;font-weight: bold; width: 100%;">
<text style="font-size: 30rpx;color: #B66463;">唯一码 </text>
{{item.content}}
</view> -->
</view>
</u-swipe-action>
</view>
</scroll-view>
<u-loadmore :status="loadingType" v-if="showList.length>0" />
</view>
<view class="page-footer" style="position: fixed;bottom: 0;width:100%" v-if="dataContent">
<view class="uni-flex u-col-center space-between " style="background-color:ghostwhite; width: 100%; ">
<view class="">
<view class="uni-flex uni-row">
</view>
</view>
<view class=" uni-flex uni-row">
<button class="btn_single_clear" hover-class="btn_commit_after" style="margin-right: 50rpx;"
@click="clear">清空</button>
<button class="btn_single_commit" hover-class="btn_commit_after" @click="submit">提交</button>
</view>
</view>
</view>
<comReceiptPopup ref="comReceiptPopup" @confirm='requestConfirm'></comReceiptPopup>
<win-scan-button v-if="dataContent" @goScan='openScanPopup'></win-scan-button>
<win-scan-fg-label ref="scanPopup" @getResult='getScanResult' title='灯码标签'></win-scan-fg-label>
<comMessage ref="comMessage"></comMessage>
</view>
</template>
<script setup lang="ts">
import { ref, getCurrentInstance, nextTick } from 'vue'
import { onLoad, onShow, onNavigationBarButtonTap, onReady, onBackPress, onReachBottom, onPullDownRefresh } from '@dcloudio/uni-app'
import { isCheckMesCode, planReceiptSubmit,
createPutawayRequestByPlan, createInspectRequestByPlan,
getPlanByNumber,getBalanceToPackage,createByPlanSubmit,
batchPrintingLable } from '@/api/request2.js'
import { calc } from '@/common/calc.js'
import storage from '@/common/utils/storage.js'
import { getRemoveOption, deepCopyData,
getCurrDateTime, compare,getSwitchInfoByCode} from '@/common/basic.js'
import {Exception} from 'sass';
import winScanButton from '@/mycomponents/scan/winScanButton.vue'
import comBlankView from '@/mycomponents/common/comBlankView.vue'
import comReceiptPopup from '@/pages/fg/coms/comReceiptPopup.vue'
import item from '@/mycomponents/item/item.vue'
import batch from '@/mycomponents/balance/batch.vue'
import pack from '@/mycomponents/balance/pack.vue'
import winScanFgLabel from '@/mycomponents/scan/winScanFgLabel.vue'
import comFgCard from '@/pages/productReceipt/coms/comFgCard.vue'
import light from '@/mycomponents/balance/light.vue'
const dataContent = ref(null)
const options = ref([])
const showList = ref([])
const allList = ref([])
const index = ref(1)
const loadingType = ref('')
const loadingType = ref('')
const pageSize = ref(500)
const comReceiptPopupRef = ref()
const scanPopup = ref()
const comMessageRef = ref()
const settingPutAwayRequestSwitch = ref(true)
const settingPutAwayInspectSwitch = ref(true)
onLoad(() => {
options.value = getRemoveOption()
openFg()
})
onReachBottom(() => {
console.log('onReachBottom')
//
if (loadingType.value == 'nomore') {
return
}
index.value++
const list = getDataPage(index.value, pageSize.value)
if (list.length > 0) {
// this.showList=list
showList.value = showList.value.concat(list)
} else {
//
loadingType.value = 'nomore'
}
})
const openFg = () => {
setTimeout((res) => {
if (comReceiptPopupRef.value) {
comReceiptPopupRef.value.openRequestPopup()
}
}, 600)
}
const requestConfirm = (result) => {
dataContent.value = {
itemCode: result.itemCode,
planNumber: result.planNumber, //
handleQty: 0,
qty: 0,
planQty: result.planQty,
goodQty: result.goodQty,
noGoodQty: calc.sub(result.planQty, result.goodQty),
packQtyHint: result.packQtyHint,
packQty: result.packQty,
uom: result.uom,
batch: result.batch,
packUnit: result.packUnit,
workStationCode: result.workStationCode,
fgLocationCode: result.fgLocationCode,
putAwayRequestSwitch: result.putAwayRequestSwitch,
putAwayInspectSwitch: result.putAwayInspectSwitch,
subList: []
}
settingPutAwayRequestSwitch.value = result.putAwayRequestSwitch
settingPutAwayInspectSwitch.value = result.putAwayInspectSwitch
}
const initList = () => {
index.value = 1
showList.value = []
loadingType.value = ''
showList.value = getDataPage(index.value, pageSize.value)
dataContent.value.handleQty = showList.value.length;
}
const getDataPage = (pageNo, pageSize) => {
//
const totalPages = Math.ceil(allList.value.length / pageSize)
//
const start = (pageNo - 1) * pageSize
const end = start + pageSize //
return allList.value.slice(start, end)
}
const swipeClick = (e, dataContent, index) => {
if (e.content.text == '移除') {
comMessageRef.value.showQuestionMessage('是否要移除', (res) => {
if (res) {
allList.value.splice(index, 1)
initList()
}
})
}
}
const submit = () => {
if (allList.value.length == 0) {
showErrorMessage('请先扫描唯一码')
return
}
if (allList.value.length < dataContent.value.packQty) {
comMessageRef.value.showQuestionMessage('扫描数量小于包装规格数量,是否提交?', (res) => {
if (res) {
commit()
}
})
} else {
commit()
}
}
const commit = async () => {
let list = []
try {
let startTime = new Date()
uni.showLoading({
title: '提交中...',
mask: true
})
const params = setParams()
console.log(JSON.stringify(params))
const list = []
const planData = await createByPlanSubmit(params)
if (planData.data.tb1 && planData.data.tb1.length > 0) {
planData.data.tb1.forEach((item) => {
list.push({
itemCode: item.itemCode, //
itemName: item.itemName, //
packName: item.packName, //
packageCode: item.toPackingNumber, //
batch: item.toBatch, //
parentNumber: item.parentNumber, //
itemType: item.itemType, //
asnNumber: item.asnNumber, // ASN
supplierCode: item.supplierCode, //
qty: item.qty, //
printTimes: getCurrDateTime(), //
productionLineCode: item.productionLineCode, // 线
barcodeString: item.barcodeString, //
barcodeBase64: '',
requestNumber: item.requestNumber
})
})
} else {
throw new Error('提交失败未获取到打印信息')
}
if (planData.data.tb2 && planData.data.tb2.list.length > 0) {
let planInfo = planData.data.tb2.list[0]
if (planInfo.goodQty >= planInfo.planQty) {
uni.showToast({
title:"计划已完成",
duration:2000
})
clearData()
} else {
//
dataContent.value.planQty = planInfo.data.list[0].planQty
dataContent.value.goodQty = planInfo.data.list[0].goodQty
dataContent.value.noGoodQty = calc.sub(planInfo.planQty, planInfo.goodQty)
dataContent.value.handleQty = 0;
dataContent.value.subList = []
showList.value = []
allList.value = []
index.value = 1
}
} else {
throw new Error('提交失败未获取到计划信息')
}
uni.hideLoading()
let hintMsg = "提交成功\n生成装配收货记录\n";
// showCommitSuccessMessage('<br><br>', list)
if (list.length > 0 && list[0].requestNumber) {
hintMsg += list[0].requestNumber
}
nextTick(() => {
showCommitSuccessMessage(hintMsg, list)
})
} catch (error) {
uni.hideLoading()
const hint = error.message ? error.message : error
if (hint.indexOf('请返回开工阶段') > -1) {
showMessage('计划已完成')
clearData()
} else {
showErrorMessage(hint)
}
}
startSetting(list)
}
const startSetting = async (list)=> {
//
if (settingPutAwayRequestSwitch.value) {
if (list.length > 0 && list[0].requestNumber) {
await createPutawayRequestByPlan(list[0].requestNumber)
}
}
//
if (settingPutAwayInspectSwitch.value) {
if (list.length > 0 && list[0].requestNumber) {
await createInspectRequestByPlan(list[0].requestNumber)
}
}
}
const setParams = () => {
allList.value.forEach((res) => {
res.outsideItemCode = res.itemCode
res.outsideProduceDate = null
res.outsideSerialNumber = res.order
})
dataContent.value.subList = allList.value
return dataContent.value
}
const clear = () => {
comMessageRef.value.showQuestionMessage('是否要清空?', (res) => {
if (res) {
clearData()
openFg()
}
})
}
const clearData = () => {
dataContent.value = null
showList.value = []
allList.value = []
index.value = 1
}
const openScanPopup = () => {
const { itemCode } = dataContent.value
console.log('物料', itemCode)
scanPopup.value.openScanPopup(itemCode)
}
const getScanResult = (result) => {
// TODO
// mes
isCheckMesCode(result.content)
.then((res) => {
if (res.data) {
if (that.dataContent) {
const itemIndex = this.allList.findIndex((r) => r.content == result.content)
//
if (itemIndex == -1) {
// if (this.allList.length > this.dataContent.packQty) {
// this.showErrorMessage("")
// return;
// }
result.countTime = new Date()
allList.value.push(result)
allList.value.sort(compare('countTime')) //
initList()
scanPopupGetFocus()
calcFgQty()
} else {
comMessageRef.value.showQuestionMessage(`唯一码【${result.content}】已经扫描,是否移除`, (res) => {
if (res) {
allList.value.splice(itemIndex, 1)
allList.value.sort(compare('countTime')) //
initList()
calcFgQty()
}
})
}
}
}
})
.catch((error) => {
showErrorMessage(error)
})
}
const calcFgQty = () => {
dataContent.value.handleQty = showList.value.length
if (dataContent.value.handleQty == dataContent.value.packQty || (dataContent.value.noGoodQty < dataContent.value.packQty && dataContent.value.handleQty == dataContent.value.noGoodQty)) {
if (scanPopup.value) {
scanPopup.value.closeScanPopup()
}
commit()
}
}
const scanPopupGetFocus = () => {
if (scanPopup.value) {
scanPopup.value.getfocus()
}
}
const scanPopupLoseFocus = () => {
if (scanPopup.value) {
scanPopup.value.losefocus()
}
}
const getH5BatchPrintingLable = (number)=> {
batchPrintingLable(number).then(resLable => {
console.log('batchPrintingLable', resLable)
uni.hideLoading()
if(resLable.data){
const webUrl = `${import.meta.env.VITE_JMREPORT_BASE_URL}/jmreport/view/922734157577715712`
const webData = {
token: storage.getStorage(storage.constant.token),
asn_number: resLable.data
}
uni.navigateTo({
url: `/pages/pointProductReceipt/webview?url=${webUrl}&webData=${JSON.stringify(webData)}`
});
}else {
showErrorMessage(number + "批量打印标签 H5失败")
}
}).catch(error => {
uni.hideLoading()
showErrorMessage(error)
})
}
const print = (pointData)=> {
// #ifdef APP
if (pointData.length > 0) {
uni.navigateTo({
url: `/pages/point/index?points=${JSON.stringify(pointData)}`
});
}
// #endif
// #ifdef H5
let packingNumber = []
pointData.forEach(item=>{
packingNumber.push(item.packageCode)
})
if(packingNumber.length == 0){
showErrorMessage('包装号不能为空!')
return
}
uni.showLoading({
title: "正在获取打印信息",
mask: true
})
getBalanceToPackage({
packingNumber: packingNumber.join(',')
}).then(res => {
console.log('PC打印', res)
if (res.data && res.data.number) {
getH5BatchPrintingLable(res.data.number)
} else {
uni.hideLoading()
let hint = ""
packingNumber.forEach(item => {
hint += item
})
hint += "根据库存余额获取包装信息"
showErrorMessage(hint)
}
}).catch(error => {
uni.hideLoading()
showErrorMessage(error)
})
// #endif
}
const showCommitSuccessMessage = (hint, pointData) => {
comMessageRef.value.showSuccessMessage(hint, (res) => {
print(pointData)
})
}
const showErrorMessage = (message) => {
comMessageRef.value.showErrorMessage(message, (res) => {
if (res) {
scanPopupGetFocus()
}
})
}
const showMessage = (message)=> {
comMessageRef.value.showMessage(message, res => {
if (res) {
openFg();
}
});
}
</script>
<style scoped lang="scss">
.item {
background-color: #fff;
}
.item_scaned {
background-color: antiquewhite;
}
.auto-wrap {
white-space: normal;
word-break: break-all;
overflow-wrap: break-word;
/* 对于兼容性更好的情况 */
}
</style>

510
src/pages/fg/receiptNoPlan.vue

@ -0,0 +1,510 @@
<template>
<view class="page-wraper" style="background-color: #fff;">
<view class="header">
<view class="">
<com-blank-view @goScan='openFg' v-if="!dataContent"></com-blank-view>
</view>
<view class="" v-if="dataContent">
<view class="page-header">
<view class="header-view">
<view class="cell_box uni-flex uni-row">
<view class="cell_info">
<view class="text_lightblue">完工库位</view>
<view style="font-size: 30rpx; margin-top: 13rpx;">{{dataContent.fgLocationCode}}
</view>
</view>
<view class="cell_info">
<view class="text_lightblue">报工数量</view>
<view>{{dataContent.planQty}}{{dataContent.uom}}</view>
</view>
<view class="cell_info">
<view class="text_lightblue">已报工数量</view>
<view>{{scanedQty}}{{dataContent.uom}}</view>
</view>
</view>
</view>
</view>
<view class='split_line'></view>
<view class="" style="padding: 10rpx;margin-left: 10rpx;">
<item :dataContent="dataContent"></item>
</view>
<view class='split_line'></view>
<view class="uni-flex uni-row space-between" style="align-items: center;padding-left:10rpx">
<view style="word-break: break-all;">
<batch :batch="dataContent.batch"></batch>
<view class="card_view ">
<text style="color: #FFA500;padding: 5px;font-size: 30rpx;">包装规格</text>
<text class="card_content ">{{dataContent.packUnit}} </text>
</view>
</view>
<view style="word-break: break-all; font-size: 35rpx; font-weight: bold;">
<text v-if="dataContent.handleQty>0" style="color: #FFA500;">{{dataContent.handleQty}}/</text>
<!-- {{dataContent.packQtyHint}} -->
<text class="text_recommend">{{dataContent.packQtyHint}}</text>
</view>
</view>
</view>
</view>
<view style="margin-top: 350rpx; padding-bottom: 160rpx;" v-if="dataContent">
<scroll-view scroll-y="true" class="">
<view class="scan_view" v-for="(item, index) in showList" :key="index">
<u-swipe-action :options="options" @click="(...event)=>swipeClick(event,item,index)">
<<view class="uni-flex uni-row "
style="margin-left: 30rpx; margin-top: 10rpx; margin-bottom: 10rpx;">
<light :lightCode='item.content'></light>
<!-- <view class="auto-wrap" style="font-size: 35rpx;font-weight: bold; width: 100%;">
<text style="font-size: 30rpx;color: #B66463;">唯一码 </text>
{{item.content}}
</view> -->
</view>
</u-swipe-action>
<u-line color="#D8D8D8"></u-line>
</view>
</scroll-view>
<u-loadmore :status="loadingType" v-if="showList.length>0" />
</view>
<view class="page-footer" v-if="dataContent">
<view class="uni-flex u-col-center space-between " style="background-color:ghostwhite; width: 100%; ">
<view class="">
<view class="uni-flex uni-row">
</view>
</view>
<view class=" uni-flex uni-row">
<button class="btn_single_clear" hover-class="btn_commit_after" style="margin-right: 50rpx;"
@click="clear">清空</button>
<button class="btn_single_commit" hover-class="btn_commit_after" @click="submit">提交</button>
</view>
</view>
</view>
<comNoReceiptPopup ref="comNoReceiptPopupRef" @confirm='requestConfirm'></comNoReceiptPopup>
<win-scan-button v-if="dataContent" @goScan='openScanPopup'></win-scan-button>
<win-scan-fg-label ref="scanPopup" @getResult='getScanResult' title='制品标签'></win-scan-fg-label>
<comMessage ref="comMessage"></comMessage>
</view>
</template>
<script setup lang="ts">
import {
isCheckMesCode,
planReceiptSubmit,
createPutawayRequestByPlan,
createInspectRequestByPlan,
getPlanByNumber,
getBalanceToPackage,
batchPrintingLable,
createByPlanSubmit
} from '@/api/request2.js';
import {calc} from '@/common/calc.js';
import storage from '@/common/utils/storage.js'
import {
getRemoveOption,
deepCopyData,
getCurrDateTime,
compare,
getSwitchInfoByCode
} from '@/common/basic.js';
import winScanButton from '@/mycomponents/scan/winScanButton.vue'
import comBlankView from '@/mycomponents/common/comBlankView.vue'
import comNoReceiptPopup from '@/pages/fg/coms/comNoReceiptPopup.vue'
import item from '@/mycomponents/item/item.vue'
import batch from '@/mycomponents/balance/batch.vue'
import winScanFgLabel from "@/mycomponents/scan/winScanFgLabel.vue"
import light from '@/mycomponents/balance/light.vue'
import { ref } from 'vue';
import { onLoad, onShow, onReachBottom } from '@dcloudio/uni-app';
const dataContent = ref(null);
const options = ref([]);
const showList = ref([]);
const allList = ref([]);
const index = ref(1);
const loadingType = ref("");
const pageSize = ref(20);
const scanedQty = ref(0);
const settingPutAwayRequestSwitch = ref(true);
const settingPutAwayInspectSwitch = ref(true);
const comNoReceiptPopupRef = ref(null);
const comMessageRef = ref(null);
const scanPopup = ref(null);
onLoad(() => {
options.value = getRemoveOption();
openFg();
});
onShow(() => {});
onReachBottom(() => {
console.log("onReachBottom");
if (loadingType.value === 'nomore') {
return;
}
index.value++;
const list = getDataPage(index.value, pageSize.value);
if (list.length > 0) {
showList.value = showList.value.concat(list);
} else {
loadingType.value = "nomore";
}
});
const openFg = () => {
setTimeout(() => {
if (comNoReceiptPopupRef.value) {
comNoReceiptPopupRef.value.openRequestPopup();
}
}, 600);
};
const requestConfirm = (result) => {
dataContent.value = {
itemCode: result.itemCode,
planNumber: result.planNumber, //
handleQty: 0,
qty: 0,
planQty: result.planQty,
goodQty: result.goodQty,
noGoodQty: calc.sub(result.planQty, result.goodQty),
packQtyHint: result.packQtyHint,
packQty: result.packQty,
uom: result.uom,
batch: result.batch,
packUnit: result.packUnit,
workStationCode: result.workStationCode,
fgLocationCode: result.fgLocationCode,
subList: [],
productionLine: result.productionLine,
bomVersion: result.bomVersion,
workshop: result.workshop,
team: "",
shift: "",
putAwayRequestSwitch: result.putAwayRequestSwitch,
putAwayInspectSwitch: result.putAwayInspectSwitch
};
settingPutAwayRequestSwitch.value = result.putAwayRequestSwitch;
settingPutAwayInspectSwitch.value = result.putAwayInspectSwitch;
};
const initList = () => {
index.value = 1;
showList.value = [];
loadingType.value = "";
showList.value = getDataPage(index.value, pageSize.value);
};
const getDataPage = (pageNo, pageSize) => {
const totalPages = Math.ceil(allList.value.length / pageSize);
const start = (pageNo - 1) * pageSize;
const end = start + pageSize;
return allList.value.slice(start, end);
};
const swipeClick = (e, dataContent, index) => {
if (e.content.text === "移除") {
comMessageRef.value.showQuestionMessage("是否要移除", (res) => {
if (res) {
showList.value.splice(index, 1);
calcFgQty();
}
});
}
};
const submit = () => {
if (showList.value.length === 0) {
showErrorMessage("请先扫描唯一码");
return;
}
if (showList.value.length < dataContent.value.packQty) {
comMessageRef.value.showQuestionMessage("扫描数量小于包装规格数量,是否提交?", (res) => {
if (res) {
commit();
}
});
} else {
commit();
}
};
const commit = async () => {
let list = [];
try {
uni.showLoading({
title: "提交中...",
mask: true
});
const params = setParams();
const planData = await createByPlanSubmit(params);
if (planData.data.tb1 && planData.data.tb1.length > 0) {
planData.data.tb1.forEach((item) => {
list.push({
itemCode: item.itemCode, //
itemName: item.itemName, //
packName: item.packName, //
packageCode: item.toPackingNumber, //
batch: item.toBatch, //
parentNumber: item.parentNumber, //
itemType: item.itemType, //
asnNumber: item.asnNumber, // ASN
supplierCode: item.supplierCode, //
qty: item.qty, //
printTimes: getCurrDateTime(), //
productionLineCode: item.productionLineCode, // 线
barcodeString: item.barcodeString, //
barcodeBase64: '',
requestNumber: item.requestNumber
});
});
} else {
throw new Error("提交失败");
}
let hintMsg = "提交成功\n生成装配收货记录\n";
if (list.length > 0 && list[0].requestNumber) {
hintMsg += list[0].requestNumber;
}
showCommitSuccessMessage(hintMsg, list);
scanedQty.value += showList.value.length;
showList.value = [];
dataContent.value.handleQty = 0;
uni.hideLoading();
} catch (error) {
uni.hideLoading();
const hint = error.message ? error.message : error;
showErrorMessage(hint);
}
startSetting(list);
};
const startSetting = async (list) => {
if (settingPutAwayRequestSwitch.value) {
if (list.length > 0 && list[0].requestNumber) {
await createPutawayRequestByPlan(list[0].requestNumber);
}
}
if (settingPutAwayInspectSwitch.value) {
if (list.length > 0 && list[0].requestNumber) {
await createInspectRequestByPlan(list[0].requestNumber);
}
}
console.log("提交所有完成" + getCurrDateTime());
};
const setParams = () => {
showList.value.forEach((res) => {
res.outsideItemCode = res.itemCode;
res.outsideProduceDate = null;
res.outsideSerialNumber = res.order;
});
dataContent.value.subList = showList.value;
return dataContent.value;
};
const clear = () => {
comMessageRef.value.showQuestionMessage("是否要清空?", (res) => {
if (res) {
clearData();
openFg();
}
});
};
const clearData = () => {
dataContent.value = null;
showList.value = [];
allList.value = [];
index.value = 1;
};
const openScanPopup = () => {
const itemCode = dataContent.value.itemCode;
console.log("物料", itemCode);
scanPopup.value.openScanPopup(itemCode);
};
const getScanResult = (result) => {
isCheckMesCode(result.content).then((res) => {
if (res.data) {
if (dataContent.value) {
const itemIndex = showList.value.findIndex((r) => r.content === result.content);
if (itemIndex === -1) {
result.countTime = new Date();
showList.value.push(result);
showList.value.sort(compare('countTime'));
calcFgQty();
} else {
comMessageRef.value.showQuestionMessage(`唯一码【${result.content}】已经扫描,是否移除`, (res) => {
if (res) {
showList.value.splice(itemIndex, 1);
showList.value.sort(compare('countTime'));
calcFgQty();
}
});
}
}
}
}).catch((error) => {
showErrorMessage(error);
});
};
const calcFgQty = () => {
dataContent.value.handleQty = showList.value.length;
if (parseFloat(dataContent.value.planQty) - parseFloat(scanedQty.value) <= parseFloat(dataContent.value.packQty)) {
if (parseFloat(dataContent.value.handleQty) === parseFloat(dataContent.value.planQty) - parseFloat(scanedQty.value)) {
if (scanPopup.value) {
scanPopup.value.closeScanPopup();
}
commit();
}
} else {
if (parseFloat(dataContent.value.handleQty) === parseFloat(dataContent.value.packQty)) {
if (scanPopup.value) {
scanPopup.value.closeScanPopup();
}
commit();
}
}
};
const scanPopupGetFocus = () => {
if (scanPopup.value) {
scanPopup.value.getfocus();
}
};
const scanPopupLoseFocus = () => {
if (scanPopup.value) {
scanPopup.value.losefocus();
}
};
const getH5BatchPrintingLable = (number) => {
batchPrintingLable(number).then((resLable) => {
const webUrl = `${import.meta.env.VITE_JMREPORT_BASE_URL}/jmreport/view/922734157577715712`;
const webData = {
token: storage.getStorage(storage.constant.token),
asn_number: resLable.data
};
if (scanedQty.value + showList.value.length === dataContent.value.planQty) {
uni.redirectTo({
url: `/pages/pointProductReceipt/webview?url=${webUrl}&webData=${JSON.stringify(webData)}`
});
} else {
uni.navigateTo({
url: `/pages/pointProductReceipt/webview?url=${webUrl}&webData=${JSON.stringify(webData)}`
});
}
});
};
const print = (pointData) => {
if (pointData.length > 0) {
if (scanedQty.value + showList.value.length === dataContent.value.planQty) {
uni.redirectTo({
url: `/pages/point/index?points=${JSON.stringify(pointData)}`
});
} else {
uni.navigateTo({
url: `/pages/point/index?points=${JSON.stringify(pointData)}`
});
}
}
const packingNumber = pointData.map((item) => item.packageCode).join(',');
getBalanceToPackage({ packingNumber }).then((res) => {
console.log('PC打印', res);
getH5BatchPrintingLable(res.data.number);
}).catch((error) => {
showErrorMessage(error);
});
};
const showCommitSuccessMessage = (hint, pointData) => {
comMessageRef.value.showSuccessMessage(hint, (res) => {
print(pointData);
});
};
const showErrorMessage = (message) => {
comMessageRef.value.showErrorMessage(message, (res) => {
if (res) {
scanPopupGetFocus();
}
});
};
</script>
<style scoped lang="scss">
page {
width: 100%;
height: 100%;
background-color: #fff;
}
.page-wraper {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
}
.header {
position: fixed;
left: 0;
width: 100%;
background-color: #fff;
z-index: 10;
}
.page-footer {
position: fixed;
bottom: 0;
left: 0;
right: 0;
}
.page-main {
flex: 1;
position: relative;
}
.page-main-scroll {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
.page-main-list {
/* height: 80rpx;
line-height: 80rpx; */
text-align: center;
background: #e0e0e0;
}
.item {
background-color: #fff;
}
.item_scaned {
background-color: antiquewhite;
}
.auto-wrap {
white-space: normal;
word-break: break-all;
overflow-wrap: break-word;
/* 对于兼容性更好的情况 */
}
</style>

184
src/pages/inventoryMove/coms/comInventoryDetailCardBatch.vue

@ -0,0 +1,184 @@
<template>
<view class="" style="background-color: #fff;">
<!-- <item-qty :dataContent="dataContent" :handleQty="dataContent.handleQty"></item-qty> -->
<item-compare-qty :dataContent="dataContent" :handleQty="dataContent.handleQty" :isShowStdPack="false">
</item-compare-qty>
<view class='split_line'></view>
<view class="" v-for="(item,index) in dataContent.subList">
<u-swipe-action ref="swipeAction" v-if="index ==0"
:options="(item.scaned&&isEdit)?editAndRemoveOptions : item.scaned? removeOptions:options"
@click="(...event)=>swipeClick(event,item)"
:class="item.scaned?'scan_view':''">
<view style="display: flex;">
<view style="flex: 1;">
<batch v-if="item.batch" :batch="item.batch"></batch>
<location v-if="item.fromLocationCode" title="来源库位" :locationCode="item.fromLocationCode">
</location>
<to-location v-if="item.toLocationCode" title="目标库位" :locationCode="item.toLocationCode">
</to-location>
</view>
<text style="font-size: 30rpx;color: #2979ff; " @click="copy(item)" v-if="isDevlement()">复制</text>
</view>
</u-swipe-action>
</view>
<balance-qty-edit ref="qtyEdit" :settingParam="settingParam" @confirm="confirm"
:allowEditStatus="true"></balance-qty-edit>
<win-scan-location ref="scanLocationCode" :locationAreaTypeList="locationAreaTypeList" title="目标库位"
@getLocation='getLocation'></win-scan-location>
<detail-info-popup ref="detailInfoPopup"></detail-info-popup>
<comMessage ref="message"></comMessage>
</view>
</template>
<script setup lang="ts">
import {ref, watch, onMounted, computed} from 'vue';
import itemQty from '@/mycomponents/item/itemQty.vue'
import recommend from '@/mycomponents/recommend/recommend.vue'
import balanceQtyEdit from '@/mycomponents/qty/balanceQtyEdit.vue'
import detailInfoPopup from '@/pages/inventoryMove/coms/detailInfoPopup.vue'
import winScanLocation from "@/mycomponents/scan/winScanLocation.vue"
import location from '@/mycomponents/balance/location.vue'
import toLocation from '@/mycomponents/balance/toLocation.vue'
import batch from '@/mycomponents/balance/batch.vue'
import itemCompareQty from '@/mycomponents/item/itemCompareQty.vue'
import config from '@/static/config.js'
import {getRemoveOption, getEditRemoveOption} from '@/common/array.js';
const props = defineProps({
dataContent: {
type: Object,
default: () => ({})
},
settingParam: {
type: Object,
default: () => ({})
},
allowEditQty: {
type: Boolean,
default: false
},
locationAreaTypeList: {
type: Array,
default: () => []
},
isEdit: {
type: Boolean,
default: true
}
});
const emit = defineEmits(['openDetail', 'remove','updateData'])
const option = ref([]);
const title = ref("推荐详情");
const showItem = ref({});
const editItem = ref({});
const detailOptions = ref([]);
const scanOptions = ref([]);
const options = ref([]);
const removeOptions = ref([]);
const editAndRemoveOptions = ref([]);
const collapse1 = ref(null)
const qtyEdit = ref(null)
const winHint = ref(null)
const message = ref(null)
const locatonItem = ref({})
const scanLocationCode = ref(null)
watch(() => props.dataContent, (newName, oldName) => {
if (props.dataContent.subList.length > 0) {
setTimeout(() => {
if (collapse1.value) {
collapse1.value.init();
}
}, 200);
}
}, {immediate: true, deep: true});
onMounted(() => {
removeOptions.value = getRemoveOption();
editAndRemoveOptions.value = getEditRemoveOption();
});
const openDetailCardPopup = () => {
winHint.value.openScanPopup();
};
const swipeClick = (e, item) => {
switch (e.content.text) {
case "详情":
detail(item);
break;
case "编辑":
edit(item);
break;
case "库位":
showLocation(item);
break;
case "移除":
remove(item);
break;
}
};
const edit = (item) => {
editItem.value = item;
qtyEdit.value.openEditPopup(item.balance, item.handleQty);
};
const detail = (item) => {
emit('openDetail', item);
};
const remove = (item) => {
message.value.showQuestionMessage("确定移除扫描信息?", (res) => {
if (res) {
item.scaned = false;
item.balance = {};
item.handleQty = 0;
emit('remove', item);
}
});
};
const confirm = (qty) => {
editItem.value.handleQty = qty;
emit('updateData');
};
const showLocation = (item) => {
locatonItem.value = item;
scanLocationCode.value.openScanPopup();
};
const getLocation = (location, code) => {
locatonItem.value.toLocationCode = code;
emit('updateData');
};
const isDevlement = () => {
return config.isDevelopment;
};
const copy = (detail) => {
const content = `HPQ;V1.0;I${detail.itemCode};P${detail.packingNumber};B${detail.batch};Q${detail.qty}`;
// #ifdef H5
navigator.clipboard.writeText(content).then(() => {
uni.showToast({title: '复制采购标签成功', icon: 'none'});
});
// #endif
// #ifndef H5
uni.setClipboardData({
data: content,
success: () => {
uni.showToast({title: '复制采购标签成功'});
}
});
// #endif
};
</script>
<style>
</style>

261
src/pages/inventoryMove/coms/okToHoldRecordPack.vue

@ -0,0 +1,261 @@
<template>
<view class="">
<u-popup v-model="showOne" mode="bottom" border-radius="14" z-index='12'>
<view class="title">
<view class="title-txt">
需求信息
</view>
<u-icon name="close" color="#4f4f4f" size="28" @click="showOne = false"></u-icon>
</view>
<view class="item">
<view class="label">来源库位</view>
<view class="value">
<u-input v-model="fromLocationCode" @blur="fromLocationScanMsg"></u-input>
<u-icon name="close-circle-fill" color="#acacac" size="36" @click="clickBtnClearFromLocation"></u-icon>
</view>
<view class="searchIcon">
<image src="/static/search.svg" mode="" @click="fromLocationClick"/>
</view>
</view>
<view class="item">
<view class="label">零件</view>
<view class="value">
<u-input v-model="itemCode" @blur="itemCodeScanMsg"></u-input>
<u-icon name="close-circle-fill" color="#acacac" size="36" @click="clickBtnClearItemCode"></u-icon>
</view>
<view class="searchIcon">
<image src="/static/search.svg" mode="" @click="itemCodeClick"/>
</view>
</view>
<view class="item">
<view class="label">批次</view>
<view class="value">
<u-input v-model='batch'></u-input>
<u-icon name="close-circle-fill" color="#acacac" size="36" @click="batch = ''"></u-icon>
</view>
<view class="searchIcon"></view>
</view>
<view class="item">
<view class="label">数量</view>
<view class="value1">
<u-number-box v-model="handleQty" @change="valChange"></u-number-box>
<view class="uom">EA</view>
</view>
</view>
<view class="uni-flex uni-row hide_border">
<button class="btn_edit_big_cancle" hover-class="btn_edit_big_after" @click="showOne = false">取消</button>
<button class="btn_edit_big_confirm" hover-class="btn_edit_big_after" @click="confirm()">确认</button>
</view>
</u-popup>
<!-- <win-scan-location ref="scanLocationCode" title="来源库位" @getLocation='getFromLocation'
:locationAreaTypeList="fromLocationAreaTypeList"></win-scan-location> -->
<comMessage ref="comMessage"></comMessage>
</view>
</template>
<script setup>
import winScanLocation from "@/mycomponents/scan/winScanLocation.vue"
import {
getBusinessType
} from '@/common/record.js';
import {
getLabelInfo
} from '@/common/label.js';
import {ref, onMounted} from 'vue';
const props = defineProps({
showOnePop: {
type: Boolean,
default: false
}
});
const handleQty = ref(0)
const fromLocationCode = ref('')
const itemCode = ref('')
const batch = ref('')
const showOne = ref(false)
//
const boxfocus = ref(false)
const scanMsg = ref('')
const fromWitch = ref('')
const scanList = ref([])
const isShowHistory = ref('')
const headerType = ref('')
const scanLocationCode = ref(null);
const comMessage = ref(null);
const emit = defineEmits(['showFromLocationPopup', 'itemCodeClick', 'confirm', 'getInputMsgResult', 'clickBtnClearFromLocation', 'clickBtnClearItemCode']);
onMounted(() => {
});
const fromLocationClick = () => {
emit('showFromLocationPopup');
};
const itemCodeClick = () => {
if (!fromLocationCode.value) {
comMessage.value.showMessage("请先扫描来源库位");
return;
}
emit('itemCodeClick');
};
const confirm = () => {
const obj = {
fromLocationCode: fromLocationCode.value,
itemCode: itemCode.value,
batch: batch.value,
handleQty: handleQty.value,
};
emit('confirm', obj);
};
const fromLocationScanMsg = () => {
if (fromLocationCode.value) {
scanMsg.value = fromLocationCode.value;
fromWitch.value = 'fromLocationScanMsg';
handelScanMsg();
}
};
const itemCodeScanMsg = () => {
if (itemCode.value) {
if (!fromLocationCode.value) {
comMessage.value.showMessage("请先扫描来源库位");
return;
}
fromWitch.value = 'itemCodeScanMsg';
scanMsg.value = itemCode.value;
handelScanMsg();
}
};
const handelScanMsg = () => {
if (scanMsg.value) {
setTimeout(() => {
losefocus();
let content = uni.$u.trim(scanMsg.value);
if (content === "") {
comMessage.value.showErrorMessage("扫描内容为空,请重新扫描", res => {
if (res) {
scanMsg.value = "";
getfocus();
}
});
return;
}
if (isShowHistory.value) {
scanList.value.unshift(content);
}
getLabelInfo(content, headerType.value, callback => {
let scanResult = callback;
scanResult.scanMessage = content;
if (scanResult.success) {
console.log(scanResult);
emit('getInputMsgResult', scanResult, fromWitch.value);
} else {
losefocus();
comMessage.value.showErrorMessage(scanResult.message, res => {
if (res) {
getfocus();
}
});
}
});
}, 200);
}
};
const losefocus = () => {
boxfocus.value = false;
};
const clickBtnClearFromLocation = () => {
emit('clickBtnClearFromLocation');
};
const clickBtnClearItemCode = () => {
emit('clickBtnClearItemCode');
};
</script>
<style lang="scss">
.title {
padding: 30rpx 20rpx;
display: flex;
border-bottom: 1px solid rgba(230, 230, 230, 1);
.title-txt {
flex: 1;
font-weight: bold;
font-size: 32rpx;
}
}
.select {
display: flex;
}
.border {
border: 1px solid rgba(230, 230, 230, 1)
}
::v-deep .u-input__right-icon__clear {
display: flex;
align-items: center;
justify-content: center;
color: #a7a7a7;
}
.item {
display: flex;
align-items: center;
padding: 20rpx;
border-bottom: 1px solid #dedede;
.value {
flex: 1;
width: 0px;
height: 80rpx;
border: 1px solid #dedede;
display: flex;
align-items: center;
font-size: 32rpx;
padding: 0px 20rpx;
}
.value1 {
flex: 1;
width: 0px;
height: 80rpx;
display: flex;
align-items: center;
font-size: 32rpx;
}
.searchIcon {
width: 40rpx;
margin-left: 20rpx;
image {
width: 40rpx;
height: 40rpx
}
}
.uom {
margin-left: 10rpx;
}
}
</style>

42
src/pages/inventoryMove/job/holdToWipMoveJob.vue

@ -0,0 +1,42 @@
<template>
<view class="page-wraper">
<comMoveJob :title="title" ref="comMoveJob" businessTypeCode='HoldToWip'></comMoveJob>
</view>
</template>
<script lang="ts" setup>
import {ref} from 'vue'
import {onLoad, onShow, onPullDownRefresh, onReachBottom, onNavigationBarButtonTap} from '@dcloudio/uni-app'
import ComMoveJob from '@/pages/inventoryMove/coms/comMoveJob.vue'
const title = ref('')
const comMoveJob = ref('')
onLoad((option) => {
title.value = option.title
})
onShow(()=> {
setTimeout(()=>{
comMoveJob.value.refresh();
},100)
})
onPullDownRefresh(()=> {
if (comMoveJob.value) {
comMoveJob.value.refresh();
}
})
onReachBottom(()=> {
if (comMoveJob.value) {
comMoveJob.value.onReach();
}
})
onNavigationBarButtonTap((e)=> {
if (e.index === 0) {
comMoveJob.value.toHome();
} else if (e.index == 1) {
comMoveJob.value.openFilter();
}
})
</script>
<style>
</style>

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save