扫码枪页面
This commit is contained in:
@@ -51,6 +51,7 @@
|
||||
"js-cookie": "3.0.1",
|
||||
"jsbarcode": "^3.12.1",
|
||||
"jsencrypt": "3.0.0-rc.1",
|
||||
"mqtt": "^5.13.3",
|
||||
"nprogress": "0.2.0",
|
||||
"qrcode": "^1.5.4",
|
||||
"quill": "1.3.7",
|
||||
|
||||
@@ -90,3 +90,19 @@ export function addStockIoWithDetail(data) {
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
export function scanInStock(data) {
|
||||
return request({
|
||||
url: '/wms/stockIo/scanInStock',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
export function scanOutStock(data) {
|
||||
return request({
|
||||
url: '/wms/stockIo/scanOutStock',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ export default {
|
||||
// 拼接条码内容 stockIoId_warehouseId_materialId_quantity
|
||||
const barcodes = details.filter(el => el.recordType == 0).map(item => {
|
||||
return {
|
||||
code: encodeURIComponent(`${item.itemId || ''}`),
|
||||
code: encodeURIComponent(`${item.itemType}__${item.itemId || ''}`),
|
||||
count: Math.min(item.quantity, 10),
|
||||
textTpl: item.itemType == ITEM_TYPE.PRODUCT ?
|
||||
`${this.productMap[item.itemId]?.productName}[${this.productMap[item.itemId]?.productCode}](${item.quantity})`
|
||||
|
||||
@@ -0,0 +1,350 @@
|
||||
<template>
|
||||
<el-row class="container" :gutter="20">
|
||||
<el-col :span="4" class="device-panel">
|
||||
<div class="panel-header">
|
||||
<h3>设备列表</h3>
|
||||
</div>
|
||||
<ul class="device-list">
|
||||
<li v-for="item in deviceList" :key="item.id" class="device-item">
|
||||
<span class="device-id">{{ item.id }}</span>
|
||||
<span class="device-name">{{ item.name }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</el-col>
|
||||
<el-col :span="20" class="main-panel">
|
||||
<div class="form-panel">
|
||||
<el-form :inline="true" class="filter-form">
|
||||
<el-form-item label="库位" class="form-item">
|
||||
<WarehouseSelect v-model="defaultForm.warehouseId" />
|
||||
</el-form-item>
|
||||
<el-form-item label="主码" class="form-item">
|
||||
<el-select v-model="defaultForm.stockIoId" placeholder="请选择主码" clearable class="form-input">
|
||||
<el-option
|
||||
v-for="item in masterList"
|
||||
:key="item.stockIoId"
|
||||
:label="item.stockIoCode"
|
||||
:value="item.stockIoId"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="数量" class="form-item">
|
||||
<el-input v-model="defaultForm.quantity" class="form-input" />
|
||||
</el-form-item>
|
||||
<el-form-item label="记录类型" class="form-item">
|
||||
<el-select v-model="defaultForm.ioType" placeholder="请选择操作类型" clearable class="form-input">
|
||||
<el-option
|
||||
v-for="dict in dict.type.stock_io_type"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="批次号" class="form-item">
|
||||
<el-input v-model="defaultForm.batchNo" class="form-input" />
|
||||
</el-form-item>
|
||||
<el-button type="primary" :disabled="selectedList.length === 0" @click="handleBatchConfirm">批量确认</el-button>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="table-panel">
|
||||
<el-table :data="messageList" style="width: 100%" height="100%" class="message-table" stripe @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column prop="time" label="时间" width="180" align="center" />
|
||||
<el-table-column prop="itemId" label="物料" align="center">
|
||||
<template #default="scope">
|
||||
<ProductInfo v-if="scope.row.itemType === 'product'" :productId="scope.row.itemId" />
|
||||
<RawMaterialInfo v-else :materialId="scope.row.itemId" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="存储位置" align="center">
|
||||
<template #default="scope">
|
||||
<WarehouseSelect v-model="scope.row.warehouseId" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="stockIoId" label="主码" align="center">
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.stockIoId" placeholder="请选择主码" clearable class="table-select">
|
||||
<el-option
|
||||
v-for="item in masterList"
|
||||
:key="item.stockIoId"
|
||||
:label="item.stockIoCode"
|
||||
:value="item.stockIoId"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="quantity" label="数量" align="center">
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.quantity" class="table-input" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="ioType" label="操作类型" align="center">
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.ioType" placeholder="请选择操作类型" clearable class="table-select">
|
||||
<el-option
|
||||
v-for="dict in dict.type.stock_io_type"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="batchNo" label="批次号" align="center">
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.batchNo" class="table-input" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" @click="handleDelete(scope.row)">删除</el-button>
|
||||
<el-button type="primary" @click="handleConfirm(scope.row)">确认</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listStockIo, scanInStock, scanOutStock } from '@/api/wms/stockIo';
|
||||
import { addStockIoDetail } from '@/api/wms/stockIoDetail';
|
||||
import WarehouseSelect from '@/components/WarehouseSelect/index.vue';
|
||||
import ProductInfo from '@/components/KLPService/Renderer/ProductInfo.vue';
|
||||
import RawMaterialInfo from '@/components/KLPService/Renderer/RawMaterialInfo.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
WarehouseSelect,
|
||||
ProductInfo,
|
||||
RawMaterialInfo,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
deviceList: [],
|
||||
messageList: [],
|
||||
socket: null,
|
||||
defaultForm: {
|
||||
ioType: '',
|
||||
stockIoId: '',
|
||||
quantity: 1,
|
||||
warehouseId: '',
|
||||
batchNo: '',
|
||||
},
|
||||
masterList: [],
|
||||
selectedList: [],
|
||||
};
|
||||
},
|
||||
dicts: ['stock_io_type'],
|
||||
mounted() {
|
||||
this.initSocket();
|
||||
this.fetchMaster();
|
||||
},
|
||||
methods: {
|
||||
initSocket() {
|
||||
this.socket = new WebSocket("ws://localhost:9000/ws");
|
||||
this.socket.onopen = () => {
|
||||
console.log("Socket 连接已建立");
|
||||
};
|
||||
this.socket.onmessage = (event) => {
|
||||
const data = JSON.parse(event.data);
|
||||
if (data.type === "deviceList") {
|
||||
console.log(data, '获取设备列表');
|
||||
this.deviceList = data.devices;
|
||||
} else if (data.type === "scanMessage") {
|
||||
console.log(data, '获取消息');
|
||||
this.messageList.push({
|
||||
time: new Date().toLocaleString(),
|
||||
itemId: data.itemId,
|
||||
itemType: data.itemType,
|
||||
stockIoId: this.defaultForm.stockIoId,
|
||||
quantity: this.defaultForm.quantity,
|
||||
ioType: this.defaultForm.ioType,
|
||||
warehouseId: this.defaultForm.warehouseId,
|
||||
batchNo: this.defaultForm.batchNo,
|
||||
unit: '个'
|
||||
});
|
||||
}
|
||||
};
|
||||
this.socket.onclose = () => {
|
||||
console.log("Socket 连接已关闭");
|
||||
};
|
||||
},
|
||||
fetchMaster() {
|
||||
listStockIo({ pageSize: 9999, pageNum: 1 }).then(res => {
|
||||
console.log(res, '获取主码');
|
||||
this.masterList = res.rows;
|
||||
});
|
||||
},
|
||||
handleDeviceChange(item) {
|
||||
this.socket.send(
|
||||
JSON.stringify({
|
||||
type: "toggleDevice",
|
||||
deviceId: item.id,
|
||||
})
|
||||
);
|
||||
},
|
||||
handleBatchConfirm() {
|
||||
// 汇总会导致的库存变更,需要确认
|
||||
console.log(this.selectedList, '批量确认');
|
||||
this.selectedList.forEach(item => {
|
||||
console.log(item, 'item');
|
||||
});
|
||||
},
|
||||
handleSelectionChange(selection) {
|
||||
this.selectedList = selection;
|
||||
},
|
||||
handleDelete(row) {
|
||||
this.messageList = this.messageList.filter(item => item.time !== row.time);
|
||||
},
|
||||
async handleConfirm(row) {
|
||||
// 同时做两件事,插入记录,修改库存
|
||||
// recordType为1表明记录来源扫码枪
|
||||
await this.insertRecord({...row, recordType: 1})
|
||||
await this.updateStock(row)
|
||||
this.handleDelete(row);
|
||||
this.$message.success('确认成功');
|
||||
},
|
||||
insertRecord(row) {
|
||||
return addStockIoDetail(row)
|
||||
},
|
||||
updateStock(row) {
|
||||
if (row.ioType === 'in') {
|
||||
return scanInStock(row)
|
||||
} else {
|
||||
return scanOutStock(row)
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.container {
|
||||
height: calc(100vh - 100px);
|
||||
padding: 20px;
|
||||
background-color: #f5f7fa;
|
||||
}
|
||||
|
||||
.device-panel {
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||||
padding: 0 !important;
|
||||
height: calc(100vh - 40px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.main-panel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: calc(100vh - 40px);
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.panel-header {
|
||||
padding: 15px 20px;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
background-color: #f8fafc;
|
||||
border-radius: 8px 8px 0 0;
|
||||
}
|
||||
|
||||
.panel-header h3 {
|
||||
margin: 0;
|
||||
font-size: 16px;
|
||||
color: #303133;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.device-list {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.device-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 12px 20px;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
.device-item:hover {
|
||||
background-color: #f5f7fa;
|
||||
}
|
||||
|
||||
.device-id {
|
||||
font-weight: 500;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.device-name {
|
||||
color: #909399;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.form-panel {
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||||
padding: 15px 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.filter-form {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.form-item {
|
||||
margin-bottom: 0 !important;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.form-input {
|
||||
width: 180px;
|
||||
}
|
||||
|
||||
.table-panel {
|
||||
flex: 1;
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.message-table {
|
||||
flex: 1;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.table-select {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.table-input {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.el-table::before {
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.el-table th {
|
||||
background-color: #f8fafc !important;
|
||||
color: #606266;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.el-table td, .el-table th {
|
||||
padding: 12px 0;
|
||||
}
|
||||
</style>
|
||||
@@ -74,10 +74,15 @@
|
||||
|
||||
<el-table v-loading="loading" :data="productionLineList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="产线ID" align="center" prop="lineId" v-if="true"/>
|
||||
<el-table-column label="产线编号" align="center" prop="lineCode" />
|
||||
<el-table-column label="产线名称" align="center" prop="lineName" />
|
||||
<el-table-column label="日产能" align="center" prop="capacity" />
|
||||
<el-table-column label="负载任务数/预计耗时" align="center" prop="unit">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.planDetailCount }}</span> /
|
||||
<span>{{ scope.row.totalPlanDays }}天</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="产能单位" align="center" prop="unit" />
|
||||
<el-table-column label="是否启用" align="center" prop="isEnabled">
|
||||
<template slot-scope="scope">
|
||||
|
||||
@@ -92,9 +92,23 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" align="center" prop="status">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="statusTagType(scope.row.status)" disable-transitions>
|
||||
<el-select v-model="scope.row.status" @change="handleStatusChange(scope.row)">
|
||||
<el-option key="1" :value="0" label="新建">
|
||||
<el-tag type="info">新建</el-tag>
|
||||
</el-option>
|
||||
<el-option key="2" :value="1" label="已排产">
|
||||
<el-tag type="warning">已排产</el-tag>
|
||||
</el-option>
|
||||
<el-option key="3" :value="2" label="生产中">
|
||||
<el-tag type="primary">生产中</el-tag>
|
||||
</el-option>
|
||||
<el-option key="4" :value="3" label="已完成">
|
||||
<el-tag type="success">已完成</el-tag>
|
||||
</el-option>
|
||||
</el-select>
|
||||
<!-- <el-tag :type="statusTagType(scope.row.status)" disable-transitions>
|
||||
{{ statusText(scope.row.status) }}
|
||||
</el-tag>
|
||||
</el-tag> -->
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" align="center" prop="remark" />
|
||||
@@ -111,14 +125,12 @@
|
||||
type="text"
|
||||
icon="el-icon-edit"
|
||||
@click="handleUpdate(scope.row)"
|
||||
|
||||
>修改</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-delete"
|
||||
@click="handleDelete(scope.row)"
|
||||
|
||||
>删除</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
@@ -267,6 +279,13 @@
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
handleStatusChange(row) {
|
||||
console.log(row);
|
||||
updateSchedulePlan(row).then(response => {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.getList();
|
||||
});
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
|
||||
Reference in New Issue
Block a user