Browse Source

拆分标签

master
han\hanst 4 weeks ago
parent
commit
c433a4a134
  1. 3
      src/api/inventory/label.js
  2. 6
      src/views/main.vue
  3. 284
      src/views/modules/inventory/label-query.vue

3
src/api/inventory/label.js

@ -4,3 +4,6 @@ export const queryLabelInfo = data => createAPI(`/pda/label/query`,'post',data)
// 取消WMS预留 - rqrq
export const cancelReserve = data => createAPI(`/pda/label/cancelReserve`,'post',data)
// 标签拆分
export const splitLabel = data => createAPI(`/pda/label/split`,'post',data)

6
src/views/main.vue

@ -244,12 +244,6 @@
</div>
<div class="menu-text">盘点</div>
</div>
<div class="menu-item disabled" @click="handleDisabledFeature('handlingunit')">
<div class="menu-icon hu">
<van-icon name="cluster-o" size="24" />
</div>
<div class="menu-text">HU管理</div>
</div>
</div>
</div>

284
src/views/modules/inventory/label-query.vue

@ -110,6 +110,12 @@
<!-- 底部操作按钮 -->
<div v-if="labelInfo" class="bottom-actions">
<button
class="action-btn primary"
@click="showSplitDialog"
>
拆分
</button>
<button
class="action-btn secondary"
@click="clearData"
@ -120,11 +126,66 @@
</div>
</div>
</div>
<!-- 拆分对话框 -->
<el-dialog
title="标签拆分"
:visible.sync="splitDialogVisible"
width="90%"
:close-on-click-modal="false"
:append-to-body="true"
:modal-append-to-body="true"
>
<div class="split-dialog-content">
<div class="split-info-row">
<span class="split-label">原标签编码:</span>
<span class="split-value">{{ labelInfo ? labelInfo.unitId : '' }}</span>
</div>
<div class="split-info-row">
<span class="split-label">当前数量:</span>
<span class="split-value">{{ labelInfo ? labelInfo.qty : 0 }}</span>
</div>
<div class="split-input-group">
<label class="split-label required">拆分数量:</label>
<el-input
v-model="splitQty"
type="number"
placeholder="请输入拆分数量(必须小于100)"
class="split-input"
ref="splitInput"
/>
<div class="split-hint" v-if="splitQty && !isValidSplitQty">
<i class="el-icon-warning"></i>
拆分数量必须大于0且小于当前数量
</div>
</div>
<div class="split-info-row">
<span class="split-label">拆分后原标签剩余:</span>
<span class="split-value split-remain">{{ calculateRemainQty }}</span>
</div>
</div>
<div slot="footer" class="dialog-footer">
<button class="dialog-btn cancel" @click="splitDialogVisible = false">
取消
</button>
<button
class="dialog-btn confirm"
@click="confirmSplit"
:disabled="splitLoading || !isValidSplitQty"
>
{{ splitLoading ? '处理中...' : '确定拆分' }}
</button>
</div>
</el-dialog>
</div>
</template>
<script>
import { queryLabelInfo } from '@/api/inventory/label'
import { queryLabelInfo, splitLabel } from '@/api/inventory/label'
import { printLabelCommon } from '@/api/production/production-inbound.js'
export default {
@ -136,10 +197,41 @@ export default {
labelCode: '',
labelInfo: null,
loading: false,
printLoading: false
printLoading: false,
splitDialogVisible: false,
splitQty: '',
splitLoading: false
};
},
computed: {
/**
* 计算拆分后原标签剩余数量
*/
calculateRemainQty() {
if (!this.labelInfo || !this.splitQty) {
return this.labelInfo ? this.labelInfo.qty : 0;
}
const currentQty = parseFloat(this.labelInfo.qty) || 0;
const split = parseFloat(this.splitQty) || 0;
const remain = currentQty - split;
return remain >= 0 ? remain : 0;
},
/**
* 验证拆分数量是否有效
*/
isValidSplitQty() {
if (!this.splitQty || !this.labelInfo) {
return false;
}
const split = parseFloat(this.splitQty);
const current = parseFloat(this.labelInfo.qty) || 0;
return split > 0 && split < current;
}
},
methods: {
/**
* 返回上一页
@ -281,6 +373,94 @@ export default {
} finally {
this.printLoading = false;
}
},
/**
* 显示拆分对话框
*/
showSplitDialog() {
if (!this.labelInfo) {
this.$message.error('没有可拆分的标签');
return;
}
this.splitQty = '';
this.splitDialogVisible = true;
//
this.$nextTick(() => {
if (this.$refs.splitInput) {
this.$refs.splitInput.focus();
}
});
},
/**
* 确认拆分
*/
async confirmSplit() {
//
if (!this.splitQty) {
this.$message.error('请输入拆分数量');
return;
}
const splitQty = parseFloat(this.splitQty);
const currentQty = parseFloat(this.labelInfo.qty);
if (splitQty <= 0) {
this.$message.error('拆分数量必须大于0');
return;
}
if (splitQty >= currentQty) {
this.$message.error('拆分数量必须小于当前数量');
return;
}
this.splitLoading = true;
try {
const { data } = await splitLabel({
site: this.site,
unitId: this.labelInfo.unitId,
splitQty: splitQty,
operatorName: localStorage.getItem('userName')
});
if (data && data.code === 0) {
const result = data.data;
this.$message.success('拆分成功!');
//
this.splitDialogVisible = false;
//
let printLabelType;
if (this.labelInfo.partNo && this.labelInfo.partNo.startsWith("80")) {
printLabelType = '库存成品标签';
} else {
printLabelType = 'BIL标签';
}
//
console.log('打印标签:', [result.originalUnitId, result.newUnitId]);
await this.printViaServer([result.originalUnitId, result.newUnitId], printLabelType);
//
this.labelCode = this.labelInfo.unitId;
this.handleLabelScan();
} else {
this.$message.error(data.msg || '拆分失败');
}
} catch (error) {
console.error('拆分标签失败:', error);
this.$message.error('拆分异常: ' + (error.message || error));
} finally {
this.splitLoading = false;
}
}
},
@ -500,6 +680,106 @@ export default {
background: #e8e8e8;
}
/* 拆分对话框样式 */
.split-dialog-content {
padding: 16px 0;
}
.split-info-row {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 0;
border-bottom: 1px solid #f0f0f0;
}
.split-label {
font-size: 14px;
color: #666;
font-weight: 500;
}
.split-value {
font-size: 15px;
font-weight: 600;
color: #333;
}
.split-value.split-remain {
color: #17B3A3;
font-size: 16px;
}
.split-input-group {
margin: 20px 0;
}
.split-input-group .split-label {
display: block;
margin-bottom: 8px;
}
.split-input {
width: 100%;
}
/* 对话框底部按钮 */
.dialog-footer {
display: flex;
gap: 12px;
padding-top: 16px;
}
.dialog-btn {
flex: 1;
padding: 12px 24px;
border: none;
border-radius: 6px;
font-size: 16px;
font-weight: 500;
cursor: pointer;
transition: all 0.2s;
min-height: 44px;
}
.dialog-btn.confirm {
background: #17B3A3;
color: white;
}
.dialog-btn.confirm:hover:not(:disabled) {
background: #15a394;
}
.dialog-btn.confirm:disabled {
background: #ccc;
cursor: not-allowed;
opacity: 0.6;
}
.dialog-btn.cancel {
background: #f5f5f5;
color: #333;
border: 1px solid #ddd;
}
.dialog-btn.cancel:hover {
background: #e8e8e8;
}
/* 强制对话框显示在最上层 */
::v-deep .el-dialog__wrapper {
z-index: 9999 !important;
}
::v-deep .el-dialog {
z-index: 10000 !important;
}
::v-deep .v-modal {
z-index: 9998 !important;
}
/* 响应式设计 */
@media screen and (max-width: 480px) {
.header-bar {

Loading…
Cancel
Save