Browse Source

2025-11-25

实时库存管理属性变动修改
master
fengyuan_yang 2 months ago
parent
commit
5bf4390f7e
  1. 536
      src/views/modules/print/rePrintPoPart.vue

536
src/views/modules/print/rePrintPoPart.vue

@ -28,11 +28,11 @@
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-form-item label="批次号"> <el-form-item label="批次号">
<el-input v-model="searchData.batchNo" clearable style="width: 100px">
<el-input v-model="searchData.batchNo" clearable style="width: 80px">
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-form-item label="状态"> <el-form-item label="状态">
<el-select v-model="searchData.statusList" style="width: 200px" multiple collapse-tags clearable placeholder="请选择状态">
<el-select v-model="searchData.statusList" style="width: 150px" multiple collapse-tags clearable placeholder="请选择状态">
<el-option label="待检" value="待检"></el-option> <el-option label="待检" value="待检"></el-option>
<el-option label="待入" value="待入"></el-option> <el-option label="待入" value="待入"></el-option>
<el-option label="在库" value="在库"></el-option> <el-option label="在库" value="在库"></el-option>
@ -254,7 +254,132 @@
</div> </div>
</el-dialog> </el-dialog>
<!-- 属性变动对话框 -->
<!-- 扫描标签对话框新增 -->
<el-dialog
:close-on-click-modal="false"
v-drag
top="10vh"
:visible.sync="scanLabelDialogVisible"
width="1100px"
class="scan-label-dialog">
<div slot="title" class="dialog-title-custom">
<i class="el-icon-edit-outline"></i>
<span>属性变动</span>
</div>
<div class="scan-label-content">
<!-- 扫描输入区域 -->
<div class="scan-input-section">
<div class="input-wrapper">
<label class="input-label">标签条码</label>
<el-input
ref="scanInput"
v-model="scanLabelNo"
@keyup.enter.native="handleScanLabel"
clearable
placeholder="请扫描标签条码"
prefix-icon="el-icon-barcode"
class="scan-input">
</el-input>
</div>
<div class="mode-switch-wrapper">
<el-switch
v-model="isRemoveMode"
active-color="#ff4949"
inactive-color="#67C23A"
class="mode-switch">
</el-switch>
<span class="mode-text" :class="{ 'remove-mode': isRemoveMode }">
{{ isRemoveMode ? '移除' : '添加' }}
</span>
</div>
<div class="info-badges">
<div class="badge-item">
<i class="el-icon-document"></i>
<span class="badge-label">标签张数</span>
<span class="badge-value">{{ scannedLabelList.length }}</span>
</div>
<div class="badge-item">
<i class="el-icon-box"></i>
<span class="badge-label">物料总数</span>
<span class="badge-value">{{ totalScannedQty }}</span>
</div>
</div>
</div>
<!-- 扫描的标签列表 -->
<div class="table-wrapper">
<el-table
:data="scannedLabelList"
height="420"
stripe
class="scan-table">
<el-table-column
type="index"
label="NO."
width="60"
align="center">
</el-table-column>
<el-table-column
prop="rollNo"
label="标签条码"
header-align="center"
align="left"
min-width="120"
show-overflow-tooltip>
</el-table-column>
<el-table-column
prop="qtyOnHand"
label="标签数量"
header-align="center"
align="right"
width="100">
</el-table-column>
<el-table-column
prop="partNo"
label="物料编码"
header-align="center"
align="left"
min-width="130"
show-overflow-tooltip>
</el-table-column>
<el-table-column
prop="partDescription"
label="物料名称"
header-align="center"
align="left"
min-width="200"
show-overflow-tooltip>
</el-table-column>
<el-table-column
prop="parentRollNo"
label="上机标签号"
header-align="center"
align="left"
min-width="120"
show-overflow-tooltip>
</el-table-column>
</el-table>
</div>
</div>
<div slot="footer" class="dialog-footer-custom">
<el-button
type="success"
@click="confirmScanLabels()"
:disabled="scannedLabelList.length === 0"
icon="el-icon-check">
保存
</el-button>
<el-button @click="closeScanLabelDialog()" icon="el-icon-close">
取消
</el-button>
</div>
</el-dialog>
<!-- 属性变动对话框原有的 -->
<el-dialog title="属性变动" :close-on-click-modal="false" v-drag :visible.sync="attributeChangeDialogVisible" width="450px"> <el-dialog title="属性变动" :close-on-click-modal="false" v-drag :visible.sync="attributeChangeDialogVisible" width="450px">
<el-form :model="attributeChangeForm" label-position="top" style="margin-top: -5px;"> <el-form :model="attributeChangeForm" label-position="top" style="margin-top: -5px;">
<el-row :gutter="20"> <el-row :gutter="20">
@ -724,6 +849,11 @@ export default {
dataList: [], dataList: [],
addModelFlag: false, addModelFlag: false,
dataListLoading: false, dataListLoading: false,
//
scanLabelDialogVisible: false,
scanLabelNo: '',
scannedLabelList: [],
isRemoveMode: false, //
// //
attributeChangeDialogVisible: false, attributeChangeDialogVisible: false,
attributeChangeForm: { attributeChangeForm: {
@ -746,6 +876,14 @@ export default {
}, },
components: { components: {
},
computed: {
//
totalScannedQty() {
return this.scannedLabelList.reduce((sum, item) => {
return sum + (parseFloat(item.qtyOnHand) || 0);
}, 0);
}
}, },
mounted() { mounted() {
this.$nextTick(() => { this.$nextTick(() => {
@ -999,20 +1137,139 @@ export default {
kuCunLabelPrint(this.selectionDataList,"A") kuCunLabelPrint(this.selectionDataList,"A")
}, },
//
//
openAttributeChangeDialog() { openAttributeChangeDialog() {
if(this.selectionDataList.length === 0){
this.$message.warning('请先勾选要变动属性的标签!');
return false;
//
this.scannedLabelList = JSON.parse(JSON.stringify(this.selectionDataList));
this.scanLabelNo = '';
this.isRemoveMode = false; //
//
this.scanLabelDialogVisible = true;
//
this.$nextTick(() => {
if (this.$refs.scanInput) {
this.$refs.scanInput.focus();
}
});
},
//
async handleScanLabel() {
if (!this.scanLabelNo || this.scanLabelNo.trim() === '') {
this.$message.warning('请输入或扫描标签条码!');
return;
}
const rollNo = this.scanLabelNo.trim();
if (this.isRemoveMode) {
//
this.removeLabelByCode(rollNo);
} else {
//
this.addLabelByCode(rollNo);
} }
//
},
//
async addLabelByCode(rollNo) {
//
const existingIndex = this.scannedLabelList.findIndex(item => item.rollNo === rollNo);
if (existingIndex !== -1) {
this.$message.warning(`标签 ${rollNo} 已存在列表中`);
this.scanLabelNo = '';
this.$nextTick(() => {
if (this.$refs.scanInput) {
this.$refs.scanInput.focus();
}
});
return;
}
try {
// 使SQL
const params = {
userName: this.$store.state.user.name,
rollNo: rollNo,
page: 1,
limit: 1
};
const {data} = await getKuCunLabelData(params);
if (data && data.code === 0 && data.page && data.page.list && data.page.list.length > 0) {
const labelData = data.page.list[0];
//
this.scannedLabelList.unshift(labelData);
this.$message.success(`标签 ${rollNo} 添加成功`);
} else {
this.$message.error(`未找到标签 ${rollNo}`);
}
} catch (error) {
this.$message.error(`查询标签失败: ${error.message || error}`);
}
//
this.scanLabelNo = '';
this.$nextTick(() => {
if (this.$refs.scanInput) {
this.$refs.scanInput.focus();
}
});
},
//
removeLabelByCode(rollNo) {
const existingIndex = this.scannedLabelList.findIndex(item => item.rollNo === rollNo);
if (existingIndex === -1) {
this.$message.warning(`未找到标签 ${rollNo}`);
} else {
this.scannedLabelList.splice(existingIndex, 1);
this.$message.success(`标签 ${rollNo} 已移除`);
}
//
this.scanLabelNo = '';
this.$nextTick(() => {
if (this.$refs.scanInput) {
this.$refs.scanInput.focus();
}
});
},
//
confirmScanLabels() {
if (this.scannedLabelList.length === 0) {
this.$message.warning('请至少扫描一个标签!');
return;
}
//
this.scanLabelDialogVisible = false;
// selectionDataList
this.selectionDataList = JSON.parse(JSON.stringify(this.scannedLabelList));
//
this.attributeChangeForm = { this.attributeChangeForm = {
batchNo: '', batchNo: '',
remark: '' remark: ''
}; };
//
this.attributeChangeDialogVisible = true; this.attributeChangeDialogVisible = true;
}, },
//
closeScanLabelDialog() {
this.scanLabelDialogVisible = false;
this.scanLabelNo = '';
},
// //
async saveAttributeChange() { async saveAttributeChange() {
// //
@ -1247,4 +1504,267 @@ export default {
border-color: #409EFF; border-color: #409EFF;
box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.1); box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.1);
} }
/* 扫描标签对话框样式 - 简约高端 */
.scan-label-dialog {
/deep/ .el-dialog {
border-radius: 8px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12);
}
/deep/ .el-dialog__header {
padding: 0;
border-bottom: 1px solid #e8e8e8;
}
/deep/ .el-dialog__body {
padding: 0;
}
/deep/ .el-dialog__footer {
padding: 16px 24px;
border-top: 1px solid #e8e8e8;
background-color: #fafafa;
}
.dialog-title-custom {
padding: 20px 24px;
font-size: 18px;
font-weight: 600;
color: #303133;
display: flex;
align-items: center;
i {
font-size: 20px;
margin-right: 10px;
color: #409EFF;
}
}
.scan-label-content {
padding: 24px;
.scan-input-section {
display: flex;
align-items: flex-end;
gap: 20px;
margin-bottom: 20px;
padding-bottom: 20px;
border-bottom: 1px solid #f0f0f0;
.input-wrapper {
flex: 1;
.input-label {
display: block;
font-size: 14px;
color: #606266;
margin-bottom: 2px;
font-weight: 500;
}
.scan-input {
/deep/ .el-input__inner {
height: 42px;
line-height: 42px;
font-size: 14px;
border-radius: 4px;
border: 1px solid #dcdfe6;
transition: all 0.3s;
&:focus {
border-color: #409EFF;
box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.1);
}
}
/deep/ .el-input__prefix {
left: 10px;
font-size: 16px;
color: #909399;
}
}
}
.mode-switch-wrapper {
display: flex;
align-items: center;
gap: 10px;
padding: 0 16px;
height: 42px;
//background: #f5f7fa;
border-radius: 4px;
//.mode-switch {
// /deep/ .el-switch__core {
// width: 44px !important;
// height: 22px;
// border-radius: 11px;
//
// &::after {
// width: 18px;
// height: 18px;
// top: 1px;
// left: 1px;
// }
// }
//
// /deep/ .el-switch.is-checked .el-switch__core::after {
// left: calc(100% - 2px);
// margin-left: -18px;
// }
//}
.mode-text {
font-size: 14px;
font-weight: 600;
color: #67C23A;
transition: color 0.3s;
min-width: 40px;
&.remove-mode {
color: #ff4949;
}
}
}
.info-badges {
display: flex;
gap: 16px;
.badge-item {
display: flex;
align-items: center;
gap: 8px;
padding: 10px 16px;
background: linear-gradient(135deg, #f5f7fa 0%, #e8eaf0 100%);
border-radius: 4px;
border: 1px solid #e4e7ed;
i {
font-size: 18px;
color: #409EFF;
}
.badge-label {
font-size: 13px;
color: #909399;
}
.badge-value {
font-size: 18px;
font-weight: 700;
color: #303133;
min-width: 32px;
text-align: right;
}
}
}
}
.table-wrapper {
position: relative;
.scan-table {
/deep/ .el-table__header-wrapper {
th {
background-color: #f5f7fa;
color: #606266;
font-weight: 600;
font-size: 13px;
padding: 12px 0;
}
}
/deep/ .el-table__body-wrapper {
.el-table__row {
transition: background-color 0.2s;
&:hover {
background-color: #f5f7fa;
}
td {
padding: 10px 0;
font-size: 13px;
}
}
}
/deep/ .el-table--striped .el-table__body tr.el-table__row--striped td {
background-color: #fafafa;
}
}
.empty-state {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
color: #909399;
i {
font-size: 64px;
color: #dcdfe6;
margin-bottom: 16px;
}
p {
font-size: 14px;
margin: 0;
}
}
}
}
.dialog-footer-custom {
display: flex;
justify-content: center;
gap: 12px;
.el-button {
min-width: 100px;
height: 38px;
font-size: 14px;
border-radius: 4px;
transition: all 0.3s;
&.el-button--success {
background: #67C23A;
border-color: #67C23A;
&:hover {
background: #85ce61;
border-color: #85ce61;
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(103, 194, 58, 0.3);
}
&:active {
transform: translateY(0);
}
&.is-disabled {
background: #b3d8a1;
border-color: #b3d8a1;
transform: none;
box-shadow: none;
}
}
&:not(.el-button--success) {
&:hover {
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
&:active {
transform: translateY(0);
}
}
}
}
}
</style> </style>
Loading…
Cancel
Save