feat: 优化手动进仓扫码流程并升至1.1.22

This commit is contained in:
2026-11-08 22:38:49 +08:00
parent 5b6690b4d8
commit 4d3f767e16
7 changed files with 216 additions and 139 deletions
@@ -48,7 +48,6 @@
:delete-mode="BarCodeDelStatus"
:message="BillDataMessage"
disabled-tip="请先提交保存后再扫码"
:show-phone-scan="usePhoneScanFallback"
@input="QRBarCode = $event"
@scan="handleScan"
@phone-scan="handlePhoneScan"
@@ -41,7 +41,6 @@
:value="QRBarCode"
:delete-mode="BarCodeDelStatus"
:message="BillDataMessage"
:show-phone-scan="usePhoneScanFallback"
@input="QRBarCode = $event"
@scan="handleScan"
@phone-scan="handlePhoneScan"
+146 -103
View File
@@ -9,39 +9,15 @@
</template>
</common-navbar>
<view class="manual-in__scan">
<input
class="manual-in__scan-input"
type="text"
confirm-type="done"
:focus="scanFocus"
v-model="scanCode"
placeholder="请点击扫描/输入布票编码"
placeholder-class="manual-in__placeholder"
@confirm="onScanConfirm"
/>
</view>
<view class="manual-in__panel">
<view class="manual-in__row">
<text class="manual-in__label">布票编码</text>
<text class="manual-in__value">{{ detail.fabric_piece_code || '-' }}</text>
</view>
<view class="manual-in__row">
<text class="manual-in__label">生产单号</text>
<text class="manual-in__value">{{ detail.production_order_no || '-' }}</text>
</view>
<view class="manual-in__row">
<text class="manual-in__label">机台</text>
<text class="manual-in__value">{{ detail.machine_number || '-' }}</text>
</view>
<view class="manual-in__row">
<text class="manual-in__label">布种名称</text>
<text class="manual-in__value">{{ detail.grey_fabric_name || '-' }}</text>
</view>
<view class="manual-in__row">
<text class="manual-in__label">坯布编号</text>
<text class="manual-in__value">{{ detail.grey_fabric_code || '-' }}</text>
<view class="manual-in__row manual-in__row--input" @click="openInspectorPicker">
<text class="manual-in__label">查布工</text>
<view class="manual-in__right">
<text :class="detail.inspector_name ? 'manual-in__field-text' : 'manual-in__placeholder'">
{{ detail.inspector_name || '请选择查布工' }}
</text>
<text class="manual-in__action" @click.stop="clearInspector">取消</text>
</view>
</view>
<view class="manual-in__row manual-in__row--input">
<text class="manual-in__label">重量</text>
@@ -66,15 +42,6 @@
<text class="manual-in__action" @click.stop="clearLevel">取消</text>
</view>
</view>
<view class="manual-in__row manual-in__row--input" @click="openInspectorPicker">
<text class="manual-in__label">查布工</text>
<view class="manual-in__right">
<text :class="detail.inspector_name ? 'manual-in__field-text' : 'manual-in__placeholder'">
{{ detail.inspector_name || '请选择查布工' }}
</text>
<text class="manual-in__action" @click.stop="clearInspector">取消</text>
</view>
</view>
<view class="manual-in__row manual-in__row--input">
<text class="manual-in__label">存放仓位</text>
<view class="manual-in__right">
@@ -88,22 +55,62 @@
<text class="manual-in__action" @click="editWarehouseBin">修改</text>
</view>
</view>
</view>
<view class="manual-in__scan">
<input
class="manual-in__scan-input"
type="text"
confirm-type="done"
:confirm-hold="true"
:focus="scanFocus"
v-model="scanCode"
placeholder="先选查布工并填写信息,再扫描布票编码"
placeholder-class="manual-in__placeholder"
@confirm="onScanConfirm"
/>
<view
v-if="scanCode"
class="manual-in__scan-icon"
@click.stop="clearScanCode"
>
<u-icon name="close-circle-fill" size="44" color="#bfbfbf" />
</view>
<view
class="manual-in__scan-icon"
@click.stop="handlePhoneScan"
>
<u-icon name="scan" size="44" color="#595959" />
</view>
</view>
<view class="manual-in__panel">
<view class="manual-in__row">
<text class="manual-in__label">布票编码</text>
<text class="manual-in__value">{{ detail.fabric_piece_code || '-' }}</text>
</view>
<view class="manual-in__row">
<text class="manual-in__label">生产单号</text>
<text class="manual-in__value">{{ detail.production_order_no || '-' }}</text>
</view>
<view class="manual-in__row">
<text class="manual-in__label">机台</text>
<text class="manual-in__value">{{ detail.machine_number || '-' }}</text>
</view>
<view class="manual-in__row">
<text class="manual-in__label">布种名称</text>
<text class="manual-in__value">{{ detail.grey_fabric_name || '-' }}</text>
</view>
<view class="manual-in__row">
<text class="manual-in__label">坯布编号</text>
<text class="manual-in__value">{{ detail.grey_fabric_code || '-' }}</text>
</view>
<view class="manual-in__row" v-if="detail.volume_number != null && detail.volume_number !== ''">
<text class="manual-in__label">卷号</text>
<text class="manual-in__value">{{ detail.volume_number }}</text>
</view>
</view>
<view class="manual-in__footer">
<u-button
type="primary"
shape="circle"
:loading="submitting"
:disabled="submitting || loadingDetail"
@click="submitInWarehouse"
>确定进仓</u-button>
</view>
<SearchSelectPopup
:show.sync="levelPickerShow"
title="选择等级"
@@ -217,12 +224,19 @@ export default {
this.loadInspectorOptions();
},
onShow() {
this.scanFocus = false;
this.$nextTick(() => {
this.scanFocus = true;
});
this.refocusScanInput(50);
},
onUnload() {
clearTimeout(this._scanFocusTimer);
},
methods: {
refocusScanInput(delay = 120) {
clearTimeout(this._scanFocusTimer);
this.scanFocus = false;
this._scanFocusTimer = setTimeout(() => {
this.scanFocus = true;
}, delay);
},
navToSetting() {
uni.navigateTo({ url: '/pages/sys/user/scan-settings' });
},
@@ -330,6 +344,22 @@ export default {
if (!code) return;
this.fetchScanDetail(code);
},
clearScanCode() {
this.scanCode = '';
this.refocusScanInput();
},
handlePhoneScan() {
const err = this.validateBeforeScan();
if (err) {
this.$u.toast(err);
return;
}
this.openPhoneScan({
callback: (scanResult) => {
this.handleScanCode(scanResult);
},
});
},
onScanConfirm() {
const code = String(this.scanCode || '').trim();
if (!code) {
@@ -338,33 +368,60 @@ export default {
}
this.fetchScanDetail(code);
},
validateBeforeScan() {
const inspectorName = String(this.detail.inspector_name || '').trim();
if (!inspectorName && (this.detail.inspector_id == null || this.detail.inspector_id === '')) {
return '请先选择查布工';
}
if (toWeightInt(this.weightKg) == null) {
return '请先输入有效重量';
}
return '';
},
async fetchScanDetail(code) {
if (this.loadingDetail) return;
if (this.loadingDetail || this.submitting) return;
const err = this.validateBeforeScan();
if (err) {
this.$u.toast(err);
return;
}
this.loadingDetail = true;
this.scanCode = code;
let detailOk = false;
try {
const res = await this.$u.api.productionScheduleOrder.getScanFineCodeDetail({
fabric_piece_code: code,
});
this.applyScanDetail(res, code);
detailOk = true;
} catch (error) {
console.log('扫码获取细码失败', error);
const kept = this.keepFormFields();
this.detail = {
...emptyDetail(),
fabric_piece_code: code,
inspector_id: this.detail.inspector_id,
inspector_name: this.detail.inspector_name,
...kept,
};
this.weightKg = '';
this.scanCode = '';
this.refocusScanInput(200);
} finally {
this.loadingDetail = false;
}
if (detailOk) {
await this.submitInWarehouse();
}
},
keepFormFields() {
return {
grey_fabric_level_id: normalizeLevelIds(this.detail.grey_fabric_level_id),
grey_fabric_level_name: this.detail.grey_fabric_level_name || '',
inspector_id: this.detail.inspector_id,
inspector_name: this.detail.inspector_name || '',
};
},
applyScanDetail(res, fallbackCode) {
const data = res || {};
const levelIds = normalizeLevelIds(data.grey_fabric_level_id);
const hasIncomingInspector = data.inspector_id != null && data.inspector_id !== ''
|| String(data.inspector_name || '').trim();
const kept = this.keepFormFields();
this.detail = {
...emptyDetail(),
fabric_piece_code: data.fabric_piece_code || fallbackCode || '',
@@ -372,21 +429,11 @@ export default {
machine_number: data.machine_number || '',
grey_fabric_name: data.grey_fabric_name || '',
grey_fabric_code: data.grey_fabric_code || '',
inspection_weight: formatDisplayWeightKg(data.inspection_weight) ? data.inspection_weight : null,
grey_fabric_level_id: levelIds,
grey_fabric_level_name: Array.isArray(data.grey_fabric_level_name)
? data.grey_fabric_level_name.filter(Boolean).join('、')
: (data.grey_fabric_level_name || ''),
inspector_id: hasIncomingInspector && data.inspector_id != null && data.inspector_id !== ''
? data.inspector_id
: this.detail.inspector_id,
inspector_name: hasIncomingInspector
? (data.inspector_name || this.detail.inspector_name || '')
: (this.detail.inspector_name || ''),
inspection_weight: toWeightInt(this.weightKg),
volume_number: data.volume_number != null && data.volume_number !== '' ? data.volume_number : null,
...kept,
};
this.weightKg = formatDisplayWeightKg(data.inspection_weight);
this.scanCode = this.detail.fabric_piece_code;
util.playSpeak('扫码成功');
},
async submitInWarehouse() {
const fabricPieceCode = String(this.detail.fabric_piece_code || this.scanCode || '').trim();
@@ -440,26 +487,21 @@ export default {
this.resetForNextScan();
} catch (error) {
console.log('手动进仓失败', error);
this.scanCode = '';
this.refocusScanInput(200);
} finally {
this.submitting = false;
}
},
resetForNextScan() {
const inspectorId = this.detail.inspector_id;
const inspectorName = this.detail.inspector_name;
const kept = this.keepFormFields();
this.scanCode = '';
this.detail = {
...emptyDetail(),
inspector_id: inspectorId,
inspector_name: inspectorName,
...kept,
};
this.weightKg = '';
this.$nextTick(() => {
this.scanFocus = false;
this.$nextTick(() => {
this.scanFocus = true;
});
});
// toast 会抢焦点,稍后再聚焦,方便连续扫码
this.refocusScanInput(600);
},
},
};
@@ -471,7 +513,7 @@ export default {
.manual-in {
min-height: 100vh;
background: #f5f6f8;
padding-bottom: 180rpx;
padding-bottom: 40rpx;
box-sizing: border-box;
}
@@ -487,14 +529,31 @@ export default {
margin: 16rpx 0;
padding: 0 28rpx;
background: #fff;
display: flex;
align-items: center;
gap: 12rpx;
}
.manual-in__scan-input {
flex: 1;
min-width: 0;
height: $pda-scan-input-height;
font-size: $pda-font-body;
color: #202328;
}
.manual-in__scan-icon {
display: flex;
align-items: center;
justify-content: center;
width: 72rpx;
height: 72rpx;
flex-shrink: 0;
border-radius: 8rpx;
border: 1rpx solid #d9d9d9;
background: #f7f7f7;
}
.manual-in__placeholder {
color: #b0b4bb;
font-size: $pda-font-placeholder;
@@ -569,20 +628,4 @@ export default {
color: #2f78e6;
flex-shrink: 0;
}
.manual-in__footer {
position: fixed;
left: 0;
right: 0;
bottom: 0;
padding: 24rpx 40rpx calc(24rpx + env(safe-area-inset-bottom));
background: #fff;
box-shadow: 0 -4rpx 16rpx rgba(0, 0, 0, 0.04);
}
::v-deep .manual-in__footer .u-btn {
height: $pda-button-height !important;
line-height: $pda-button-height !important;
font-size: $pda-font-button !important;
}
</style>