徐州宝开四向车

This commit is contained in:
杨学谦 2025-07-23 17:30:14 +08:00
commit 5ece196d28
252 changed files with 52027 additions and 0 deletions

23
wms_client/.gitignore vendored Normal file
View File

@ -0,0 +1,23 @@
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

24
wms_client/README.md Normal file
View File

@ -0,0 +1,24 @@
# helloworld
## Project setup
```
npm install
```
### Compiles and hot-reloads for development
```
npm run serve
```
### Compiles and minifies for production
```
npm run build
```
### Lints and fixes files
```
npm run lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).

BIN
wms_client/WMS-1.0.jar Normal file

Binary file not shown.

View File

@ -0,0 +1,5 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}

19
wms_client/jsconfig.json Normal file
View File

@ -0,0 +1,19 @@
{
"compilerOptions": {
"target": "es5",
"module": "esnext",
"baseUrl": "./",
"moduleResolution": "node",
"paths": {
"@/*": [
"src/*"
]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
}
}

23809
wms_client/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

59
wms_client/package.json Normal file
View File

@ -0,0 +1,59 @@
{
"name": "WMS",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"@element-plus/icons-vue": "^2.3.1",
"axios": "^1.3.3",
"core-js": "^3.8.3",
"element-plus": "^2.4.0",
"file-saver": "^2.0.5",
"moment": "^2.29.4",
"node-polyfill-webpack-plugin": "^2.0.1",
"qrcode": "^1.5.3",
"qrcode.vue": "^3.4.1",
"stream-http": "^3.2.0",
"vue": "^3.2.13",
"vue-print-nb": "^1.7.5",
"vue-router": "^4.0.3",
"vue3-print-nb": "^0.1.4",
"vuex": "^4.0.0",
"xlsx": "^0.18.5"
},
"devDependencies": {
"@babel/core": "^7.12.16",
"@babel/eslint-parser": "^7.12.16",
"@vue/cli-plugin-babel": "~5.0.0",
"@vue/cli-plugin-router": "~5.0.0",
"@vue/cli-plugin-vuex": "~5.0.0",
"@vue/cli-service": "~5.0.0",
"node-sass": "^8.0.0",
"sass-loader": "^13.2.0"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/vue3-essential"
],
"parserOptions": {
"parser": "@babel/eslint-parser"
},
"rules": {
"no-unused-vars": "off"
}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead",
"not ie 11"
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -0,0 +1,37 @@
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
<script>
let timeout; // 定义一个变量存储定时器
function resetTimer() {
clearTimeout(timeout); // 清除之前的定时器
// 设置一个新的定时器,用户空闲时刷新
timeout = setTimeout(() => {
location.reload(); // 刷新当前页面
}, 300000); // 10 分钟
}
// 监听用户活动事件
window.onload = function() {
resetTimer(); // 页面加载时重置定时器
window.addEventListener('mousemove', resetTimer);
window.addEventListener('keypress', resetTimer);
window.addEventListener('scroll', resetTimer);
window.addEventListener('click', resetTimer);
};
</script>
</body>
</html>

55
wms_client/src/App.vue Normal file
View File

@ -0,0 +1,55 @@
<template>
<router-view></router-view>
</template>
<script>
export default {
created() {
//sessionStorage
if (sessionStorage.getItem('storeState')) {
//replaceStatestore
this.$store.replaceState(Object.assign({}, this.$store.state, JSON.parse(sessionStorage.getItem('storeState'))))
}
//vuexsessionStorage
window.addEventListener('beforeunload', () => {
sessionStorage.setItem('storeState', JSON.stringify(this.$store.state))
})
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
height: 100%;
width: 100%;
}
nav {
padding: 30px;
}
nav a {
font-weight: bold;
color: #2c3e50;
}
nav a.router-link-exact-active {
color: #42b983;
}
html {
height: 100%;
width: 100%;
}
body {
margin: 0px;
height: 100%;
width: 100%;
}
</style>

View File

@ -0,0 +1,39 @@
import request from "@/http/request";
const getConfigs = () => {
return request.get('/config/getConfigs')
}
const updateConfig = (params) => {
return request.post('/config/updateConfig', params)
}
const queryBoxConfig = (params) => {
return request.post('/config/queryBoxConfig', params)
}
const queryBoxConfigByPage = (params) => {
return request.post('/config/queryBoxConfigByPage', params)
}
const updateBoxConfig = (params) => {
return request.post('/config/updateBoxConfig', params)
}
const addBoxConfig = (params) => {
return request.post('/config/addBoxConfig', params)
}
const deleteBoxConfig = (params) => {
return request.post('/config/deleteBoxConfig', params)
}
export {
getConfigs,
updateConfig,
queryBoxConfig,
queryBoxConfigByPage,
updateBoxConfig,
addBoxConfig,
deleteBoxConfig
}

183
wms_client/src/api/excel.js Normal file
View File

@ -0,0 +1,183 @@
import request from "@/http/request";
const downlocadExcel = () => {
return request.get('/test/testExcelExport', {
responseType: 'blob'
})
}
const uploadExcel = (formData) => {
return request({
url: '/test/testExcelImport',
method: 'post',
data: formData,
timeout: 100000
})
}
const uploadExcelPeijian = (data) => {
return request({
url: '/excel/uploadExcelPeijian',
method: 'post',
data: data,
timeout: 100000
})
}
const uploadExcelHejian = (data) => {
return request({
url: '/excel/uploadExcelHejian',
method: 'post',
data: data,
timeout: 100000
})
}
const uploadExcelJinji = (data) => {
return request({
url: '/excel/uploadExcelJinji',
method: 'post',
data: data,
timeout: 100000
})
}
const uploadExcelKatePackage = (data) => {
return request({
url: '/excel/uploadExcelKatePackage',
method: 'post',
data: data,
timeout: 100000
})
}
const uploadExcelParts = (data) => {
return request({
url: '/excel/uploadPartInfos',
method: 'post',
data: data,
timeout: 100000
})
}
const uploadBoxConfig = (data) => {
return request({
url: '/excel/uploadBoxConfig',
method: 'post',
data: data,
timeout: 100000
})
}
const distributePeijianTasks = (data) => {
return request({
url: '/excel/distributePeijianTasks',
method: 'post',
data: data,
timeout: 100000
})
}
const distributeHejianTasks = (data) => {
return request({
url: '/excel/distributeHejianTasks',
method: 'post',
data: data,
timeout: 100000
})
}
const distributeJinjiTasks = (data) => {
return request({
url: '/excel/distributeJinjiTasks',
method: 'post',
data: data,
timeout: 100000
})
}
const downloadStockExcel = () => {
return request({
url: '/excel/downloadStockExcel',
method: 'get',
responseType: 'blob'
})
}
const downloadKateTaskExcel = () => {
return request({
url: '/excel/downloadKateTaskExcel',
method: 'get',
responseType: 'blob'
})
}
const downloadPeijianExcel = () => {
return request({
url: '/excel/downloadPeijianExcel',
method: 'get',
responseType: 'blob'
})
}
const downloadRukuExcel = () => {
return request({
url: '/excel/downloadRukuExcel',
method: 'get',
responseType: 'blob'
})
}
const downloadHejianExcel = () => {
return request({
url: '/excel/downloadHejianExcel',
method: 'get',
responseType: 'blob'
})
}
const downloadJinjiExcel = () => {
return request({
url: '/excel/downloadJinjiExcel',
method: 'get',
responseType: 'blob'
})
}
const downloadPackageExcel = () => {
return request({
url: '/excel/downloadPackageExcel',
method: 'get',
responseType: 'blob'
})
}
const downloadMaterialExcel = () => {
return request({
url: '/excel/downloadMaterialExcel',
method: 'get',
responseType: 'blob'
})
}
export {
downlocadExcel,
uploadExcel,
uploadExcelPeijian,
uploadExcelHejian,
uploadExcelParts,
distributePeijianTasks,
distributeHejianTasks,
downloadStockExcel,
downloadKateTaskExcel,
uploadExcelJinji,
distributeJinjiTasks,
downloadPeijianExcel,
downloadRukuExcel,
downloadHejianExcel,
downloadJinjiExcel,
downloadPackageExcel,
uploadBoxConfig,
uploadExcelKatePackage,
downloadMaterialExcel
}

View File

@ -0,0 +1,66 @@
import request from "@/http/request";
const getAllGoods = () => {
return request({
url: '/goods/getAllGoods',
method: 'get'
})
}
const getPartInfo = (params) => {
return request({
url: '/goods/getPartInfo',
method: 'post',
data: params
})
}
const updateGoodsInfo = (params) => {
return request({
url: '/goods/updateGoodsInfo',
method: 'post',
data: params
})
}
const queryPartInfoByPartNo = (params) => {
return request({
url: '/goods/queryPartInfoByPartNo',
method: 'post',
data: params
})
}
const updatePartInfo = (params) => {
return request({
url: '/goods/updatePartInfo',
method: 'post',
data: params
})
}
const queryPartNo = (params) => {
return request({
url: '/goods/queryPartNo',
method: 'post',
data: params
})
}
const deleteCurrentPartInfo = (params) => {
return request({
url: '/goods/deletePartInfo',
method: 'post',
data: params
})
}
export {
getAllGoods,
updateGoodsInfo,
queryPartInfoByPartNo,
getPartInfo,
updatePartInfo,
queryPartNo,
deleteCurrentPartInfo
}

View File

@ -0,0 +1,31 @@
import request from "@/http/request";
const getLocations = (params) => {
return request({
url: '/location/getLocations',
method: 'post',
data: params
})
}
const updateLocation = (params) => {
return request({
url: '/location/updateLocation',
method: 'post',
data: params
})
}
const getAvailableLocations = (params) => {
return request({
url: '/location/getAvailableLocations',
method: 'post',
data: params
})
}
export {
getLocations,
updateLocation,
getAvailableLocations
}

View File

@ -0,0 +1,31 @@
import request from "@/http/request";
const loginWithoutAuth = (params) => {
return request({
url: '/user/loginWithoutAuth',
method: 'post',
data: params
})
}
const loginWithAuth = (params) => {
return request({
url: '/user/loginWithAuth',
method: 'post',
data: params
})
}
const getUser = (params) => {
return request({
url: '/login/getUser',
method: 'post',
data: params
})
}
export {
loginWithoutAuth,
loginWithAuth,
getUser
}

View File

@ -0,0 +1,61 @@
import request from "@/http/request";
export default {
// 根据条件获取全部订单
getOrderInList(params) {
return request.post('/api/orderIn/queryOrderIn', params)
},
// 根据载具号查询
getOrderInWithVehicleNo(vehicleNo) {
return request.get('/api/orderIn/getOrderInWithVehicleNo', {
params: {
vehicleNo: vehicleNo
}
})
},
//下发任务
addOrderIn(params){
return request.post('/api/orderIn/addOrderIn', params)
},
// 绑定物料
bindingVehicle(params) {
return request.post('/api/orderIn/bindingVehicle', params)
},
//提交更新入库信息
updateForNum(params){
return request.post('/api/orderIn/updateForNum', params)
},
// 解绑物料
unbindingVehicle(rowId) {
return request.put('/api/orderIn/unBindingVehicle/' + rowId)
},
//删除订单
deleteOrderIn(rowId) {
return request.delete('/api/orderIn/deleteOrderIn/' + rowId)
},
// 根据条件获取全部订单
getOrderCheckList(params) {
return request.post('/api/orderCheck/queryOrderCheck',params)
},
downInventoryTask(){
return request.post('/api/orderCheck/downInventoryTask')
},
// 删除订单
deleteGoodsOrderInCheck(remarkReturn) {
return request.delete('/api/orderCheck/deleteCheckAll/' + remarkReturn)
},
//执行订单
executeCheck(recordId){
return request.put('/api/orderCheck/executeOrderCheck/' + recordId)
},
// 删除订单
deleteCheckList(recordId) {
return request.delete('/api/orderCheck/deleteCheck/' + recordId)
},
}

View File

@ -0,0 +1,30 @@
import request from "@/http/request";
export default {
// 根据条件获取全部订单
getOrderOutList(params) {
return request.post('/api/orderOut/queryOrderOut', params)
},
// 执行出库
executeOut(rowId) {
return request.put('/api/orderOut/executeOrderOut/' + rowId)
},
// 刪除按钮
deleteOrder(rowId){
return request.delete('/api/orderOut/deleteOrderOut/' + rowId)
},
// 添加按钮
addOrder(params){
return request.post('/api/orderOut/addOrderOut', params)
},
emptyAddOrder(params){
return request.post('/api/orderOut/emptyAddOrderOut', params)
},
addOrderByInsertEmpty(params){
return request.post('/api/orderOut/addOrderByInsertEmpty', params)
},
// // 库存页面执行出库
// outRowStock(rowId){
// return request.put('/api/orderOut/outRowStock/' + rowId)
// }
}

View File

@ -0,0 +1,13 @@
import request from "@/http/request";
const getTaskRecords = (params) => {
return request({
url: '/record/getTaskRecords',
method: 'post',
data: params
})
}
export {
getTaskRecords
}

View File

@ -0,0 +1,22 @@
import request from "@/http/request";
const getAllStands = (params) => {
return request({
url: '/stand/getAllStands',
method: 'post',
data: params
})
}
const updateStandInfo = (params) => {
return request({
url: '/stand/updateStandInfo',
method: 'post',
data: params
})
}
export {
getAllStands,
updateStandInfo
}

View File

@ -0,0 +1,31 @@
import request from "@/http/request";
const getAllStocks = (params) => {
return request({
url: '/stock/getAllStocks',
method: 'post',
data: params
})
}
const getAllStocksByGoodsId = (params) => {
return request({
url: '/stock/getAllStocksByGoodsId',
method: 'post',
data: params
})
}
const updateStockInfo = (params) => {
return request({
url: '/stock/updateStockInfo',
method: 'post',
data: params
})
}
export {
getAllStocks,
updateStockInfo,
getAllStocksByGoodsId
}

255
wms_client/src/api/task.js Normal file
View File

@ -0,0 +1,255 @@
import request from "@/http/request";
const sendVehicleNo = (params) => {
return request({
url: '/task/sendVehicleNo',
method: 'post',
data: params
})
}
const sendGoodsInTask = (params) => {
return request({
url: '/task/sendGoodsInTask',
method: 'post',
data: params
})
}
const submitPackageTask = (params) => {
return request({
url: '/taskOut/submitPackageTask',
method: 'post',
data: params
})
}
const sendGoodsOutTask = (params) => {
return request({
url: '/task/sendGoodsOutTask',
method: 'post',
data: params
})
}
const getAllTasks = () => {
return request({
url: '/task/getAllTasks',
method: 'get'
})
}
const sendInventoryTask = (params) => {
return request({
url: '/task/sendInventoryTask',
method: 'post',
data: params
})
}
const finishInventoryTask = (params) => {
return request({
url: '/task/finishInventoryTask',
method: 'post',
data: params
})
}
const getTasks = (params) => {
return request({
url: '/task/getTasks',
method: 'post',
data: params
})
}
const getAllKateTasks = (params) => {
return request({
url: '/task/getKateTasks',
method: 'post',
data: params
})
}
const getKateTasksByTask = (params) => {
return request({
url: '/task/getKateTasksByTask',
method: 'post',
data: params
})
}
const finishPicking = (params) => {
return request({
url: '/task/finishPicking',
method: 'post',
data: params
})
}
const finishCurrentKateTask = (params) => {
return request({
url: '/task/finishCurrentKateTask',
method: 'post',
data: params
})
}
const getTaskByTask = (params) => {
return request({
url: '/task/getTaskByTask',
method: 'post',
data: params
})
}
const getAllPeijians = (params) => {
return request({
url: '/task/getAllPeijians',
method: 'post',
data: params
})
}
const getPeijians = (params) => {
return request({
url: '/task/getPeijians',
method: 'post',
data: params
})
}
const getAllHejians = (params) => {
return request({
url: '/task/getAllHejians',
method: 'post',
data: params
})
}
const getHejians = (params) => {
return request({
url: '/task/getHejians',
method: 'post',
data: params
})
}
const getAllJinjis = (params) => {
return request({
url: '/task/getAllJinjis',
method: 'post',
data: params
})
}
const getJinjis = (params) => {
return request({
url: '/task/getJinjis',
method: 'post',
data: params
})
}
const getAllPackages = (params) => {
return request({
url: '/task/getAllPackages',
method: 'post',
data: params
})
}
const getPackages = (params) => {
return request({
url: '/task/getPackages',
method: 'post',
data: params
})
}
const getPrintData = (params) => {
return request({
url: '/task/getPrintData',
method: 'post',
data: params
})
}
const redistributeLackKateTask = (params) =>{
return request({
url: '/task/redistributeLackKateTask',
method: 'post',
data: params
})
}
const callEmptyVehicle = (params) => {
return request({
url: '/taskOut/callEmptyVehicle',
method: 'post',
data: params
})
}
const changeTaskStatus = (params) => {
return request({
url: '/taskDeal/changeTaskStatus',
method: 'post',
data: params
})
}
const deleteAllKateTasks = (params) => {
return request({
url: '/taskDeal/deleteAllKateTasks',
method: 'post',
data: params
})
}
const sendBoxArrive = (params) => {
return request({
url: '/task/boxArrive',
method: 'post',
data: params
})
}
const selectVehicleOut = (params) => {
return request({
url: '/task/vehicleOut',
method: 'post',
data: params
})
}
export {
sendVehicleNo,
sendGoodsInTask,
sendGoodsOutTask,
getAllTasks,
sendInventoryTask,
finishInventoryTask,
getTasks,
getAllKateTasks,
getKateTasksByTask,
finishPicking,
finishCurrentKateTask,
getTaskByTask,
getAllPeijians,
getAllHejians,
getPrintData,
redistributeLackKateTask,
getPeijians,
getHejians,
getJinjis,
getAllJinjis,
getAllPackages,
getPackages,
callEmptyVehicle,
changeTaskStatus,
deleteAllKateTasks,
submitPackageTask,
sendBoxArrive,
selectVehicleOut
}

View File

@ -0,0 +1,59 @@
import request from "@/http/request";
// 登录方法
export function login(username, password, code, uuid) {
const data = {
username,
password,
code,
uuid
}
return request({
url: '/login',
headers: {
isToken: false
},
method: 'post',
data: data
})
}
// 注册方法
export function register(data) {
return request({
url: '/register',
headers: {
isToken: false
},
method: 'post',
data: data
})
}
// 获取用户详细信息
export function getInfo() {
return request({
url: '/getInfo',
method: 'get'
})
}
// 退出方法
export function logout() {
return request({
url: '/logout',
method: 'post'
})
}
// 获取验证码
export function getCodeImg() {
return request({
url: '/captchaImage',
headers: {
isToken: false
},
method: 'get',
timeout: 20000
})
}

View File

@ -0,0 +1,31 @@
import request from "@/http/request";
const getAllVehicles = (params) => {
return request({
url: '/location/getVehicles',
method: 'post',
data: params
})
}
const updateVehicleInfo = (params) => {
return request({
url: '/location/updateVehicleInfo',
method: 'post',
data: params
})
}
const deleteCurrentVehicle = (params) => {
return request({
url: '/location/deleteVehicle',
method: 'post',
data: params
})
}
export {
getAllVehicles,
updateVehicleInfo,
deleteCurrentVehicle
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

@ -0,0 +1,258 @@
<!-- -->
<template>
<div style="margin-left: 10px">
<el-dialog :model-value="modelValue" :show-close="false" title="下发入库任务"
@close="() => $emit('update:modelValue', false)">
<div>
<el-form
label-width="100px"
:model="bindingData"
require-asterisk-position="right"
inline
>
<el-form-item label="载具号:" required>
<el-input class="form-input" v-model="bindingData.vehicleNo" clearable/>
</el-form-item>
<el-form-item label="零件号:">
<el-input class="form-input" v-model="bindingData.goodsId" clearable/>
</el-form-item>
<el-form-item label="数量:" >
<el-input class="form-input" v-model="bindingData.goodsNum" clearable/>
</el-form-item>
<el-form-item label="库区选择:" prop="abcSelect" required>
<el-select v-model="bindingData.abcSelect" placeholder="请选择" style="width: 100%;">
<el-option label="A" value="A"></el-option>
<el-option label="B" value="B"></el-option>
<el-option label="C" value="C"></el-option>
</el-select>
</el-form-item>
<el-form-item label="物料种类:" prop="efSelect" required>
<el-select v-model="bindingData.efSelect" placeholder="请选择" style="width: 120%;">
<el-option label="单种" value="E"></el-option>
<el-option label="多种" value="F"></el-option>
<el-option label="空托" value="G"></el-option>
</el-select>
</el-form-item>
<div style="margin-top: 50px">
<el-button type="warning" @click="resetInput">
<el-icon class="el-icon--left"><RefreshRight/></el-icon>
重置输入
</el-button>
<el-button type="primary" @click="addOrderIn()">
<el-icon class="el-icon--left"><Search /></el-icon>
下发任务
</el-button>
<el-button type="danger" @click="$emit('update:modelValue', false)">
<el-icon class="el-icon--left"><CircleCloseFilled/></el-icon>
关闭窗口
</el-button>
</div>
</el-form>
</div>
</el-dialog>
</div>
</template>
<script>
// import from ' ';
import {CircleCloseFilled, Close, RefreshRight} from "@element-plus/icons-vue";
import {formatterOrderInEnum} from "@/enum/order.in.enum";
import {formatCellValueTime} from "@/utils/formatter";
import {ElMessage, ElMessageBox} from "element-plus";
import apiOrderIn from '@/api/order.in';
export default {
// import 使
components: {Close, CircleCloseFilled, RefreshRight},
props: ['modelValue'],
emits: ['update:modelValue'],
data() {
//
return {
//
bindingData: {
vehicleNo: '',
goodsId: '',
goodsNum: '',
abcSelect: '',
efSelect: ''
},
bindOrderInList: []
}
},
// data
computed: {},
// data
watch: {},
//
methods: {
formatCellValueTime,
formatterOrderInEnum,
test() {
console.log(this.bindingData);
},
//
addOrderIn() {
if(this.bindingData.efSelect === 'G') {
if(this.bindingData.goodsId !== '' || this.bindingData.goodsNum !== '' ){
ElMessage({
message: '空托盘入库不能填写物料号和数量',
type: 'error',
});
return;
}
}else {
if(this.bindingData.goodsId === '' || this.bindingData.goodsNum === '' ){
ElMessage({
message: '物料号和数量不能为空',
type: 'error',
});
return;
}
}
if(this.bindingData.vehicleNo === '' || this.bindingData.abcSelect === '' || this.bindingData.efSelect === '') {
ElMessage({
message: '载具号,库区和物料种类不能为空',
type: 'error',
});
return;
}
this.bindOrderInList = []
ElMessageBox.confirm(`是否下发入库任务?`, '提示')
.then(() => {
apiOrderIn.addOrderIn(this.bindingData).then(res => {
const responseData = res.data;
if (responseData.code === 0) {
//
ElMessage({
message: '执行成功',
type: 'success',
});
this.bindOrderInList = responseData['returnData'];
} else {
//
ElMessageBox.alert(`服务器返回失败:${responseData.message}`, '执行失败', {
type: 'warning',
confirmButtonText: '确定',
showClose: false
})
}
}).catch(err => {
//
ElMessageBox.alert(`请求服务器失败::${err}`, '任务添加失败', {
type: 'warning',
confirmButtonText: '确定'
})
})
})
.catch(() => {
})
},
//
resetInput() {
this.bindingData.vehicleNo = '';
this.bindingData.goodsId = '';
this.bindingData.goodsNum = '';
},
//
bindingGoods() {
if(this.bindingData.vehicleNo === '' || this.bindingData.code === '') {
ElMessage({
message: '载具号和物料号不能为空',
type: 'error',
});
return;
}
apiOrderIn.bindingVehicle({vehicleNo: this.bindingData.vehicleNo, code: this.bindingData.code}).then(res => {
const responseData = res.data
if (responseData.code === 0) {
//
ElMessage({
message: '绑定成功',
type: 'success',
});
this.queryBinding();
this.bindingData.code = '';
} else {
//
ElMessageBox.alert(`服务器返回失败:${responseData.message}`, '绑定失败', {
type: 'warning',
confirmButtonText: '确定',
showClose: false
})
}
}).catch(err => {
//
ElMessageBox.alert(`请求服务器失败::${err}`, '任务添加失败', {
type: 'warning',
confirmButtonText: '确定'
})
})
},
//
unBindingOrder(row) {
apiOrderIn.unbindingVehicle(row.rowId).then(res => {
const responseData = res.data
if (responseData.code === 0) {
//
ElMessage({
message: '解绑成功',
type: 'success',
});
this.queryBinding();
} else {
//
ElMessageBox.alert(`服务器返回失败:${responseData.message}`, '解绑失败', {
type: 'warning',
confirmButtonText: '确定',
showClose: false
})
}
}).catch(err => {
//
ElMessageBox.alert(`请求服务器失败::${err}`, '任务添加失败', {
type: 'warning',
confirmButtonText: '确定'
})
})
}
},
// API
setup() {
},
//
beforeCreate() {
},
// (访 this )
created() {
},
// -
beforeMount() {
},
// - 访 DOM
mounted() {
},
//
beforeUpdate() {
},
//
updated() {
},
//
beforeUnmount() {
},
//
unmounted() {
}
}
</script>
<style lang="scss" scoped>
$input-width: 500px;
.form-input {
width: $input-width;
}
</style>

View File

@ -0,0 +1,71 @@
// AppTag
<template>
<div class="app-tag">
<el-tag closable size="default" v-for="(tag, index) in tags" :key="tag.labelName" :disable-transitions="true"
:effect="$route.path === tag.path ? 'dark' : 'plain'" @close="handleClose(tag, index)"
@click="handleClick(tag)">
{{ tag.labelName }}
</el-tag>
</div>
</template>
<script>
import { mapState, mapMutations } from 'vuex';
export default {
name: 'app-tag',
data() {
return {
tags: []
}
},
created() {
//stateTagsListstate.jstagskeystateTagsList
this.tags = this.stateTagsList;
},
computed: {
...mapState(['stateTagsList'])
},
methods: {
...mapMutations({
close: 'mutationCloseTag'
}),
handleClose(tag, index) {
if (this.tags.length === 1) { //
return
}
this.close(tag) // tag
if (this.$router.path === tag.path) { //
return
} else {
if (index === (this.tags.length - 1)) { // ,
this.$router.push(this.tags[index].path)
} else { //
if (index === 0) {
this.$router.push(this.tags[0].path)
} else {
this.$router.push(this.tags[index - 1].path)
}
}
}
},
// tags
handleClick(tag) {
this.$router.push(tag.path)
}
}
}
</script>
<style scoped>
.app-tag .el-tag {
cursor: pointer;
height: 30px;
margin-right: 2px;
}
.app-tag .el-tag:hover {
color: #000;
background-color: #5A9CF8;
}
</style>

View File

@ -0,0 +1,222 @@
<!-- -->
<template>
<div style="margin-left: 10px">
<el-dialog :model-value="modelValue" :show-close="false" title="下发盘点任务"
@close="() => $emit('update:modelValue', false)">
<div>
<el-form
label-width="100px"
:model="bindingData"
require-asterisk-position="right"
inline
>
<el-form-item label="载具号:" required>
<el-input class="form-input" v-model="bindingData.vehicleNo" clearable/>
</el-form-item>
<el-form-item label="零件号:" required>
<el-input class="form-input" v-model="bindingData.goodsId" clearable/>
</el-form-item>
<el-form-item label="数量:" required>
<el-input class="form-input" v-model="bindingData.goodsNum" clearable/>
</el-form-item>
<div style="margin-top: 50px">
<el-button type="warning" @click="resetInput">
<el-icon class="el-icon--left"><RefreshRight/></el-icon>
重置输入
</el-button>
<el-button type="primary" @click="addOrderIn()">
<el-icon class="el-icon--left"><Search /></el-icon>
下发任务
</el-button>
<el-button type="danger" @click="$emit('update:modelValue', false)">
<el-icon class="el-icon--left"><CircleCloseFilled/></el-icon>
关闭窗口
</el-button>
</div>
</el-form>
</div>
</el-dialog>
</div>
</template>
<script>
// import from ' ';
import {CircleCloseFilled, Close, RefreshRight} from "@element-plus/icons-vue";
import {formatterOrderInEnum} from "@/enum/order.in.enum";
import {formatCellValueTime} from "@/utils/formatter";
import {ElMessage, ElMessageBox} from "element-plus";
import apiOrderIn from '@/api/order.in';
export default {
// import 使
components: {Close, CircleCloseFilled, RefreshRight},
props: ['modelValue'],
emits: ['update:modelValue'],
data() {
//
return {
//
bindingData: {
vehicleNo: '',
goodsId: '',
goodsNum: ''
},
bindOrderInList: []
}
},
// data
computed: {},
// data
watch: {},
//
methods: {
formatCellValueTime,
formatterOrderInEnum,
//
addOrderIn() {
if(this.bindingData.vehicleNo === '' || this.bindingData.goodsId === '' || this.bindingData.goodsNum === '') {
ElMessage({
message: '载具号、零件号和数量不能为空',
type: 'error',
});
return;
}
this.bindOrderInList = []
ElMessageBox.confirm(`是否下发入库任务?`, '提示')
.then(() => {
apiOrderIn.addOrderIn(this.bindingData).then(res => {
const responseData = res.data;
if (responseData.code === 0) {
//
ElMessage({
message: '执行成功',
type: 'success',
});
this.bindOrderInList = responseData['returnData'];
} else {
//
ElMessageBox.alert(`服务器返回失败:${responseData.message}`, '执行失败', {
type: 'warning',
confirmButtonText: '确定',
showClose: false
})
}
}).catch(err => {
//
ElMessageBox.alert(`请求服务器失败::${err}`, '任务添加失败', {
type: 'warning',
confirmButtonText: '确定'
})
})
})
.catch(() => {
})
},
//
resetInput() {
this.bindingData.vehicleNo = '';
this.bindingData.goodsId = '';
this.bindingData.goodsNum = '';
},
//
bindingGoods() {
if(this.bindingData.vehicleNo === '' || this.bindingData.code === '') {
ElMessage({
message: '载具号和物料号不能为空',
type: 'error',
});
return;
}
apiOrderIn.bindingVehicle({vehicleNo: this.bindingData.vehicleNo, code: this.bindingData.code}).then(res => {
const responseData = res.data
if (responseData.code === 0) {
//
ElMessage({
message: '绑定成功',
type: 'success',
});
this.queryBinding();
this.bindingData.code = '';
} else {
//
ElMessageBox.alert(`服务器返回失败:${responseData.message}`, '绑定失败', {
type: 'warning',
confirmButtonText: '确定',
showClose: false
})
}
}).catch(err => {
//
ElMessageBox.alert(`请求服务器失败::${err}`, '任务添加失败', {
type: 'warning',
confirmButtonText: '确定'
})
})
},
//
unBindingOrder(row) {
apiOrderIn.unbindingVehicle(row.rowId).then(res => {
const responseData = res.data
if (responseData.code === 0) {
//
ElMessage({
message: '解绑成功',
type: 'success',
});
this.queryBinding();
} else {
//
ElMessageBox.alert(`服务器返回失败:${responseData.message}`, '解绑失败', {
type: 'warning',
confirmButtonText: '确定',
showClose: false
})
}
}).catch(err => {
//
ElMessageBox.alert(`请求服务器失败::${err}`, '任务添加失败', {
type: 'warning',
confirmButtonText: '确定'
})
})
}
},
// API
setup() {
},
//
beforeCreate() {
},
// (访 this )
created() {
},
// -
beforeMount() {
},
// - 访 DOM
mounted() {
},
//
beforeUpdate() {
},
//
updated() {
},
//
beforeUnmount() {
},
//
unmounted() {
}
}
</script>
<style lang="scss" scoped>
$input-width: 500px;
.form-input {
width: $input-width;
}
</style>

View File

@ -0,0 +1,225 @@
<!-- -->
<template>
<div style="margin-left: 10px">
<el-dialog :model-value="modelValue" :show-close="false" title="下发空托盘出库任务"
@close="() => $emit('update:modelValue', false)">
<div>
<el-form
label-width="150px"
:model="bindingData"
require-asterisk-position="right"
inline
>
<el-form-item label="托盘号:" required>
<el-input class="form-input" v-model="bindingData.vehicleNo" clearable/>
</el-form-item>
<div style="margin-top: 50px">
<el-button type="warning" @click="resetInput">
<el-icon class="el-icon--left"><RefreshRight/></el-icon>
重置输入
</el-button>
<el-button type="primary" @click="addOrder()">
<el-icon class="el-icon--left"><Search /></el-icon>
下发任务
</el-button>
<el-button type="danger" @click="$emit('update:modelValue', false)">
<el-icon class="el-icon--left"><CircleCloseFilled/></el-icon>
关闭窗口
</el-button>
</div>
</el-form>
</div>
</el-dialog>
</div>
</template>
<script>
// import from ' ';
import {CircleCloseFilled, Close, RefreshRight} from "@element-plus/icons-vue";
import {formatterOrderInEnum} from "@/enum/order.in.enum";
import {formatCellValueTime} from "@/utils/formatter";
import {ElMessage, ElMessageBox} from "element-plus";
//import apiOrderIn from '@/api/order.in';
import apiOrderOut from '@/api/order.out'
export default {
// import 使
components: {Close, CircleCloseFilled, RefreshRight},
props: ['modelValue'],
emits: ['update:modelValue'],
data() {
//
return {
//
bindingData: {
vehicleNo: '',
},
bindOrderInList: []
}
},
// data
computed: {},
// data
watch: {},
//
methods: {
formatCellValueTime,
formatterOrderInEnum,
addOrder() {
if(this.bindingData.vehicleNo === '') {
ElMessage({
message: '托盘号不能为空',
type: 'error',
});
return;
}
this.bindOrderInList = []
ElMessageBox.confirm(`是否执行空托出库?`, '提示')
.then(() => {
apiOrderOut.addOrder(this.bindingData).then(res => {
const responseData = res.data;
if (responseData.code === 0) {
//
ElMessage({
message: '执行成功',
type: 'success',
});
this.bindOrderInList = responseData['returnData'];
} else {
//
ElMessageBox.alert(`服务器返回失败:${responseData.message}`, '执行失败', {
type: 'warning',
confirmButtonText: '确定',
showClose: false
})
}
}).catch(err => {
//
ElMessageBox.alert(`请求服务器失败::${err}`, '任务添加失败', {
type: 'warning',
confirmButtonText: '确定'
})
})
})
.catch(() => {
})
},
test() {
console.log(this.bindingData);
},
//
queryBinding() {
if(this.bindingData.vehicleNo === '') {
ElMessage({
message: '载具号不能为空',
type: 'error',
});
return;
}
this.bindOrderInList = [];
apiOrderIn.getOrderInWithVehicleNo(this.bindingData.vehicleNo).then(res => {
const responseData = res.data
if (responseData.code === 0) {
//
ElMessage({
message: '查询成功',
type: 'success',
});
this.bindOrderInList = responseData['returnData'];
} else {
//
ElMessageBox.alert(`服务器返回失败:${responseData.message}`, '查询失败', {
type: 'warning',
confirmButtonText: '确定',
showClose: false
})
}
}).catch(err => {
//
ElMessageBox.alert(`请求服务器失败::${err}`, '任务添加失败', {
type: 'warning',
confirmButtonText: '确定'
})
})
},
//
resetInput() {
this.bindingData.vehicleNo = '';
},
//
bindingGoods() {
if(this.bindingData.vehicleNo === '' || this.bindingData.code === '') {
ElMessage({
message: '载具号和物料号不能为空',
type: 'error',
});
return;
}
apiOrderIn.bindingVehicle({vehicleNo: this.bindingData.vehicleNo, code: this.bindingData.code}).then(res => {
const responseData = res.data
if (responseData.code === 0) {
//
ElMessage({
message: '绑定成功',
type: 'success',
});
this.queryBinding();
this.bindingData.code = '';
} else {
//
ElMessageBox.alert(`服务器返回失败:${responseData.message}`, '绑定失败', {
type: 'warning',
confirmButtonText: '确定',
showClose: false
})
}
}).catch(err => {
//
ElMessageBox.alert(`请求服务器失败::${err}`, '任务添加失败', {
type: 'warning',
confirmButtonText: '确定'
})
})
},
},
// API
setup() {
},
//
beforeCreate() {
},
// (访 this )
created() {
},
// -
beforeMount() {
},
// - 访 DOM
mounted() {
},
//
beforeUpdate() {
},
//
updated() {
},
//
beforeUnmount() {
},
//
unmounted() {
}
}
</script>
<style lang="scss" scoped>
$input-width: 500px;
.form-input {
width: $input-width;
}
</style>

View File

@ -0,0 +1,230 @@
<!-- -->
<template>
<div style="margin-left: 10px">
<el-dialog :model-value="modelValue" :show-close="false" title="下发出库任务"
@close="() => $emit('update:modelValue', false)">
<div>
<el-form
label-width="150px"
:model="bindingData"
require-asterisk-position="right"
inline
>
<el-form-item label="零件号:" required>
<el-input class="form-input" v-model="bindingData.goodsId" clearable/>
</el-form-item>
<el-form-item label="数量:" required>
<el-input class="form-input" v-model="bindingData.goodsNum" clearable/>
</el-form-item>
<div style="margin-top: 50px">
<el-button type="warning" @click="resetInput">
<el-icon class="el-icon--left"><RefreshRight/></el-icon>
重置输入
</el-button>
<el-button type="primary" @click="addOrder()">
<el-icon class="el-icon--left"><Search /></el-icon>
下发任务
</el-button>
<el-button type="danger" @click="$emit('update:modelValue', false)">
<el-icon class="el-icon--left"><CircleCloseFilled/></el-icon>
关闭窗口
</el-button>
</div>
</el-form>
</div>
</el-dialog>
</div>
</template>
<script>
// import from ' ';
import {CircleCloseFilled, Close, RefreshRight} from "@element-plus/icons-vue";
import {formatterOrderInEnum} from "@/enum/order.in.enum";
import {formatCellValueTime} from "@/utils/formatter";
import {ElMessage, ElMessageBox} from "element-plus";
//import apiOrderIn from '@/api/order.in';
import apiOrderOut from '@/api/order.out'
export default {
// import 使
components: {Close, CircleCloseFilled, RefreshRight},
props: ['modelValue'],
emits: ['update:modelValue'],
data() {
//
return {
//
bindingData: {
goodsId: '',
goodsNum: '',
},
bindOrderInList: []
}
},
// data
computed: {},
// data
watch: {},
//
methods: {
formatCellValueTime,
formatterOrderInEnum,
addOrder() {
if(this.bindingData.goodsId === '' || this.bindingData.goodsNum === '') {
ElMessage({
message: '数量和物料号不能为空',
type: 'error',
});
return;
}
this.bindOrderInList = []
ElMessageBox.confirm(`是否执行手动出库?`, '提示')
.then(() => {
apiOrderOut.addOrder(this.bindingData).then(res => {
const responseData = res.data;
if (responseData.code === 0) {
//
ElMessage({
message: '执行成功',
type: 'success',
});
this.bindOrderInList = responseData['returnData'];
} else {
//
ElMessageBox.alert(`服务器返回失败:${responseData.message}`, '执行失败', {
type: 'warning',
confirmButtonText: '确定',
showClose: false
})
}
}).catch(err => {
//
ElMessageBox.alert(`请求服务器失败::${err}`, '任务添加失败', {
type: 'warning',
confirmButtonText: '确定'
})
})
})
.catch(() => {
})
},
test() {
console.log(this.bindingData);
},
//
queryBinding() {
if(this.bindingData.vehicleNo === '') {
ElMessage({
message: '载具号不能为空',
type: 'error',
});
return;
}
this.bindOrderInList = [];
apiOrderIn.getOrderInWithVehicleNo(this.bindingData.vehicleNo).then(res => {
const responseData = res.data
if (responseData.code === 0) {
//
ElMessage({
message: '查询成功',
type: 'success',
});
this.bindOrderInList = responseData['returnData'];
} else {
//
ElMessageBox.alert(`服务器返回失败:${responseData.message}`, '查询失败', {
type: 'warning',
confirmButtonText: '确定',
showClose: false
})
}
}).catch(err => {
//
ElMessageBox.alert(`请求服务器失败::${err}`, '任务添加失败', {
type: 'warning',
confirmButtonText: '确定'
})
})
},
//
resetInput() {
this.bindingData.goodsId = '';
this.bindingData.goodsNum = '';
},
//
bindingGoods() {
if(this.bindingData.vehicleNo === '' || this.bindingData.code === '') {
ElMessage({
message: '载具号和物料号不能为空',
type: 'error',
});
return;
}
apiOrderIn.bindingVehicle({vehicleNo: this.bindingData.vehicleNo, code: this.bindingData.code}).then(res => {
const responseData = res.data
if (responseData.code === 0) {
//
ElMessage({
message: '绑定成功',
type: 'success',
});
this.queryBinding();
this.bindingData.code = '';
} else {
//
ElMessageBox.alert(`服务器返回失败:${responseData.message}`, '绑定失败', {
type: 'warning',
confirmButtonText: '确定',
showClose: false
})
}
}).catch(err => {
//
ElMessageBox.alert(`请求服务器失败::${err}`, '任务添加失败', {
type: 'warning',
confirmButtonText: '确定'
})
})
},
},
// API
setup() {
},
//
beforeCreate() {
},
// (访 this )
created() {
},
// -
beforeMount() {
},
// - 访 DOM
mounted() {
},
//
beforeUpdate() {
},
//
updated() {
},
//
beforeUnmount() {
},
//
unmounted() {
}
}
</script>
<style lang="scss" scoped>
$input-width: 500px;
.form-input {
width: $input-width;
}
</style>

View File

@ -0,0 +1,229 @@
<!-- -->
<template>
<div style="margin-left: 10px">
<el-dialog :model-value="modelValue" :show-close="false" title="添加一个空托盘"
@close="() => $emit('update:modelValue', false)">
<div>
<el-form
label-width="150px"
:model="bindingData"
require-asterisk-position="right"
inline
>
<el-form-item label="托盘号:" required>
<el-input class="form-input" v-model="bindingData.vehicleNo" clearable/>
</el-form-item>
<el-form-item label="位置:" required>
<el-input class="form-input" v-model="bindingData.location" clearable/>
</el-form-item>
<div style="margin-top: 50px">
<el-button type="warning" @click="resetInput">
<el-icon class="el-icon--left"><RefreshRight/></el-icon>
重置输入
</el-button>
<el-button type="primary" @click="addOrder()">
<el-icon class="el-icon--left"><Search /></el-icon>
添加空框
</el-button>
<el-button type="danger" @click="$emit('update:modelValue', false)">
<el-icon class="el-icon--left"><CircleCloseFilled/></el-icon>
关闭窗口
</el-button>
</div>
</el-form>
</div>
</el-dialog>
</div>
</template>
<script>
// import from ' ';
import {CircleCloseFilled, Close, RefreshRight} from "@element-plus/icons-vue";
import {formatterOrderInEnum} from "@/enum/order.in.enum";
import {formatCellValueTime} from "@/utils/formatter";
import {ElMessage, ElMessageBox} from "element-plus";
//import apiOrderIn from '@/api/order.in';
import apiOrderOut from '@/api/order.out'
export default {
// import 使
components: {Close, CircleCloseFilled, RefreshRight},
props: ['modelValue'],
emits: ['update:modelValue'],
data() {
//
return {
//
bindingData: {
vehicleNo: '',
location: '',
},
bindOrderInList: []
}
},
// data
computed: {},
// data
watch: {},
//
methods: {
formatCellValueTime,
formatterOrderInEnum,
addOrder() {
if(this.bindingData.vehicleNo === '' || this.bindingData.location === '') {
ElMessage({
message: '托盘号和位置不能为空',
type: 'error',
});
return;
}
this.bindOrderInList = []
ElMessageBox.confirm(`是否添加一个空托盘?`, '提示')
.then(() => {
apiOrderOut.addOrderByInsertEmpty(this.bindingData).then(res => {
const responseData = res.data;
if (responseData.code === 0) {
//
ElMessage({
message: '执行成功',
type: 'success',
});
this.bindOrderInList = responseData['returnData'];
} else {
//
ElMessageBox.alert(`服务器返回失败:${responseData.message}`, '执行失败', {
type: 'warning',
confirmButtonText: '确定',
showClose: false
})
}
}).catch(err => {
//
ElMessageBox.alert(`请求服务器失败::${err}`, '任务添加失败', {
type: 'warning',
confirmButtonText: '确定'
})
})
})
.catch(() => {
})
},
test() {
console.log(this.bindingData);
},
//
queryBinding() {
if(this.bindingData.vehicleNo === '') {
ElMessage({
message: '载具号不能为空',
type: 'error',
});
return;
}
this.bindOrderInList = [];
apiOrderIn.getOrderInWithVehicleNo(this.bindingData.vehicleNo).then(res => {
const responseData = res.data
if (responseData.code === 0) {
//
ElMessage({
message: '查询成功',
type: 'success',
});
this.bindOrderInList = responseData['returnData'];
} else {
//
ElMessageBox.alert(`服务器返回失败:${responseData.message}`, '查询失败', {
type: 'warning',
confirmButtonText: '确定',
showClose: false
})
}
}).catch(err => {
//
ElMessageBox.alert(`请求服务器失败::${err}`, '任务添加失败', {
type: 'warning',
confirmButtonText: '确定'
})
})
},
//
resetInput() {
this.bindingData.vehicleNo = '';
},
//
bindingGoods() {
if(this.bindingData.vehicleNo === '' || this.bindingData.code === '') {
ElMessage({
message: '载具号和物料号不能为空',
type: 'error',
});
return;
}
apiOrderIn.bindingVehicle({vehicleNo: this.bindingData.vehicleNo, code: this.bindingData.code}).then(res => {
const responseData = res.data
if (responseData.code === 0) {
//
ElMessage({
message: '绑定成功',
type: 'success',
});
this.queryBinding();
this.bindingData.code = '';
} else {
//
ElMessageBox.alert(`服务器返回失败:${responseData.message}`, '绑定失败', {
type: 'warning',
confirmButtonText: '确定',
showClose: false
})
}
}).catch(err => {
//
ElMessageBox.alert(`请求服务器失败::${err}`, '任务添加失败', {
type: 'warning',
confirmButtonText: '确定'
})
})
},
},
// API
setup() {
},
//
beforeCreate() {
},
// (访 this )
created() {
},
// -
beforeMount() {
},
// - 访 DOM
mounted() {
},
//
beforeUpdate() {
},
//
updated() {
},
//
beforeUnmount() {
},
//
unmounted() {
}
}
</script>
<style lang="scss" scoped>
$input-width: 500px;
.form-input {
width: $input-width;
}
</style>

View File

@ -0,0 +1,58 @@
<template>
<div class="menu-title">主菜单</div>
<!-- 侧边栏菜单区域 -->
<el-menu active-text-color="#409Eff" background-color="#fff" text-color="#000" :router="true" unique-opened>
<!-- 一级菜单 -->
<el-sub-menu :index="item.id" v-for="item in menuList" :key="item.id">
<!-- 一级菜单模板区域 -->
<template #title>
<el-icon>
<component :is="item.iconValue"></component>
</el-icon>
<span>{{ item.labelName }}</span>
</template>
<!-- 二级菜单 -->
<el-menu-item :index="subItem.path" v-for="subItem in item.children" :key="subItem.id"
@click="clickMenu(subItem)">
<template #title>
<span>{{ subItem.labelName }}</span>
</template>
</el-menu-item>
</el-sub-menu>
</el-menu>
</template>
<script setup>
import store from '@/store'
// import { mapState, mapMutations } from 'vuex';
</script>
<script>
export default {
name: 'side-menu',
data() {
return {
menuList: []
}
},
mounted() {
this.getMenuList()
},
methods: {
getMenuList() {
// this.menuList = this.$store.state.menuList
this.menuList = store.getters.getMenuList
},
//
clickMenu(value) {
//vuexstore
store.commit('mutationSelectTags', value)
}
}
}
</script>
<style scoped>
.menu-title {
margin-top: 5px;
}
</style>

View File

@ -0,0 +1,55 @@
<template>
<el-upload :on-preview="previewFile" :limit="1" :on-change="changeFile" :auto-upload="false" :data="uploadForm.data">
<template #trigger>
<el-button size="small" type="primary">选取文件</el-button>
</template>
<el-button style="margin-left: 10px;" size="small" type="success" @click="submitUpload">确认导入</el-button>
</el-upload>
</template>
<script setup>
import { ref, reactive } from 'vue';
import { uploadExcel } from '@/api/excel.js'
import { ElMessage } from 'element-plus'
const file = ref()
const uploadForm = reactive({
data: {
fileId: '',
name: '',
type: ''
}
})
const changeFile = (uploadFile) => {
file.value = uploadFile
}
const submitUpload = () => {
if (uploadForm == undefined || file.value == undefined) {
ElMessage.error('请选择文件之后再导入')
}
const jsonStr = JSON.stringify(uploadForm.data);
const blob = new Blob([jsonStr], {
type: 'application/json'
});
let formData = new FormData();
// file.value.rawfilefile.valueProxy
formData.append("file", file.value.raw);
uploadExcel(formData).then(res => {
console.log(res.data)
if (res.data.code == 0) {
ElMessage({
message: '导入成功',
type: 'success',
})
} else {
ElMessage.error(res.data.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('导入错误')
})
}
const previewFile = () => {
}
</script>
<style scoped></style>

View File

@ -0,0 +1,39 @@
// 入库单状态
export const orderInEnum = {
creat: {
value: 0,
label: '待入库',
color: 'info'
},
running: {
value: 1,
label: '正在入库',
color: 'primary'
},
finish: {
value: 2,
label: '绑定成功',
color: 'success'
},
error: {
value: 9,
label: '执行异常',
color: 'danger'
}
}
export function formatterOrderInEnum(value) {
switch (parseInt(value)){
case orderInEnum.creat.value:
return {label: orderInEnum.creat.label, type: orderInEnum.creat.color};
case orderInEnum.running.value:
return {label: orderInEnum.running.label, type: orderInEnum.running.color};
case orderInEnum.finish.value:
return {label: orderInEnum.finish.label, type: orderInEnum.finish.color};
case orderInEnum.error.value:
return {label: orderInEnum.error.label, type: orderInEnum.error.color};
default:
return {label: `未知类型:${value}`, type: 'danger'};
}
}

View File

@ -0,0 +1,32 @@
// 出库单状态
export const orderOutEnum = {
creat: {
value: 0,
label: '待出库',
color: 'info'
},
running: {
value: 1,
label: '出库中',
color: 'primary'
},
error: {
value: 9,
label: '执行异常',
color: 'danger'
}
}
export function formatterOrderOutEnum(value) {
switch (parseInt(value)){
case orderOutEnum.creat.value:
return {label: orderOutEnum.creat.label, type: orderOutEnum.creat.color};
case orderOutEnum.running.value:
return {label: orderOutEnum.running.label, type: orderOutEnum.running.color};
case orderOutEnum.error.value:
return {label: orderOutEnum.error.label, type: orderOutEnum.error.color};
default:
return {label: `未知类型:${value}`, type: 'danger'};
}
}

View File

@ -0,0 +1,58 @@
<template>
<el-upload ref="uploadRef" :on-preview="previewFile" :limit="1" :on-change="changeFile" :auto-upload="false" :data="uploadForm.data">
<template #trigger>
<el-button type="primary">选取文件</el-button>
</template>
<el-button style="margin-left: 5px;" type="success" @click="uploadParts">确认导入零件数据</el-button>
</el-upload>
</template>
<script setup>
import { ref, reactive } from 'vue';
import { uploadExcelParts } from '@/api/excel.js'
import { ElMessage } from 'element-plus'
const file = ref()
const uploadForm = reactive({
data: {
fileId: '',
name: '',
type: ''
}
})
const changeFile = (uploadFile) => {
file.value = uploadFile
}
const uploadRef = ref()
const uploadParts = () => {
if (uploadForm == undefined || file.value == undefined) {
ElMessage.error('请选择文件之后再导入')
}
const jsonStr = JSON.stringify(uploadForm.data);
const blob = new Blob([jsonStr], {
type: 'application/json'
});
let formData = new FormData();
// file.value.rawfilefile.valueProxy
formData.append("file", file.value.raw);
uploadExcelParts(formData).then(res => {
if (res.data.code == 0) {
ElMessage({
message: '导入成功',
type: 'success',
})
//
uploadRef.value.clearFiles()
file.value = undefined
} else {
ElMessage.error(res.data.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('导入错误')
})
}
const previewFile = () => {
}
</script>
<style scoped></style>

View File

@ -0,0 +1,46 @@
import axios from 'axios'
//192.168.16.116
const request = axios.create({
baseURL: 'http://localhost:19990/wms',
timeout: 5000
})
// axios.defaults.baseURL = 'http://192.168.103.202:12315/wms'
// axios.defaults.baseURL = 'http://localhost:12315/wms'
// axios.defaults.baseURL = 'http://192.168.8.21:12315/wms'
// // request 请求器
// // 可以自请求发送前对请求做一些处理
// // 比如统一加token对请求参数统一加密
// request.interceptors.request.use(config => {
// if (config && config.headers) {
// config.headers['Content-Type'] = 'application/json;charset=utf-8';
// }
// // config.headers['token'] = user.token; // 设置请求头
// return config
// }, error => {
// return Promise.reject(error)
// });
// // response 拦截器
// // 可以在接口响应后统一处理结果
// request.interceptors.response.use(
// response => {
// let res = response.data;
// // 如果是返回的文件
// if (response.config.responseType === 'blob') {
// return res
// }
// // 兼容服务端返回的字符串数据
// if (typeof res === 'string') {
// res = res ? JSON.parse(res) : res
// }
// return res;
// },
// error => {
// console.log('err' + error) // for debug
// return Promise.reject(error)
// }
// )
export default request

View File

@ -0,0 +1,311 @@
<template>
<div style="margin-bottom: 10px">
<el-config-provider :locale="zhCn">
<el-row>
<UploadExcelBoxConfig></UploadExcelBoxConfig>
</el-row>
<el-row style="margin-top: 10px;">
<el-input v-model="boxNoQuery" style="width: 256px; margin-right: 10px;" placeholder="料盒号" />
<el-input v-model="stationQuery" style="width: 256px; margin-right: 10px;" placeholder="站台号" />
<el-button type="primary" @click="search()">搜索</el-button>
<el-button type="warning" @click="reset()">重置</el-button>
<el-button type="success" @click="addBoxConfigFunc()">新增配置</el-button>
</el-row>
<br />
<el-table :data="boxConfigs" stripe border v-loading="loading" class="table-class" max-height="650px"
highlight-current-row @row-click="getCurrentRow" :header-cell-style="{ 'text-align': 'center' }"
:cell-style="{ 'text-align': 'center' }">
<el-table-column width="65px" fixed="left">
<template v-slot="scope">
<el-radio :label="scope.row.boxNo" v-model="boxNo">&nbsp;</el-radio>
</template>
</el-table-column>
<el-table-column prop="boxNo" label="料盒号" fixed="left" sortable min-width="120px" />
<el-table-column prop="station" label="站台号" fixed="left" min-width="120px" />
<el-table-column fixed="right" label="操作" width="240px">
<template v-slot="scope">
<el-button plain type="primary" @click="editCurrentBoxConfig(scope.row)">编辑</el-button>
<el-button plain type="danger" @click="deleteCurrentBoxConfig(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<br />
<el-pagination v-model:current-page="currentPage" v-model:page-size="pageSize" :page-sizes="[10, 25, 50]"
:small="false" :disabled="false" :background="false" :default-page-size="10"
layout="total, sizes, prev, pager, next, jumper" :total="total" @size-change="search"
@current-change="search" />
<el-dialog v-model="dialogVisible" title="更新料盒配置" width="40%" draggable :show-close="false">
<el-form ref="configFormRef" :model="configFormEntity" :label-position="labelPosition" label-width="100px"
style="max-width: 100%" :rules="rules" status-icon>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="料盒号" prop="boxNo">
<el-input v-model="configFormEntity.boxNo" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="站台号" prop="station">
<el-select-v2 v-model="configFormEntity.station" placeholder="请选择分配站台"
:options="stationOptions"></el-select-v2>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitUpdateBoxConfig(configFormEntity)">
确定
</el-button>
</span>
</template>
</el-dialog>
<el-dialog v-model="dialogVisibleAdd" title="添加料盒配置" width="40%" draggable :show-close="false">
<el-form ref="configAddFormRef" :model="configAddFormEntity" :label-position="labelPosition"
label-width="100px" style="max-width: 100%" :rules="rules" status-icon>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="料盒号" prop="boxNo">
<el-input v-model="configAddFormEntity.boxNo" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="站台号" prop="station">
<el-select-v2 v-model="configAddFormEntity.station" placeholder="请选择分配站台"
:options="stationOptions"></el-select-v2>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisibleAdd = false">取消</el-button>
<el-button type="primary" @click="submitAddBoxConfig(configAddFormEntity)">
确定
</el-button>
</span>
</template>
</el-dialog>
</el-config-provider>
</div>
</template>
<script setup>
import { queryBoxConfigByPage, updateBoxConfig, addBoxConfig, deleteBoxConfig } from '@/api/config.js'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import { ElMessage } from 'element-plus'
import { ref, reactive } from 'vue'
import UploadExcelBoxConfig from '@/excel/UploadExcelBoxConfig.vue'
</script>
<script>
export default {
name: 'boxConfig',
component: {
UploadExcelBoxConfig
},
data() {
return {
boxConfigs: [],
pageInfo: {},
currentPage: 1,
pageSize: 10,
total: 0,
boxNoQuery: '',
stationQuery: '',
loading: true,
dialogVisible: false,
dialogVisibleAdd: false,
boxNo: '',
labelPosition: 'top',
configFormEntity: reactive({}),
configFormRef: ref(),
configAddFormEntity: reactive({}),
configAddFormRef: ref(),
rules: reactive({}),
stationOptions: [
{
label: '2001',
value: '2001'
},
{
label: '2002',
value: '2002'
},
{
label: '2003',
value: '2003'
},
{
label: '2004',
value: '2004'
},
{
label: '2005',
value: '2005'
},
{
label: '2006',
value: '2006'
},
{
label: '2007',
value: '2007'
},
{
label: '2008',
value: '2008'
}
]
}
},
mounted() {
this.search()
},
methods: {
search() {
this.loading = true
this.pageInfo.pageNum = this.currentPage
this.pageInfo.pageSize = this.pageSize
const tableRequest = {
page: this.pageInfo,
param: {
boxNo: this.boxNoQuery.trim(),
station: this.stationQuery.trim()
},
}
queryBoxConfigByPage(tableRequest).then(res => {
const tableResponse = res.data
if (tableResponse.code != 0) {
ElMessage.error(tableResponse.message)
}
this.boxConfigs = tableResponse.rows
this.total = tableResponse.total
}).catch(err => {
ElMessage.error('查询料盒配置错误' + err.message)
})
this.loading = false
},
reset() {
this.queryKey = ''
this.search
},
editCurrentBoxConfig(row) {
this.configFormEntity = row
this.dialogVisible = true
},
addBoxConfigFunc() {
this.configAddFormEntity = reactive({})
this.dialogVisibleAdd = true
},
deleteCurrentBoxConfig(row) {
this.boxNo = row.boxNo
const boxConfig = {
boxNo: row.boxNo
}
deleteBoxConfig(boxConfig).then(res => {
if (res.data.code == 0) {
ElMessage({
message: '删除料盒配置成功',
type: 'success',
})
this.search()
} else {
ElMessage.error(res.data.message)
}
}).catch(err => {
ElMessage.error('删除料盒配置失败:' + err)
})
},
submitUpdateBoxConfig(formData) {
if (formData.boxNo == null | undefined || formData.station == null | undefined) {
ElMessage({
message: '料盒号和站台号必须输入',
type: 'error',
})
return;
}
updateBoxConfig(formData).then(res => {
if (res.data.code == 0) {
this.dialogVisible = false
ElMessage({
message: '更新料盒配置信息成功',
type: 'success',
})
this.search()
} else {
ElMessage.error(res.data.message)
}
}).catch(err => {
ElMessage.error('更新料盒配置信息失败')
})
},
submitAddBoxConfig(formData) {
if (formData.boxNo == null | undefined || formData.station == null | undefined) {
ElMessage({
message: '料盒号和站台号必须输入',
type: 'error',
})
return;
}
addBoxConfig(formData).then(res => {
if (res.data.code == 0) {
this.dialogVisibleAdd = false
ElMessage({
message: '添加料盒配置成功',
type: 'success',
})
this.search()
} else {
ElMessage.error(res.data.message)
}
}).catch(err => {
ElMessage.error('添加料盒配置失败')
})
},
getCurrentRow(row) {
this.boxNo = row.boxNo
},
},
// watch: {
// currentPage() {
// this.getCurrentPageGoods()
// },
// pageSize() {
// this.getCurrentPageGoods()
// }
// }
}
</script>
<style scoped>
.el-pagination {
padding-left: 5px;
}
.el-row .el-button {
width: 72px;
margin-left: 0px;
margin-right: 5px;
}
.table-class {
width: 100%;
}
.el-row .el-form-item {
width: 10% inherit;
justify-content: center;
}
.el-row .el-form-item .el-select-v2 {
width: 100% !important;
}
.el-row .el-form-item .el-input-number {
width: 100% !important;
}
.el-row .el-form-item .el-button {
margin: auto;
}
</style>

View File

@ -0,0 +1,145 @@
<template>
<el-config-provider :locale="zhCn">
<el-container class="content">
<fieldset class="input-area">
<legend>系统配置</legend>
<div v-for="config in configs">
<el-form :model="config" :label-position="'top'" label-width="100px" style="max-width: 544px"
:rules="rules" status-icon>
<el-row :gutter="16">
<el-col :span="12" :offset="1" v-if="config.configKey == 'MAIL_ADDRESS'">
<el-form-item label="邮箱账户(账户之间用;隔开)">
<div>
<el-input v-model="config.configValue" @change="updateCurrentConfig(config)" />
</div>
</el-form-item>
</el-col>
<el-col :span="12" :offset="1"
v-if="config.configType == '1' && config.configKey != 'MAIL_ADDRESS'">
<el-form-item :label="config.configName">
<div>
<el-input v-model="config.configValue" @change="updateCurrentConfig(config)" />
</div>
</el-form-item>
</el-col>
<el-col :span="12" :offset="1"
v-if="config.configType == '2' && config.configKey != 'MAIL_ADDRESS'">
<el-form-item :label="config.configName">
<div v-if="config.configType == '2'">
<el-select v-model="config.configValue" multiple collapse-tags collapse-tags-tooltip
:placeholder="'请选择' + config.configName" @change="updateCurrentConfig(config)">
<el-option v-for="(value, index) in mails" :key="index" :label="value"
:value="value" />
</el-select>
</div>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
</fieldset>
</el-container>
</el-config-provider>
</template>
<script setup>
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import { getConfigs, updateConfig } from '@/api/config.js'
import { ElMessage, ElLoading } from 'element-plus'
</script>
<script>
export default {
name: 'config',
data() {
return {
configs: [],
mails: [],
rules: {}
}
},
mounted() {
this.getAllConfigs()
},
methods: {
getAllConfigs() {//
const loading = ElLoading.service({
lock: true,
text: 'Loading',
background: 'rgba(0, 0, 0, 0.7)',
})
getConfigs().then(res => {
loading.close()
this.configs = res.data
this.configs.forEach((config) => {
if (config.configType == '2') {
const tempArray = config.configValue.split(';')
config.configValue = tempArray
}
if (config.configKey == 'MAIL_ADDRESS') {
const tempArray = config.configValue.split(';')
this.mails = tempArray
}
})
}).catch(err => {
console.log(err)
loading.close()
ElMessage.error('查询系统配置失败!')
})
},
updateCurrentConfig(config) {//
// config
const param = Object.assign({}, config)
const loading = ElLoading.service({
lock: true,
text: 'Loading',
background: 'rgba(0, 0, 0, 0.7)',
})
if (param.configType == '2') {
param.configValue = param.configValue.join(';')
}
updateConfig(param).then(res => {
loading.close()
if (res.data.code == 0) {
ElMessage({
message: '更新系统配置成功!',
type: 'success',
})
} else {
ElMessage.error(res.data.message)
}
}).catch(err => {
loading.close()
ElMessage.error('更新系统配置失败!')
})
}
}
}
</script>
<style scoped>
.content {
display: flex;
width: 100%;
}
.input-area {
margin: 10px;
width: 100%;
height: 85%;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
}
.el-row .el-form-item .el-select {
width: 512px;
}
.el-row .el-form-item .el-input {
width: 512px;
}
.el-row .el-form-item .el-button {
margin: auto;
}
</style>

View File

@ -0,0 +1,363 @@
<template>
<div style="margin-bottom: 10px">
<el-config-provider :locale="zhCn">
<el-row>
<UploadExcelPart></UploadExcelPart>
</el-row>
<el-row style="margin-top: 10px;">
<el-input v-model="queryKey" style="width: 256px; margin-right: 10px;" placeholder="零件号" />
<el-button type="primary" @click="search()">搜索</el-button>
<el-button type="warning" @click="reset()">重置</el-button>
<el-button type="success" @click="search()">刷新</el-button>
<el-button type="success" @click="exportExcel()">导出信息</el-button>
</el-row>
<br />
<el-table :data="partInfos" stripe border v-loading="loading" class="table-class" max-height="650px"
highlight-current-row @row-click="getCurrentRow" :header-cell-style="{ 'text-align': 'center' }"
:cell-style="{ 'text-align': 'center' }">
<el-table-column width="65px" fixed="left">
<template v-slot="scope">
<el-radio :label="scope.row.material" v-model="material">&nbsp;</el-radio>
</template>
</el-table-column>
<el-table-column prop="material" label="零件号" fixed="left" sortable min-width="120px" />
<el-table-column prop="itemDesc" label="描述" fixed="left" min-width="120px" />
<el-table-column prop="category" label="零件类型" fixed="left" sortable min-width="120px" />
<el-table-column prop="categoryRemark" label="策略" min-width="120px" />
<el-table-column prop="unloadPlace" label="卸货点" min-width="120px" />
<el-table-column prop="kittingPoint" label="配料点" min-width="120px" />
<el-table-column prop="property" label="可用性" min-width="120px" />
<el-table-column prop="vendorId" label="供应商代码" min-width="120px" />
<el-table-column prop="dataOwner" label="数据负责人" min-width="120px" />
<el-table-column prop="partWeight" label="重量" min-width="120px" />
<el-table-column prop="storageLocation" label="库位" min-width="120px" />
<el-table-column prop="storageType" label="存储类型" min-width="120px" />
<el-table-column prop="storageBin" label="BIN位" min-width="120px" />
<el-table-column prop="vendorNameEN" label="供应商名称(英文)" min-width="120px" />
<el-table-column prop="vendorNameCN" label="供应商名称(中文)" min-width="120px" />
<el-table-column prop="vendorCountry" label="供应商国家/地区" min-width="120px" />
<el-table-column prop="SLED" label="SLED" min-width="120px" />
<el-table-column prop="updateDate" label="更新日期" min-width="120px" />
<el-table-column fixed="right" label="操作" width="240px">
<template v-slot="scope">
<el-button plain type="primary" @click="editCurrentRowGoods(scope.row)">编辑</el-button>
<el-button plain type="danger" @click="deleteCurrentRowGoods(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<br />
<el-pagination v-model:current-page="currentPage" v-model:page-size="pageSize" :page-sizes="[10, 25, 50]"
:small="false" :disabled="false" :background="false" :default-page-size="10"
layout="total, sizes, prev, pager, next, jumper" :total="total" @size-change="search"
@current-change="search" />
<el-dialog v-model="dialogVisible" title="物料信息" width="40%" draggable :show-close="false">
<el-form ref="goodsFormRef" :model="goodsFormEntity" :label-position="labelPosition" label-width="100px"
style="max-width: 100%" :rules="rules" status-icon>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="零件号" prop="material">
<el-input v-model="goodsFormEntity.material" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="描述" prop="itemDesc">
<el-input v-model="goodsFormEntity.itemDesc" clearable />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="零件类型" prop="category">
<el-input v-model="goodsFormEntity.category" clearable />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="策略" prop="categoryRemark">
<el-input v-model="goodsFormEntity.categoryRemark" clearable />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="卸货点" prop="unloadPlace">
<el-input v-model="goodsFormEntity.unloadPlace" clearable />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="配料点" prop="kittingPoint">
<el-input v-model="goodsFormEntity.kittingPoint" clearable />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="可用性" prop="property">
<el-input v-model="goodsFormEntity.property" clearable />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="供应商代码" prop="vendorId">
<el-input v-model="goodsFormEntity.vendorId" clearable />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="数据负责人" prop="dataOwner">
<el-input v-model="goodsFormEntity.dataOwner" clearable />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="重量" prop="partWeight">
<el-input v-model="goodsFormEntity.partWeight" clearable />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="库位" prop="storageLocation">
<el-input v-model="goodsFormEntity.storageLocation" clearable />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="存储类型" prop="storageType">
<el-input v-model="goodsFormEntity.storageType" clearable />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="BIN位" prop="storageBin">
<el-input v-model="goodsFormEntity.storageBin" clearable />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="供应商名称(英文)" prop="vendorNameEN">
<el-input v-model="goodsFormEntity.vendorNameEN" clearable />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="供应商名称(中文)" prop="vendorNameCN">
<el-input v-model="goodsFormEntity.vendorNameCN" clearable />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="供应商国家/地区" prop="vendorCountry">
<el-input v-model="goodsFormEntity.vendorCountry" clearable />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="SLED" prop="SLED">
<el-input-number v-model.number="goodsFormEntity.SLED" clearable controls-position="right"
:min="0" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="更新日期" prop="updateDate">
<el-input v-model="goodsFormEntity.updateDate" clearable />
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitGoodsInfo(goodsFormEntity)">
确定
</el-button>
</span>
</template>
</el-dialog>
</el-config-provider>
</div>
</template>
<script setup>
import { getPartInfo, updatePartInfo, deleteCurrentPartInfo } from '@/api/goods.js'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import { ElMessage } from 'element-plus'
import { ref, reactive } from 'vue'
import { dateFormatter } from '@/utils/formatter.js'
import UploadExcelPart from '@/excel/UploadExcelPart.vue'
import { downloadMaterialExcel } from '@/api/excel.js'
</script>
<script>
export default {
name: 'goods',
data() {
return {
partInfos: [],
pageInfo: {},
currentPage: 1,
pageSize: 10,
total: 0,
queryKey: '',
loading: true,
dialogVisible: false,
material: '',
goodsFormEntity: reactive({}),
labelPosition: 'top',
goodsFormRef: ref(),
rules: reactive({})
}
},
mounted() {
this.search()
},
methods: {
search() {
this.loading = true
this.pageInfo.pageNum = this.currentPage
this.pageInfo.pageSize = this.pageSize
const tableRequest = {
page: this.pageInfo,
param: {
material: this.queryKey.trim()
},
}
getPartInfo(tableRequest).then(res => {
const tableResponse = res.data
if (tableResponse.code != 0) {
console.log(tableResponse.code + ':' + tableResponse.message)
ElMessage.error(tableResponse.message)
}
this.partInfos = tableResponse.rows
this.total = tableResponse.total
}).catch(err => {
ElMessage.error('查询物料错误' + err.message)
})
this.loading = false
},
dateFormat: (row, column, cellValue, index) => {
return dateFormatter(cellValue)
},
reset() {
this.queryKey = ''
this.search
},
// getCurrentPageGoods() {
// this.currentGoods = this.displayGoods.slice((this.currentPage - 1) * this.pageSize, this.currentPage * this.pageSize)
// },
editCurrentRowGoods(row) {
this.goodsFormEntity = row
this.dialogVisible = true
},
deleteCurrentRowGoods(row) {
this.material = row.material
const goods = {
material: row.material
}
deleteCurrentPartInfo(goods).then(res => {
if (res.data.code == 0) {
ElMessage({
message: '删除零件信息成功',
type: 'success',
})
this.search()
} else {
ElMessage.error(res.data.message)
}
}).catch(err => {
ElMessage.error('删除零件信息失败:' + err)
})
},
submitGoodsInfo(formData) {
updatePartInfo(formData).then(res => {
if (res.data.code == 0) {
this.dialogVisible = false
ElMessage({
message: '更新零件信息成功',
type: 'success',
})
this.search()
} else {
ElMessage.error(res.data.message)
}
}).catch(err => {
ElMessage.error('更新零件信息失败')
})
},
getCurrentRow(row) {
this.goodsId = row.goodsId
},
exportExcel() {
downloadMaterialExcel().then(res => {
const link = document.createElement('a');//a
try {
// let blob = new Blob([res.data],{type: 'application/vnd.ms-excel'}); //blobblobtypexls
let blob = res.data //blob
// let _fileName = res.headers['content-disposition'].split(';')[1].split('=')[1]; //
let _fileName = "导出物料信息" + dateFormatter(new Date) + ".xlsx"
link.style.display = 'none'//
// URL
const url = window.URL || window.webkitURL || window.moxURL
link.href = url.createObjectURL(blob)
link.setAttribute('download', _fileName.substring(_fileName.lastIndexOf('_') + 1))
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
url.revokeObjectURL(link.href)//url
} catch (e) {
ElMessage({
message: '下载文件失败:: ' + e,
type: 'error',
showClose: true
})
}
}).catch(err => {
ElMessage({
message: '导出失败:: ' + err,
type: 'error',
showClose: true
})
})
},
},
// watch: {
// currentPage() {
// this.getCurrentPageGoods()
// },
// pageSize() {
// this.getCurrentPageGoods()
// }
// }
}
</script>
<style scoped>
.el-pagination {
padding-left: 5px;
}
.el-row .el-button {
width: 72px;
margin-left: 0px;
margin-right: 5px;
}
.table-class {
width: 100%;
}
.el-row .el-form-item {
width: 10% inherit;
justify-content: center;
}
.el-row .el-form-item .el-select-v2 {
width: 100% !important;
}
.el-row .el-form-item .el-input-number {
width: 100% !important;
}
.el-row .el-form-item .el-button {
margin: auto;
}
</style>

View File

@ -0,0 +1,293 @@
<template>
<el-config-provider :locale="localLanguage">
<div style="width: calc(100vw - 300px)">
<div style="border-radius: 5px; border: #2c3e5033 solid 1px; padding: 10px; calc(100vw - 300px)"><!-- 搜索-->
<el-row style="width: 100%">
<el-form :model="searchParams" label-width="120" label-position="left" >
<el-form-item style="width: 600px" label="查询关键字:">
<el-input placeholder="输入 料箱号/库位/任务号 查询..." v-model="searchParams.searchStr" clearable></el-input>
</el-form-item>
<el-form-item style="width: 600px" label="任务状态:">
<el-select style="width: 600px" v-model="searchParams.orderStatus" multiple placeholder="请选择需要查询的任务状态">
<el-option v-for="item in orderInEnum" :key="item.value" :label="item.label" :value="item.value"/>
</el-select>
</el-form-item>
</el-form>
</el-row>
<el-row>
<el-button type="primary" @click="queryGoodsOrderIn">查询入库单</el-button>
<el-button type="success" @click="showBindingGoods = true">下发入库任务</el-button>
</el-row>
</div>
<div> <!-- 表格-->
<el-row style="width: calc(100vw - 300px)">
<h5>入库单</h5>
<el-table :data="goodsOrderInList" border stripe max-height="calc(100vh - 550px)">
<el-table-column fixed prop="rowId" label="识别号" width="130px" align="center" show-overflow-tooltip/>
<el-table-column fixed prop="guid" label="GUID" width="200px" align="center" show-overflow-tooltip/>
<el-table-column prop="inType" label="入库类型" width="100px" align="center" show-overflow-tooltip/>
<el-table-column prop="batchNo" label="批次" width="120px" align="center" show-overflow-tooltip/>
<el-table-column prop="vehicleNo" label="载具号" width="100px" align="center" show-overflow-tooltip/>
<el-table-column prop="goodsId" label="物料号" width="120px" align="center" show-overflow-tooltip/>
<el-table-column prop="goodsNum" label="物料数量" width="120px" align="center" show-overflow-tooltip/>
<el-table-column prop="wareHouse" label="库别" width="100px" align="center" show-overflow-tooltip/>
<el-table-column prop="orderStatus" label="入库单状态" width="95px" align="center">
<template #default="scope">
<el-tag class="ml-2" :type=formatterOrderInEnum(scope.row.orderStatus).type>
{{formatterOrderInEnum(scope.row.orderStatus).label }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="createPerson" label="创建人" width="100px" align="center" show-overflow-tooltip/>
<el-table-column prop="createTime" label="创建时间" :formatter="formatCellValueTime" width="180px"
align="center" show-overflow-tooltip/>
<el-table-column prop="updateTime" label="更新时间" :formatter="formatCellValueTime" width="180px" align="center" show-overflow-tooltip/>
<el-table-column prop="remark" label="备注" show-overflow-tooltip min-width="120px"/>
<el-table-column fixed="right" label="操作" align="center" width="190">
<template #default="scope">
<el-button-group class="ml-4">
<!-- <el-tooltip content="解绑" placement="top" effect="light">
<el-button type="warning" size="small" @click="unBindingOrder(scope.row)">
<el-icon><Close /></el-icon>
</el-button>
</el-tooltip> -->
<el-tooltip content="更新数量" placement="top" effect="light">
<el-button type="success" size="small" @click="updateGoodsNum(scope.row)">
<el-icon><Edit/></el-icon>
</el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top" effect="light">
<el-button type="danger" size="small" @click="deleteOrder(scope.row)">
<el-icon><Delete/></el-icon>
</el-button>
</el-tooltip>
</el-button-group>
</template>
</el-table-column>
</el-table>
<!-- 对话框部分 -->
<el-dialog v-model="dialogVisible" title="更新数量" width="40%" @close="resetForm">
<el-form ref="updateFormRef" :model="updateFormEntity" :rules="rules" status-icon>
<el-form-item label="识别号" prop="rowId">
<el-input v-model="updateFormEntity.rowId" readonly />
</el-form-item>
<el-form-item label="实际数量" prop="realNum">
<el-input-number v-model.number="updateFormEntity.realNum" controls-position="right" :min="0" clearable />
</el-form-item>
<!-- 其他表单项 -->
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitUpdate">确认</el-button>
</span>
</el-dialog>
</el-row>
</div>
</div>
<!-- 绑定物料框-->
<BindingGoods v-model="showBindingGoods"></BindingGoods>
</el-config-provider>
</template>
<script>
import { Delete, Close, Edit } from "@element-plus/icons-vue";
import apiOrderIn from '@/api/order.in';
import {ElMessage, ElMessageBox} from 'element-plus'
import stock from '@/layout/stock.vue'
import {formatterOrderInEnum, orderInEnum} from "@/enum/order.in.enum";
import {formatCellValueTime} from "@/utils/formatter";
import zhCn from 'element-plus/dist/locale/zh-cn.mjs';
import en from 'element-plus/dist/locale/en.mjs';
import {ref} from "vue";
import BindingGoods from "@/components/BindingGoods.vue";
const language = ref('zh-cn');
export default {
name: 'goodsIn',
computed: {
orderInEnum() {
return orderInEnum
},
localLanguage: () => (language.value === 'zh-cn' ? zhCn : en)
},
components: {BindingGoods, Delete, Close, Edit },
data() {
return {
//
searchParams: {
searchStr: '',
orderStatus: [0,1,2]
},
//
showBindingGoods: false,
//
dialogVisible: false,
updateFormEntity: {
rowId: '',
realNum: 0
//
},
rules: {
//
},
tableData: [], //
//
goodsOrderInList: []
}
},
mounted() {},
methods: {
formatCellValueTime,
formatterOrderInEnum,
//
queryGoodsOrderIn() {
this.goodsOrderInList = [];
apiOrderIn.getOrderInList(this.searchParams).then(res => {
const responseData = res.data
if (responseData.code === 0) {
//
ElMessage({
message: '查询成功',
type: 'success',
});
this.goodsOrderInList = responseData['returnData'];
} else {
//
ElMessageBox.alert(`服务器返回失败:${responseData.msg}`, '查询失败', {
type: 'warning',
confirmButtonText: '确定',
showClose: false
})
}
}).catch(err => {
//
ElMessageBox.alert(`请求服务器失败::${err}`, '任务添加失败', {
type: 'warning',
confirmButtonText: '确定'
})
})
},
//
deleteOrder(row) {
ElMessageBox.confirm('确定执行删除吗?','提示')
.then(() => {
apiOrderIn.deleteOrderIn(row.rowId).then(res => {
const responseData = res.data;
if (responseData.code === 0) {
//
ElMessage({
message: '删除成功',
type: 'success',
});
this.queryGoodsOrderIn();
} else {
//
ElMessageBox.alert(`服务器返回失败:${responseData.message}`, '删除失败', {
type: 'warning',
confirmButtonText: '确定',
showClose: false
})
}
}).catch(err => {
//
ElMessageBox.alert(`请求服务器失败::${err}`, '任务添加失败', {
type: 'warning',
confirmButtonText: '确定'
})
})
})
.catch(() => {
})
},
//
updateGoodsNum(row) {
this.dialogVisible = true;
this.updateFormEntity = row;
},
test() {
console.log({rowId:this.updateFormEntity.rowId,realNum:this.updateFormEntity.realNum,orderStatus:this.updateFormEntity.orderStatus});
},
//
submitUpdate(){
if(this.updateFormEntity.realNum === 0){
ElMessage({
message: '数量不能为0',
type: 'error',
});
return;
}
if(this.updateFormEntity.orderStatus === 1){
ElMessage({
message: '正在入库的订单不能更新数量',
type: 'error',
});
return;
}
apiOrderIn.updateForNum({rowId:this.updateFormEntity.rowId,realNum:this.updateFormEntity.realNum}).then(res => {
const responseData = res.data
if (responseData.code === 0) {
//
ElMessage({
message: '更新成功',
type: 'success',
});
this.queryGoodsOrderIn();
}else {
//
ElMessageBox.alert(`服务器返回失败:${responseData.message}`, '更新失败', {
type: 'warning',
confirmButtonText: '确定',
showClose: false
})
}
}).catch(err => {
//
ElMessageBox.alert(`请求服务器失败::${err}`, '任务添加失败', {
type: 'warning',
confirmButtonText: '确定'
})
})
},
//
unBindingOrder(row) {
ElMessageBox.confirm('你确定要解绑该吗','提示')
.then(() => {
apiOrderIn.unbindingVehicle(row.rowId).then(res => {
const responseData = res.data
if (responseData.code === 0) {
//
ElMessage({
message: '解绑成功',
type: 'success',
});
this.queryGoodsOrderIn();
} else {
//
ElMessageBox.alert(`服务器返回失败:${responseData.message}`, '解绑失败', {
type: 'warning',
confirmButtonText: '确定',
showClose: false
})
}
}).catch(err => {
//
ElMessageBox.alert(`请求服务器失败::${err}`, '任务添加失败', {
type: 'warning',
confirmButtonText: '确定'
})
})
})
.catch(() => {
})
}
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,407 @@
<template>
<el-config-provider :locale="zhCn">
<el-container class="content">
<fieldset class="input-area">
<legend style="font-size: xxx-large;">入库界面</legend>
<el-form ref="taskInRequestRef" :model="taskInRequestEntity" :label-position="labelPosition"
label-width="100px" style="max-width: 100%" :rules="rules" status-icon size="large">
<el-row>
<el-col :span="22" :offset="1">
<el-form-item label="是否入空托" prop="isEmpty">
<el-select-v2 v-model="taskInRequestEntity.isEmpty" placeholder="请选择入库类型"
:options="stockTypeOptions"
@change="autoCompleteEmptyInfo(taskInRequestEntity)"></el-select-v2>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="22" :offset="1">
<el-form-item label="箱号" prop="vehicleNo">
<el-input v-model="taskInRequestEntity.vehicleNo" ref="vehicleNo" clearable
style="height: 50px;" v-on:keyup.tab="detectEndInputVehicleNo(taskInRequestEntity)" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="22" :offset="1">
<el-form-item label="零件号" prop="goodsId">
<el-input v-model="taskInRequestEntity.goodsId" ref="goodsId" clearable
:disabled="disabledEmpty" @blur="queryAndAutoComplete(taskInRequestEntity)"
style="height: 50px;" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="22" :offset="1">
<el-form-item label="零件名称" prop="goodsName">
<el-input v-model="taskInRequestEntity.goodsName" clearable readonly
style="height: 50px;" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="22" :offset="1">
<el-form-item label="零件数量" prop="goodsNum">
<el-input-number v-model.number="taskInRequestEntity.goodsNum" ref="goodsNum" clearable
:disabled="disabledEmpty" controls-position="right" :min="1"
@blur="detectEndInputNum(taskInRequestEntity)" style="height: 50px;"></el-input-number>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="22" :offset="1">
<el-form-item label="零件重量(千克)" prop="weight">
<el-input v-model="taskInRequestEntity.weight" clearable readonly style="height: 50px;" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="22" :offset="1" v-show="disPlayDateFlag">
<el-form-item label="有效期(年)" prop="shelfLife">
<!-- // TODO -->
<el-input v-model="taskInRequestEntity.shelfLife" clearable readonly
style="height: 50px;" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="22" :offset="1" v-show="disPlayDateFlag">
<el-form-item label="生产日期" prop="productionDate">
<el-date-picker v-model="taskInRequestEntity.productionDate" ref="productionDate"
:disabled="disabledEmpty" style="width: 100%;height: 75px;" type="date"
placeholder="请选择生产日期" :editable="false" size="large" clearable />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="4" class="btn-area">
<el-col :span="8" :offset="0">
<el-form-item>
<el-button type="primary" round
@click="addTempTasks(taskInRequestRef, taskInRequestEntity)">绑定信息</el-button>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item>
<el-button type="success" round
@click="submitGoodsInTask(taskInRequestRef)">下发任务</el-button>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item>
<el-button type="warning" round @click="callEmptyVehicles(taskInRequestEntity)">请求空箱</el-button>
</el-form-item>
</el-col>
</el-row>
</el-form>
</fieldset>
<div ref="btnArea"></div>
</el-container>
</el-config-provider>
</template>
<script setup>
import store from '@/store'
import { sendGoodsInTask, callEmptyVehicle } from '@/api/task'
import { queryPartInfoByPartNo } from '@/api/goods'
import { reactive, ref } from 'vue'
import { ElMessage } from 'element-plus'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import UploadExcelPart from '@/excel/UploadExcelPart.vue'
const taskInRequestRef = ref()
const taskInRequestEntity = reactive({
vehicleNo: '',//
goodsId: '',//
goodsName: '',//
goodsNum: 1,//
weight: 0,//
shelfLife: 0,//
productionDate: '',//
isEmpty: '1',
userName: store.getters.getUserName//
})
const rules = reactive({
vehicleNo: [
{ required: true, message: '请输入载具编号' }
],
goodsId: [
{ required: true, message: '请输入物料编号' }
],
goodsNum: [
{ required: true, message: '请输入数量' },
{ type: 'number', message: '请输入数字' }
]
})
const labelPosition = "top"
</script>
<script>
export default {
name: 'goodsInPda',
components: {
UploadExcelPart
},
data() {
return {
tempTasks: [],
tempVehicleNo: '',
disPlayDateFlag: false,
currentPartInfo: {},
stockTypeOptions: [
{
value: '0',
label: '空箱入库'
},
{
value: '1',
label: '带料入库'
}
],
disabledEmpty: false,
totalWeight: 0,
isOverWeight: false
}
},
mounted() {
this.$refs.vehicleNo.focus()
},
methods: {
//
queryAndAutoComplete(taskInRequestEntity) {
this.loading = true
const param = { material: taskInRequestEntity.goodsId }
queryPartInfoByPartNo(param).then(res => {
console.log(res)
if (res.data.code == 0) {
this.currentPartInfo = res.data.returnData
taskInRequestEntity.goodsName = this.currentPartInfo.itemDesc
this.calWeight(taskInRequestEntity)
if (this.currentPartInfo.SLED > 0) {//
this.disPlayDateFlag = true
taskInRequestEntity.shelfLife = this.currentPartInfo.SLED
} else {
this.disPlayDateFlag = false
taskInRequestEntity.shelfLife = 0
taskInRequestEntity.productionDate = ''
}
taskInRequestEntity.goodsNum = ''
this.$refs.goodsNum.focus()
} else {
taskInRequestEntity.goodsName = ''
taskInRequestEntity.goodsNum = ''
taskInRequestEntity.weight = 0
this.disPlayDateFlag = false
taskInRequestEntity.shelfLife = 0
taskInRequestEntity.productionDate = ''
ElMessage.error(res.data.message)
}
}).catch(err => {
taskInRequestEntity.goodsName = ''
taskInRequestEntity.goodsNum = ''
taskInRequestEntity.weight = 0
this.disPlayDateFlag = false
taskInRequestEntity.shelfLife = 0
taskInRequestEntity.productionDate = ''
ElMessage.error('查询物料信息错误' + err.message)
})
this.loading = false
},
calWeight(taskInRequestEntity) {
taskInRequestEntity.weight = this.currentPartInfo.partWeight * taskInRequestEntity.goodsNum
this.totalWeight = this.totalWeight + taskInRequestEntity.weight
if (this.totalWeight > 30) {
this.isOverWeight = true
ElMessage({
message: '箱子重量超过30kg',
type: 'warning',
})
}
},
autoCompleteEmptyInfo(taskInRequestEntity) {//
if (taskInRequestEntity.isEmpty == '0') {//
taskInRequestEntity.goodsId = '000000000'
taskInRequestEntity.batchNo = '000000000'
taskInRequestEntity.goodsNum = 1
taskInRequestEntity.weight = 0
taskInRequestEntity.shelfLife = 0
taskInRequestEntity.productionDate = ''
this.currentPartInfo = {}
this.disabledEmpty = true
this.disPlayDateFlag = false
} else {
taskInRequestEntity.goodsId = ''
taskInRequestEntity.batchNo = ''
taskInRequestEntity.goodsNum = 1
this.disabledEmpty = false
}
this.$refs.vehicleNo.focus()
},
addTempTasks(formEl, formData) {//
if (!formEl) return
formEl.validate((valid) => {
if (!valid) {
ElMessage({
message: '请输入必须的入库信息!',
type: 'warning',
})
return
}
if (this.tempVehicleNo !== '' && this.tempVehicleNo !== formData.vehicleNo) {
ElMessage({
message: '载具编号不一致,请确认后重新输入!',
type: 'warning',
})
return
}
if (this.tempVehicleNo != '' && formData.isEmpty == '0') {
ElMessage({
message: '此箱子已经绑定过,请下发。',
type: 'warning',
})
return
}
if (this.isOverWeight) {
ElMessage({
message: '已超重,不可继续绑定,请移除此物料,并下发任务',
type: 'error',
showClose: true
})
return
}
this.tempVehicleNo = formData.vehicleNo
formData.userName = store.getters.getUserName
this.tempTasks.push(Object.assign({}, formData))
formEl.resetFields()
this.disabledEmpty = false
formData.vehicleNo = this.tempVehicleNo
this.currentPartInfo = {}
ElMessage({
message: '绑定成功!',
type: 'success',
})
})
},
submitGoodsInTask(formEl) {//
if (this.tempTasks.length == 0) {
ElMessage.error("未绑定任何信息")
}
sendGoodsInTask(this.tempTasks).then(res => {
console.log(res)
if (res.data.code == 0) {
this.tempTasks = []
this.tempVehicleNo = ''
formEl.resetFields()
this.disPlayDateFlag = false
this.disabledEmpty = false
this.currentPartInfo = {}
this.totalWeight = 0
this.isOverWeight = false
ElMessage({
message: '下发任务成功',
type: 'success'
})
this.$refs.vehicleNo.focus()
} else {
ElMessage.error(res.data.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('创建入库任务错误!' + err.message)
})
},
resetForm(formEl) {//
if (!formEl) return
formEl.resetFields()
this.tempTasks = []
this.tempVehicleNo = ''
this.currentPartInfo = {}
this.disPlayDateFlag = false
},
callEmptyVehicles(taskInRequestEntity) {
callEmptyVehicle(taskInRequestEntity).then(res => {
if (res.data.code == 0) {
ElMessage({
message: res.data.message,
type: 'success'
})
} else {
ElMessage.error(res.data.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('呼叫空箱错误' + err.message)
})
},
deleteRowTask(row) {//
this.tempTasks.splice(this.tempTasks.indexOf(row), 1)
if (this.tempTasks.length == 0) {
this.tempVehicleNo = ''
}
},
detectEndInputVehicleNo(taskInRequestEntity) {
if (taskInRequestEntity.isEmpty == '0') {//
this.$refs.btnArea.scrollIntoView();
// this.$refs.vehicleNo.blur()
} else {
this.$refs.goodsId.focus()
}
},
detectEndInputNum(taskInRequestEntity) {
this.calWeight(taskInRequestEntity)
}
}
}
</script>
<style scoped>
.content {
display: flex;
width: 100%;
}
.el-row {
margin: 20px 0;
}
:deep(.el-form-item__label) {
font-size: x-large;
/* margin: 10px; */
padding: 10px 0;
}
:deep(.el-select-v2--large .el-select-v2__placeholder) {
font-size: 25px;
}
.el-row .el-form-item {
justify-content: center;
}
.el-row .el-form-item .el-select {
width: 100% !important;
}
.el-row .el-form-item .el-select-v2 {
width: 100% !important;
}
.el-row .el-form-item .el-input-number {
width: 100% !important;
}
.el-row .el-form-item .el-button {
width: 80px;
height: 50px;
margin: auto;
font-size: small;
}
.input-area {
margin: 10px;
width: 1080px;
/* height: 730px; */
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
}
</style>

View File

@ -0,0 +1,216 @@
<template>
<el-config-provider :locale="localLanguage">
<div style="width: calc(100vw - 300px)">
<div style="border-radius: 5px; border: #2c3e5033 solid 1px; padding: 10px; calc(100vw - 300px)"><!-- 搜索-->
<el-row style="width: 100%">
<el-form :model="searchParams" label-width="120" label-position="left" >
<el-form-item style="width: 600px" label="查询关键字:">
<el-input placeholder="输入 料箱号/库位/任务号 查询..." v-model="searchParams.searchStr" clearable></el-input>
</el-form-item>
<el-form-item style="width: 600px" label="任务状态:">
<el-select style="width: 600px" v-model="searchParams.orderStatus" multiple placeholder="请选择需要查询的任务状态">
<el-option v-for="item in orderOutEnum" :key="item.value" :label="item.label" :value="item.value"/>
</el-select>
</el-form-item>
</el-form>
</el-row>
<el-row>
<el-button type="primary" @click="queryGoodsOrderOut">查询出库单</el-button>
<el-button type="success" @click="showhandOut = true">下发出库任务</el-button>
<el-button type="success" @click="emptyhandOut = true">空托盘出库</el-button>
</el-row>
</div>
<div> <!-- 表格-->
<el-row style="width: calc(100vw - 300px)">
<h5>出库单</h5>
<el-table :data="goodsOrderOutList" border stripe max-height="calc(100vh - 550px)">
<el-table-column fixed prop="rowId" label="行号" width="130px" align="center" show-overflow-tooltip/>
<el-table-column fixed prop="recordId" label="识别号" width="130px" align="center" show-overflow-tooltip/>
<el-table-column fixed prop="orderId" label="订单号" width="200px" align="center" show-overflow-tooltip/>
<el-table-column prop="warehouseOrigin" label="源库别" width="100px" align="center" show-overflow-tooltip/>
<el-table-column prop="warehouseDestination" label="托盘号" width="120px" align="center" show-overflow-tooltip/>
<el-table-column prop="orderType" label="订单类型" width="100px" align="center" show-overflow-tooltip/>
<el-table-column prop="goodsId" label="物料号" width="120px" align="center" show-overflow-tooltip/>
<el-table-column prop="deliveryTime" label="需求时间" width="120px" align="center" show-overflow-tooltip/>
<el-table-column prop="rowNo" label="行号" width="100px" align="center" show-overflow-tooltip/>
<el-table-column prop="goodsId" label="物料编号" width="100px" align="center" show-overflow-tooltip/>
<el-table-column prop="goodsNum" label="物料数量" width="100px" align="center" show-overflow-tooltip/>
<el-table-column prop="unit" label="单位" width="100px" align="center" show-overflow-tooltip/>
<el-table-column prop="status" label="出库单状态" width="95px" align="center">
<template #default="scope">
<el-tag class="ml-2" :type=formatterOrderOutEnum(scope.row.status).type>
{{formatterOrderOutEnum(scope.row.status).label }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="createTime" label="创建时间" :formatter="formatCellValueTime" width="180px"
align="center" show-overflow-tooltip/>
<el-table-column prop="remark" label="备注" show-overflow-tooltip min-width="120px" fixed="right"/>
<el-table-column fixed="right" label="操作" align="center" width="140">
<template #default="scope">
<el-button-group class="ml-4">
<el-tooltip content="执行出库" placement="top" effect="light">
<el-button type="success" size="small" @click="executeOut(scope.row)">
<el-icon><Check /></el-icon>
</el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top" effect="light">
<el-button type="danger" size="small" @click="deleteOrder(scope.row)">
<el-icon><Delete/></el-icon>
</el-button>
</el-tooltip>
</el-button-group>
</template>
</el-table-column>
</el-table>
</el-row>
</div>
</div>
<HandOut v-model="showhandOut"/>
<emptyHandOut v-model="emptyhandOut"/>
</el-config-provider>
</template>
<script>
import {taskStatusFormatter, dueFormatter, formatCellValueTime} from '@/utils/formatter.js'
import HandOut from '@/components/handOut.vue'
import emptyHandOut from '@/components/emptyHandOut.vue'
import { reactive, ref } from 'vue'
import {ElMessage, ElMessageBox} from 'element-plus'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs';
import en from 'element-plus/dist/locale/en.mjs';
import {Check, Delete} from "@element-plus/icons-vue";
import {formatterOrderOutEnum, orderOutEnum} from "@/enum/order.out.enum";
const language = ref('zh-cn');
import apiOrderOut from '@/api/order.out'
export default {
name: 'goodsOut',
components: {Check, Delete, HandOut,emptyHandOut},
data() {
return {
//
searchParams: {
searchStr: '',
orderStatus: [0,1]
},
//
showhandOut: false,
//
emptyhandOut: false,
//
goodsOrderOutList: []
}
},
mounted() {
},
beforeUnmount() {
},
methods: {
formatCellValueTime,
formatterOrderOutEnum,
//
queryGoodsOrderOut() {
this.goodsOrderOutList = [];
apiOrderOut.getOrderOutList(this.searchParams).then(res => {
const responseData = res.data;
if (responseData.code === 0) {
//
ElMessage({
message: '查询成功',
type: 'success',
});
this.goodsOrderOutList = responseData['returnData'];
} else {
//
ElMessageBox.alert(`服务器返回失败:${responseData.message}`, '查询失败', {
type: 'warning',
confirmButtonText: '确定',
showClose: false
})
}
}).catch(err => {
//
ElMessageBox.alert(`请求服务器失败::${err}`, '任务添加失败', {
type: 'warning',
confirmButtonText: '确定'
})
})
},
//
deleteOrder(row) {
ElMessageBox.confirm('是否删除该出库单?','提示')
.then(() => {
apiOrderOut.deleteOrder(row.rowId).then(res => {
const responseData = res.data;
if (responseData.code === 0) {
//
ElMessage({
message: '删除成功',
type: 'success',
});
this.queryGoodsOrderOut();
} else {
//
ElMessageBox.alert(`服务器返回失败:${responseData.message}`, '删除失败', {
type: 'warning',
confirmButtonText: '确定',
showClose: false
})
}
}).catch(err => {
//
ElMessageBox.alert(`请求服务器失败::${err}`, '任务删除失败', {
type: 'warning',
confirmButtonText: '确定'
})
})
})
.catch(() => {
})
},
//
executeOut(row) {
ElMessageBox.confirm(`是否执行 ${row.rowId} 的出库?`, '提示')
.then(() => {
apiOrderOut.executeOut(row.rowId).then(res => {
const responseData = res.data;
if (responseData.code === 0) {
//
ElMessage({
message: '执行成功',
type: 'success',
});
this.queryGoodsOrderOut();
} else {
//
ElMessageBox.alert(`服务器返回失败:${responseData.message}`, '执行失败', {
type: 'warning',
confirmButtonText: '确定',
showClose: false
})
}
}).catch(err => {
//
ElMessageBox.alert(`请求服务器失败::${err}`, '任务添加失败', {
type: 'warning',
confirmButtonText: '确定'
})
})
})
.catch(() => {
})
}
},
computed: {
orderOutEnum() {
return orderOutEnum
},
localLanguage: () => (language.value === 'zh-cn' ? zhCn : en)
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,178 @@
<template>
<div style="margin-bottom: 15px">
<el-config-provider :locale="zhCn">
<el-row>
<el-input v-model="goodsIdQuery" style="width: 256px; margin-right: 10px;" placeholder="零件号" />
<el-input v-model="vehicleNoQuery" style="width: 256px; margin-right: 10px;" placeholder="箱号" />
<el-button type="primary" @click="search()">搜索</el-button>
<el-button type="warning" @click="reset()">重置</el-button>
<el-button type="success" @click="search()">刷新</el-button>
<el-button type="success" @click="exportExcel()">导出记录</el-button>
</el-row>
<br />
<el-table :data="tasks" stripe border v-loading="loading" style="width: 100%" max-height="684px"
class="table-class" :header-cell-style="{ 'text-align': 'center' }"
:cell-style="{ 'text-align': 'center' }">
<el-table-column prop="goodsId" label="零件号" fixed="left" min-width="120px" />
<el-table-column prop="vehicleNo" label="箱号" fixed="left" min-width="120px" />
<el-table-column prop="goodsName" label="零件名称" min-width="120px" />
<el-table-column prop="taskType" label="任务类型" :formatter="taskTypeFormat" min-width="120px" />
<el-table-column prop="taskGroup" label="任务组" min-width="120px" />
<el-table-column prop="origin" label="起点" min-width="120px" />
<el-table-column prop="destination" label="终点" min-width="120px" />
<el-table-column prop="pickStand" label="拣选站台" min-width="120px" />
<el-table-column prop="weight" label="重量" min-width="120px" />
<el-table-column prop="productionDate" label="生产日期" :formatter="dateFormat" min-width="120px" />
<el-table-column prop="expirationDate" label="有效日期" :formatter="dateFormat" min-width="120px" />
<el-table-column prop="operateNum" label="操作数量" min-width="120px" />
<el-table-column prop="totalNum" label="库存数量" min-width="120px" />
<el-table-column prop="taskPriority" label="任务优先级" min-width="120px" />
<el-table-column prop="kateTaskId" label="配件任务号" min-width="140px" />
<el-table-column prop="userName" label="操作人员姓名" min-width="120px" />
<el-table-column prop="createTime" label="创建时间" :formatter="timeFormat" min-width="120px" />
<el-table-column prop="finishTime" label="任务完成时间" :formatter="timeFormat" min-width="120px" />
<el-table-column prop="taskStatus" label="任务状态" fixed="right" :formatter="taskStatusFormat"
min-width="120px" />
</el-table>
<br />
<el-pagination v-model:current-page="currentPage" v-model:page-size="pageSize" :page-sizes="[10, 25, 50]"
:small="false" :disabled="false" :background="false" :default-page-size="10"
layout="total, sizes, prev, pager, next, jumper" :total="total" @size-change="search"
@current-change="search" />
</el-config-provider>
</div>
</template>
<script setup>
import { getTaskRecords } from '@/api/record.js'
import { dateFormatter, taskStatusFormatter, timeFormatter } from '@/utils/formatter.js'
import { downloadRukuExcel } from '@/api/excel.js'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import { ElMessage } from 'element-plus'
import store from '@/store'
</script>
<script>
export default {
name: 'inTaskRecord',
data() {
return {
pageInfo: {},
tasks: [],
currentPage: 1,
pageSize: 10,
total: 0,
goodsIdQuery: '',
vehicleNoQuery: '',
loading: true
}
},
mounted() {
this.search()
},
methods: {
dateFormat: (row, column, cellValue, index) => {
return dateFormatter(cellValue)
},
timeFormat: (row, column, cellValue, index) => {
return timeFormatter(cellValue)
},
taskStatusFormat: (row, column, cellValue, index) => {
return taskStatusFormatter(cellValue)
},
taskTypeFormat: (row, column, cellValue, index) => {
switch (cellValue) {
case 1:
if (row.taskId.substr(0, 2) == 'HK') {
return '回库'
} else {
return '入库'
}
case 2: return '出库'
case 3: return '盘点'
default: return '未知'
}
},
search() {
this.loading = true
this.pageInfo.pageNum = this.currentPage
this.pageInfo.pageSize = this.pageSize
const tableRequest = {
page: this.pageInfo,
param: {
taskType: 1,
goodsId: this.goodsIdQuery.trim(),
vehicleNo: this.vehicleNoQuery.trim(),
userName: store.getters.getUserName
}
}
getTaskRecords(tableRequest).then(res => {
const tableResponse = res.data
if (tableResponse.code != 0) {
ElMessage.error(tableResponse.message)
}
this.tasks = tableResponse.rows
this.total = tableResponse.total
}).catch(err => {
console.log(err)
ElMessage.error('查询任务记录错误')
})
this.loading = false
},
reset() {
this.goodsIdQuery = ''
this.vehicleNoQuery = ''
this.search()
},
exportExcel() {
downloadRukuExcel().then(res => {
const link = document.createElement('a');//a
try {
// let blob = new Blob([res.data],{type: 'application/vnd.ms-excel'}); //blobblobtypexls
let blob = res.data //blob
// let _fileName = res.headers['content-disposition'].split(';')[1].split('=')[1]; //
let _fileName = "导出入库记录" + dateFormatter(new Date) + ".xlsx"
link.style.display = 'none'//
// URL
const url = window.URL || window.webkitURL || window.moxURL
link.href = url.createObjectURL(blob)
link.setAttribute('download', _fileName.substring(_fileName.lastIndexOf('_') + 1))
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
url.revokeObjectURL(link.href)//url
} catch (e) {
ElMessage({
message: '下载文件失败:: ' + e,
type: 'error',
showClose: true
})
}
}).catch(err => {
ElMessage({
message: '导出失败:: ' + err,
type: 'error',
showClose: true
})
})
},
},
}
</script>
<style scoped>
.el-pagination {
padding-left: 5px;
}
.el-row .el-button {
width: 72px;
margin-left: 0px;
margin-right: 5px;
}
.table-class {
width: 100%;
}
</style>

View File

@ -0,0 +1,259 @@
<template>
<el-config-provider :locale="localLanguage">
<div style="width: calc(100vw - 300px)">
<div style="border-radius: 5px; border: #2c3e5033 solid 1px; padding: 10px; calc(100vw - 300px)">
<el-row>
<el-button type="primary" @click="queryGoodsOrderCheck">查询盘点单</el-button>
<el-button type="success" @click="downInventoryTask">下发盘点任务</el-button>
</el-row>
</div>
<div>
<el-row style="width: calc(100vw - 300px)">
<h5>盘点单</h5>
<el-table :data="goodsInventoryList" border stripe max-height="calc(100vh - 550px)">
<el-table-column fixed prop="recordId" label="记录号" width="210px" align="center" show-overflow-tooltip/>
<el-table-column fixed prop="checkId" label="盘点单号" width="210px" align="center" show-overflow-tooltip/>
<el-table-column fixed prop="warehouse" label="盘点库别" width="210px" align="center" show-overflow-tooltip/>
<el-table-column prop="status" label="盘点单状态" width="210px" align="center" show-overflow-tooltip/>
<el-table-column prop="createTime" label="创建时间" width="210px" align="center" show-overflow-tooltip/>
<el-table-column prop="completeTime" label="完成时间" width="210px" align="center" show-overflow-tooltip/>
<el-table-column prop="remark" label="备注" show-overflow-tooltip min-width="120px" fixed="right"/>
<el-table-column fixed="right" label="操作" align="center" width="180">
<template #default="scope">
<el-button-group class="ml-4">
<el-tooltip content="执行盘点" placement="top" effect="light">
<el-button type="success" size="small" @click="executeCheck(scope.row)">
<el-icon><Check /></el-icon>
</el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top" effect="light">
<el-button type="danger" size="small" @click="deleteCheck(scope.row)">
<el-icon><Delete/></el-icon>
</el-button>
</el-tooltip>
</el-button-group>
</template>
</el-table-column>
</el-table>
</el-row>
</div>
</div>
</el-config-provider>
</template>
<script setup>
import store from '@/store'
import { sendInventoryTask, finishPicking, getTasks, getTaskByTask, sendBoxArrive } from '@/api/task'
import { queryPartNo } from '@/api/goods'
import { taskStatusFormatter, dueFormatter } from '@/utils/formatter.js'
import { reactive, ref } from 'vue'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import OrderCheck from '@/api/order.in'
import {ElMessage, ElMessageBox} from 'element-plus'
</script>
<script>
export default {
name: 'inventory',
data() {
return {
searchParams: {
searchStr: '',
orderStatus: [0]
},
//
remarkR:{
remarkReturn: "盘点回库"
},
goodsInventoryList: []
}
},
methods: {
queryGoodsOrderCheck(){
OrderCheck.getOrderCheckList(this.searchParams).then(res => {
const responseData = res.data;
if (responseData.code === 0) {
//
ElMessage({
message: '查询成功',
type: 'success',
});
this.goodsInventoryList = responseData['returnData'];
} else {
//
ElMessageBox.alert(`服务器返回失败:${responseData.message}`, '查询失败', {
type: 'warning',
confirmButtonText: '确定',
showClose: false
}).catch(err => {
ElMessageBox.alert(`请求服务器失败::${err}`, '任务添加失败', {
type: 'warning',
confirmButtonText: '确定'
})
})
}
})
},
downInventoryTask(){
ElMessageBox.confirm(`是否下发一个盘点任务?`, '提示')
.then(() => {
OrderCheck.downInventoryTask().then(res => {
const responseData = res.data;
if (responseData.code === 1) {
//
ElMessage({
message: '执行成功',
type: 'success',
});
this.queryGoodsOrderCheck();
} else {
//
ElMessageBox.alert(`服务器返回失败:${responseData.message}`, '执行失败', {
type: 'warning',
confirmButtonText: '确定',
showClose: false
})
}
}).catch(err => {
//
ElMessageBox.alert(`请求服务器失败::${err}`, '任务添加失败', {
type: 'warning',
confirmButtonText: '确定'
})
})
})
.catch(() => {
})
},
executeCheck(row){
ElMessageBox.confirm(`是否执行 ${row.recordId} 的盘点?`, '提示')
.then(() => {
OrderCheck.executeCheck(row.recordId).then(res => {
const responseData = res.data;
if (responseData.code === 1) {
//
ElMessage({
message: '执行成功',
type: 'success',
});
this.queryGoodsOrderCheck();
} else {
//
ElMessageBox.alert(`服务器返回失败:${responseData.message}`, '执行失败', {
type: 'warning',
confirmButtonText: '确定',
showClose: false
})
}
}).catch(err => {
//
ElMessageBox.alert(`请求服务器失败::${err}`, '任务添加失败', {
type: 'warning',
confirmButtonText: '确定'
})
})
})
.catch(() => {
})
},
deleteCheck(row) {
ElMessageBox.confirm('是否删除该出库单?','提示')
.then(() => {
OrderCheck.deleteCheckList(row.recordId).then(res => {
const responseData = res.data;
if (responseData.code === 0) {
//
ElMessage({
message: '删除成功',
type: 'success',
});
this.queryGoodsOrderCheck();
} else {
//
ElMessageBox.alert(`服务器返回失败:${responseData.message}`, '删除失败', {
type: 'warning',
confirmButtonText: '确定',
showClose: false
})
}
}).catch(err => {
//
ElMessageBox.alert(`请求服务器失败::${err}`, '任务删除失败', {
type: 'warning',
confirmButtonText: '确定'
})
})
})
.catch(() => {
})
}
}
}
</script>
<style scoped>
.content {
display: flex;
width: 100%;
}
.el-row .el-form-item {
width: 30% inherit;
justify-content: center;
}
.btn-area .el-form-item {
width: 30% inherit;
padding-left: 15px;
}
.el-row .el-form-item .el-select-v2 {
width: 100% !important;
}
.el-row .el-form-item .el-select {
width: 100% !important;
}
.el-row .el-form-item .el-input-number {
width: 100% !important;
}
.el-row .el-form-item .el-button {
margin: auto;
}
.right {
width: 40%;
padding: 5px;
}
.left {
width: 60%;
padding: 5px;
}
.input-area {
margin: auto;
max-width: inherit;
height: 300px;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
}
.display-area {
margin: auto;
min-width: inherit;
height: 632px;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
}
.table-class {
width: 100%;
}
</style>

View File

@ -0,0 +1,150 @@
<template>
<div style="margin-bottom: 15px">
<el-config-provider :locale="zhCn">
<el-row>
<el-input v-model="goodsIdQuery" style="width: 256px; margin-right: 10px;" placeholder="零件号" />
<el-input v-model="vehicleNoQuery" style="width: 256px; margin-right: 10px;" placeholder="箱号" />
<el-button type="primary" @click="search()">搜索</el-button>
<el-button type="warning" @click="reset()">重置</el-button>
<el-button type="success" @click="refresh()">刷新</el-button>
</el-row>
<br />
<el-table :data="tasks" stripe border v-loading="loading" style="width: 100%" max-height="684px"
class="table-class" :header-cell-style="{ 'text-align': 'center' }" :cell-style="{ 'text-align': 'center' }">
<el-table-column prop="goodsId" label="零件号" fixed="left" min-width="120px" />
<el-table-column prop="vehicleNo" label="箱号" fixed="left" min-width="120px" />
<el-table-column prop="goodsName" label="零件名称" min-width="120px" />
<el-table-column prop="taskType" label="任务类型" :formatter="taskTypeFormat" sortable min-width="120px" />
<el-table-column prop="taskGroup" label="任务组" min-width="120px" />
<el-table-column prop="origin" label="起点" min-width="120px" />
<el-table-column prop="destination" label="终点" min-width="120px" />
<el-table-column prop="pickStand" label="拣选站台" min-width="120px" />
<el-table-column prop="weight" label="重量" min-width="120px" />
<el-table-column prop="productionDate" label="生产日期" :formatter="dateFormat" min-width="120px" />
<el-table-column prop="expirationDate" label="有效日期" :formatter="dateFormat" min-width="120px" />
<el-table-column prop="operateNum" label="操作数量" min-width="120px" />
<el-table-column prop="totalNum" label="库存数量" min-width="120px" />
<el-table-column prop="taskPriority" label="任务优先级" sortable min-width="120px" />
<el-table-column prop="kateTaskId" label="配件任务号" sortable min-width="140px" />
<el-table-column prop="userName" label="操作人员姓名" min-width="120px" />
<el-table-column prop="createTime" label="创建时间" :formatter="timeFormat" min-width="120px" />
<el-table-column prop="finishTime" label="任务完成时间" :formatter="timeFormat" min-width="120px" />
<el-table-column prop="taskStatus" label="任务状态" fixed="right" :formatter="taskStatusFormat" min-width="120px" />
<!-- <el-table-column fixed="right" label="操作" width="180px">
<template v-slot="scope">
<el-popconfirm confirm-button-text="" cancel-button-text="" title="请确认是否取消任务?" :hide-after="10" @confirm="">
<template #reference>
<el-button plain type="warning">取消</el-button>
</template>
</el-popconfirm>
<el-popconfirm confirm-button-text="" cancel-button-text="" title="请确认是否完成任务?" :hide-after="10" @confirm="">
<template #reference>
<el-button plain type="primary">完成</el-button>
</template>
</el-popconfirm>
</template>
</el-table-column> -->
</el-table>
<br />
<el-pagination v-model:current-page="currentPage" v-model:page-size="pageSize" :page-sizes="[10, 25, 50]"
:small="false" :disabled="false" :background="false" :default-page-size="10"
layout="total, sizes, prev, pager, next, jumper" :total="total" @size-change="search"
@current-change="search" />
</el-config-provider>
</div>
</template>
<script setup>
import { getTaskRecords } from '@/api/record.js'
import { dateFormatter, taskStatusFormatter, timeFormatter } from '@/utils/formatter.js'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import { ElMessage } from 'element-plus'
import store from '@/store'
</script>
<script>
export default {
name: 'inventoryRecord',
data() {
return {
pageInfo: {},
tasks: [],
currentPage: 1,
pageSize: 10,
total: 0,
goodsIdQuery: '',
vehicleNoQuery: '',
loading: true
}
},
mounted() {
this.search()
},
methods: {
dateFormat: (row, column, cellValue, index) => {
return dateFormatter(cellValue)
},
timeFormat: (row, column, cellValue, index) => {
return timeFormatter(cellValue)
},
taskStatusFormat: (row, column, cellValue, index) => {
return taskStatusFormatter(cellValue)
},
taskTypeFormat: (row, column, cellValue, index) => {
switch (cellValue) {
case 1: return '入库'
case 2: return '出库'
case 3: return '盘点'
default: return '未知'
}
},
search() {
this.loading = true
this.pageInfo.pageNum = this.currentPage
this.pageInfo.pageSize = this.pageSize
const tableRequest = {
page: this.pageInfo,
param: {
taskType: 3,
goodsId: this.goodsIdQuery.trim(),
vehicleNo: this.vehicleNoQuery.trim(),
userName: store.getters.getUserName
}
}
getTaskRecords(tableRequest).then(res => {
const tableResponse = res.data
if (tableResponse.code != 0) {
ElMessage.error(tableResponse.message)
}
this.tasks = tableResponse.rows
this.total = tableResponse.total
}).catch(err => {
console.log(err)
ElMessage.error('查询盘点记录错误')
})
this.loading = false
},
reset() {
this.goodsIdQuery = ''
this.vehicleNoQuery = ''
this.search()
},
},
}
</script>
<style scoped>
.el-pagination {
padding-left: 5px;
}
.el-row .el-button {
width: 72px;
margin-left: 0px;
margin-right: 5px;
}
.table-class {
width: 100%;
}
</style>

View File

@ -0,0 +1,205 @@
<template>
<div style="margin-bottom: 10px">
<el-config-provider :locale="zhCn">
<el-row style="align-items: center;">
<!-- <span>选择库区</span>
<el-select v-model="areaId" placeholder="请选择库区" style="width: 120px;" @change="getAllLocations">
<el-option label="3楼库区" :value='1' />
<el-option label="2楼库区" :value='2' />
</el-select> -->
<span style="margin-left: 5px;">状态说明</span>
<el-button color="green">空闲</el-button>
<el-button color="red">占用</el-button>
<el-button color="yellow">锁定</el-button>
<el-button color="#00BFFF" style="margin: 0 0 0 auto;" @click="getAllLocations">刷新</el-button>
</el-row>
<hr style="border: 1px solid #ff0000" />
<div>
<el-scrollbar max-height="760px">
<div v-for="currentRowLocation in allLocations">
<span>{{ currentRowLocation.row }}</span>
<div class="row" v-for="currentLayerLocation in currentRowLocation.currentLayerLocations">
<div class="col" v-for="currentColLocation in currentLayerLocation.currentColLocations">
<el-button :color="getLocationStatus(currentColLocation)"
@click="showDialog(currentColLocation)">
<span style="font-size: 13px;">{{ currentColLocation.queue}}{{ currentColLocation.line}}{{ currentColLocation.layer}} -{{ currentColLocation.wareArea}}</span>
</el-button>
</div>
</div>
<hr style="border: 1px solid #000000" />
</div>
</el-scrollbar>
<el-dialog v-model="dialogVisible" :title="currentLocationTitle" width="30%" draggable :show-close="false">
<el-form :model="location">
<el-form-item label="库位号" :label-width="140">
<el-input v-model="this.currentSelectedLocation.locationId" style="width: 70%;" readonly />
</el-form-item>
<el-form-item label="占用/解除占用库位" :label-width="140">
<el-select v-model="location.locationStatus" placeholder="库位是否占用" style="width: 70%;">
<el-option label="空闲" :value='0' />
<el-option label="占用" :value='1' />
</el-select>
</el-form-item>
<el-form-item label="锁定/解锁库位" :label-width="140">
<el-select v-model="location.isLock" placeholder="库位是否锁定" style="width: 70%;">
<el-option label="解锁" :value='0' />
<el-option label="锁定" :value='1' />
</el-select>
</el-form-item>
<el-form-item label="载具" :label-width="140">
<el-input v-model="location.vehicleId" style="width: 70%;" />
</el-form-item>
<el-form-item label="库区选择" :label-width="140">
<el-select v-model="location.wareArea" placeholder="选择库区" style="width: 70%;">
<el-option label="A" value="A" />
<el-option label="B" value="B" />
<el-option label="C" value="C" />
</el-select>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitLocationStatus()">
确定
</el-button>
</span>
</template>
</el-dialog>
</div>
</el-config-provider>
</div>
</template>
<script setup>
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import { getLocations, updateLocation } from '@/api/location.js'
import { ElMessage, ElLoading } from 'element-plus'
import { reactive } from 'vue'
</script>
<script>
export default {
name: 'location',
data() {
return {
dialogVisible: false,
currentSelectedLocation: {},
allLocations: [],
location: reactive({
locationId:'this.currentSelectedLocation.locationId',
locationStatus: '',
isLock: '',
vehicleId: '',
wareArea: ''
}),
currentLocationTitle: '',
areaId: 1
}
},
mounted() {
this.getAllLocations()
},
methods: {
getLocationStatus: (currentColLocation) => {
if (currentColLocation.isLock === 1) {
return 'yellow'
}
if (currentColLocation.locationStatus === 1) {
return 'red'
}
return 'green'
},
getAllLocations() {
const loading = ElLoading.service({
lock: true,
text: 'Loading',
background: 'rgba(0, 0, 0, 0.7)',
})
const data = { areaId: this.areaId }
getLocations(data).then(res => {
loading.close()
if (res.data.code == 0) {
console.log(res.data.returnData)
this.allLocations = res.data.returnData
} else {
ElMessage.error(res.data.message)
}
}).catch(err => {
loading.close()
ElMessage.error('查询库位失败!')
})
},
test() {
console.log(this.location);
},
showDialog(currentColLocation) {
this.dialogVisible = true
this.currentSelectedLocation = currentColLocation
this.setCurrentLocationTitle()
this.location.locationId = this.currentSelectedLocation.locationId
this.location.locationStatus = this.currentSelectedLocation.locationStatus
this.location.isLock = this.currentSelectedLocation.isLock
this.location.vehicleId = this.currentSelectedLocation.vehicleId
this.location.wareArea = this.currentSelectedLocation.wareArea
},
submitLocationStatus() {
const loading = ElLoading.service({
lock: true,
text: 'Loading',
background: 'rgba(0, 0, 0, 0.7)',
})
this.currentSelectedLocation.locationId = this.location.locationId
this.currentSelectedLocation.locationStatus = this.location.locationStatus
this.currentSelectedLocation.isLock = this.location.isLock
this.currentSelectedLocation.vehicleId = this.location.vehicleId
this.currentSelectedLocation.wareArea = this.location.wareArea
updateLocation(this.currentSelectedLocation).then(res => {
if (res.data.code == 0) {
loading.close()
this.dialogVisible = false
ElMessage({
message: '更新库位信息成功!',
type: 'success',
})
this.getAllLocations()
} else {
ElMessage.error(res.data.message)
}
}).catch(err => {
loading.close()
ElMessage.error('更新库位信息失败')
})
},
setCurrentLocationTitle() {
const parts = this.currentSelectedLocation.locationId.split('-');
this.currentLocationTitle = '当前选择库位:' + parts[0] + '排' + parts[1] + '列' + parts[2] + '层';
//this.currentLocationTitle = '' + this.currentSelectedLocation.queue + '' + this.currentSelectedLocation.line + '' + this.currentSelectedLocation.layer + '' + '(' + this.currentSelectedLocation.warearea + ')'
}
}
}
</script>
<style scoped>
.el-pagination {
padding-left: 5px;
}
.row {
display: flex;
justify-content: space-between;
margin: 5px;
}
.col {
/* width: 100px; */
/* height: 40px; */
padding: 1px;
margin: 1px;
}
.col .el-button {
width: 100px;
height: 50px;
}
</style>

View File

@ -0,0 +1,150 @@
<template>
<div style="margin-bottom: 15px">
<el-config-provider :locale="zhCn">
<el-row>
<el-input v-model="goodsIdQuery" style="width: 256px; margin-right: 10px;" placeholder="零件号" />
<el-input v-model="vehicleNoQuery" style="width: 256px; margin-right: 10px;" placeholder="箱号" />
<el-button type="primary" @click="search()">搜索</el-button>
<el-button type="warning" @click="reset()">重置</el-button>
<el-button type="success" @click="search()">刷新</el-button>
</el-row>
<br />
<el-table :data="tasks" stripe border v-loading="loading" style="width: 100%" max-height="684px"
class="table-class" :header-cell-style="{ 'text-align': 'center' }" :cell-style="{ 'text-align': 'center' }">
<el-table-column prop="goodsId" label="零件号" fixed="left" min-width="120px" />
<el-table-column prop="vehicleNo" label="箱号" fixed="left" min-width="120px" />
<el-table-column prop="goodsName" label="零件名称" min-width="120px" />
<el-table-column prop="taskType" label="任务类型" :formatter="taskTypeFormat" sortable min-width="120px" />
<el-table-column prop="taskGroup" label="任务组" min-width="120px" />
<el-table-column prop="origin" label="起点" min-width="120px" />
<el-table-column prop="destination" label="终点" min-width="120px" />
<el-table-column prop="pickStand" label="拣选站台" min-width="120px" />
<el-table-column prop="weight" label="重量" min-width="120px" />
<el-table-column prop="productionDate" label="生产日期" :formatter="dateFormat" min-width="120px" />
<el-table-column prop="expirationDate" label="有效日期" :formatter="dateFormat" min-width="120px" />
<el-table-column prop="operateNum" label="操作数量" min-width="120px" />
<el-table-column prop="totalNum" label="库存数量" min-width="120px" />
<el-table-column prop="taskPriority" label="任务优先级" sortable min-width="120px" />
<el-table-column prop="kateTaskId" label="配件任务号" sortable min-width="140px" />
<el-table-column prop="userName" label="操作人员姓名" min-width="120px" />
<el-table-column prop="createTime" label="创建时间" :formatter="timeFormat" min-width="120px" />
<el-table-column prop="finishTime" label="任务完成时间" :formatter="timeFormat" min-width="120px" />
<el-table-column prop="taskStatus" label="任务状态" fixed="right" :formatter="taskStatusFormat" min-width="120px" />
<!-- <el-table-column fixed="right" label="操作" width="180px">
<template v-slot="scope">
<el-popconfirm confirm-button-text="" cancel-button-text="" title="请确认是否取消任务?" :hide-after="10" @confirm="">
<template #reference>
<el-button plain type="warning">取消</el-button>
</template>
</el-popconfirm>
<el-popconfirm confirm-button-text="" cancel-button-text="" title="请确认是否完成任务?" :hide-after="10" @confirm="">
<template #reference>
<el-button plain type="primary">完成</el-button>
</template>
</el-popconfirm>
</template>
</el-table-column> -->
</el-table>
<br />
<el-pagination v-model:current-page="currentPage" v-model:page-size="pageSize" :page-sizes="[10, 25, 50]"
:small="false" :disabled="false" :background="false" :default-page-size="10"
layout="total, sizes, prev, pager, next, jumper" :total="total" @size-change="search"
@current-change="search" />
</el-config-provider>
</div>
</template>
<script setup>
import { getTaskRecords } from '@/api/record.js'
import { dateFormatter, taskStatusFormatter, timeFormatter } from '@/utils/formatter.js'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import { ElMessage } from 'element-plus'
import store from '@/store'
</script>
<script>
export default {
name: 'outTaskRecord',
data() {
return {
pageInfo: {},
tasks: [],
currentPage: 1,
pageSize: 10,
total: 0,
goodsIdQuery: '',
vehicleNoQuery: '',
loading: true
}
},
mounted() {
this.search()
},
methods: {
dateFormat: (row, column, cellValue, index) => {
return dateFormatter(cellValue)
},
timeFormat: (row, column, cellValue, index) => {
return timeFormatter(cellValue)
},
taskStatusFormat: (row, column, cellValue, index) => {
return taskStatusFormatter(cellValue)
},
taskTypeFormat: (row, column, cellValue, index) => {
switch (cellValue) {
case 1: return '入库'
case 2: return '出库'
case 3: return '盘点'
default: return '未知'
}
},
search() {
this.loading = true
this.pageInfo.pageNum = this.currentPage
this.pageInfo.pageSize = this.pageSize
const tableRequest = {
page: this.pageInfo,
param: {
taskType: 2,
goodsId: this.goodsIdQuery.trim(),
vehicleNo: this.vehicleNoQuery.trim(),
userName: store.getters.getUserName
}
}
getTaskRecords(tableRequest).then(res => {
const tableResponse = res.data
if (tableResponse.code != 0) {
ElMessage.error(tableResponse.message)
}
this.tasks = tableResponse.rows
this.total = tableResponse.total
}).catch(err => {
console.log(err)
ElMessage.error('查询任务记录错误')
})
this.loading = false
},
reset() {
this.goodsIdQuery = ''
this.vehicleNoQuery = ''
this.search()
},
},
}
</script>
<style scoped>
.el-pagination {
padding-left: 5px;
}
.el-row .el-button {
width: 72px;
margin-left: 0px;
margin-right: 5px;
}
.table-class {
width: 100%;
}
</style>

View File

@ -0,0 +1,260 @@
<template>
<div style="margin-bottom: 10px">
<el-config-provider :locale="zhCn">
<el-row>
<el-input v-model="queryKey" style="width: 256px; margin-right: 10px;" placeholder="箱号" />
<el-button type="primary" @click="search()">搜索</el-button>
<el-button type="warning" @click="reset()">重置</el-button>
<!-- <el-button type="success" @click="refresh()">刷新</el-button> -->
</el-row>
<br />
<el-table :data="vehicles" stripe border v-loading="loading" class="table-class" max-height="650px"
highlight-current-row @row-click="getCurrentRow" :header-cell-style="{ 'text-align': 'center' }" :cell-style="{ 'text-align': 'center' }">
<el-table-column width="65px" fixed="left">
<template v-slot="scope">
<el-radio :label="scope.row.vehicleId" v-model="vehicleId">&nbsp;</el-radio>
</template>
</el-table-column>
<el-table-column prop="vehicleId" label="箱号" fixed="left" min-width="120px" />
<el-table-column prop="currentLocation" label="当前位置" fixed="left" min-width="120px" />
<el-table-column prop="vehicleStatus" label="料箱状态" :formatter="vehicleStatusFormat" min-width="120px" />
<el-table-column prop="isEmpty" label="是否空箱" :formatter="isEmptyFormat" min-width="120px" />
<el-table-column fixed="right" label="操作" width="200px" v-if="selVehicle == null">
<template v-slot="scope">
<el-button plain type="primary" @click="editCurrentRowVehicle(scope.row)">编辑</el-button>
<el-button plain type="danger" @click="deleteCurrentRowVehicle(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<br />
<el-pagination v-model:current-page="currentPage" v-model:page-size="pageSize" :page-sizes="[10, 25, 50]"
:small="false" :disabled="false" :background="false" :default-page-size="10"
layout="total, sizes, prev, pager, next, jumper" :total="total" @size-change="search"
@current-change="search" />
<el-dialog v-model="dialogVisible" title="托盘信息" width="40%" draggable :show-close="false">
<el-form ref="vehicleFormRef" :model="vehicleFormEntity" :label-position="labelPosition" label-width="100px"
style="max-width: 100%" :rules="rules" status-icon>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="料箱号" prop="vehicleId">
<el-input v-model="vehicleFormEntity.vehicleId" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="当前位置" prop="currentLocation">
<el-input v-model="vehicleFormEntity.currentLocation" placeholder="请输入当前位置" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="是否空箱" prop="isEmpty">
<el-select-v2 v-model="vehicleFormEntity.isEmpty" placeholder="请选择托盘状态"
:options="isEmptyOptions"></el-select-v2>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="托盘状态" prop="vehicleStatus">
<el-select-v2 v-model="vehicleFormEntity.vehicleStatus" placeholder="请选择托盘状态"
:options="vehicleStatusOptions"></el-select-v2>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitVehicleInfo(vehicleFormEntity)">
确定
</el-button>
</span>
</template>
</el-dialog>
</el-config-provider>
</div>
</template>
<script setup>
import { getAllVehicles, updateVehicleInfo, deleteCurrentVehicle } from '@/api/vehicle'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import { ElMessage } from 'element-plus'
import { ref, reactive } from 'vue'
import { vehicleStatusFormatter, locationFormatter } from '@/utils/formatter.js'
</script>
<script>
export default {
name: 'stand',
props: ['selVehicle'],
emits: ['update:selVehicle'],
data() {
return {
pageInfo: {},
vehicles: [],
currentPage: 1,
pageSize: 10,
total: 0,
queryKey: '',
loading: true,
dialogVisible: false,
vehicleId: '',
vehicleFormEntity: reactive({}),
labelPosition: 'top',
vehicleFormRef: ref(),
rules: reactive({
locationId: [
{ required: true, message: '请输入库位' }
]
}),
//
isEmptyOptions: [
{
value: 0,
label: '带料'
},
{
value: 1,
label: '空箱'
}
],
//
vehicleStatusOptions: [
{
value: 0,
label: '入库中'
},
{
value: 1,
label: '在库中'
},
{
value: 2,
label: '出库中'
}
]
}
},
mounted() {
this.search()
},
methods: {
search() {
this.loading = true
this.pageInfo.pageNum = this.currentPage
this.pageInfo.pageSize = this.pageSize
const tableRequest = {
page: this.pageInfo,
param: {
vehicleId: this.queryKey.trim()
},
}
getAllVehicles(tableRequest).then(res => {
const tableResponse = res.data
if (tableResponse.code != 0) {
console.log(tableResponse.code + ':' + tableResponse.message)
ElMessage.error(tableResponse.message)
}
this.vehicles = tableResponse.rows
this.total = tableResponse.total
}).catch(err => {
ElMessage.error('查询托盘信息错误' + err.message)
})
this.loading = false
},
vehicleStatusFormat: (row, column, cellValue, index) => {
return vehicleStatusFormatter(cellValue)
},
locationFormat: (row, column, cellValue, index) => {
return locationFormatter(cellValue)
},
isEmptyFormat: (row, column, cellValue, index) => {
if (cellValue == 0) {
return '带料'
}
if (cellValue == 1) {
return '空箱'
}
},
reset() {
this.queryKey = ''
this.search()
},
editCurrentRowVehicle(row) {
this.vehicleFormEntity = row
this.dialogVisible = true
},
deleteCurrentRowVehicle(row) {
this.vehicleId = row.vehicleId
const vehicle = {
vehicleId: row.vehicleId
}
deleteCurrentVehicle(vehicle).then(res => {
if (res.data.code == 0) {
ElMessage({
message: '删除料箱成功',
type: 'success',
})
this.search()
} else {
ElMessage.error(res.data.message)
}
}).catch(err => {
ElMessage.error('删除料箱信息失败:' + err)
})
},
submitVehicleInfo(formData) {
updateVehicleInfo(formData).then(res => {
if (res.data.code == 0) {
this.dialogVisible = false
ElMessage({
message: '更新料箱信息成功',
type: 'success',
})
this.search()
} else {
ElMessage.error(res.data.message)
}
}).catch(err => {
ElMessage.error('更新料箱信息失败:' + err)
})
},
getCurrentRow(row) {
this.vehicleId = row.vehicleId
this.$emit('update:selVehicle', row)
}
}
}
</script>
<style scoped>
.el-pagination {
padding-left: 5px;
}
.el-row .el-button {
width: 72px;
margin-left: 0px;
margin-right: 5px;
}
.table-class {
width: 100%;
/* font-size: 5px; */
}
.el-row .el-form-item {
width: 10% inherit;
justify-content: center;
}
.el-row .el-form-item .el-select-v2 {
width: 100% !important;
}
.el-row .el-form-item .el-input-number {
width: 100% !important;
}
.el-row .el-form-item .el-button {
margin: auto;
}
</style>

View File

@ -0,0 +1,457 @@
<template>
<div style="margin-bottom: 10px">
<el-config-provider :locale="zhCn">
<el-row>
<el-input v-model="queryKey" v-if="dataType == 1" style="width: 256px; margin-right: 10px;"
placeholder="零件号/箱号/零件名称" :suffix-icon="Search" />
<el-input v-if="dataType == 2" v-model="goodsIdQuery" style="width: 256px; margin-right: 10px;"
placeholder="零件号" :suffix-icon="Search" />
<el-button type="primary" @click="search()">搜索</el-button>
<el-button type="warning" @click="reset()">重置</el-button>
<el-button type="success" @click="exportExcel()">导出表格</el-button>
<el-select-v2 v-if="selStock == null" v-model="dataType" style="width: 156px; margin-right: 10px;"
placeholder="请选择库存显示类型" :options="dataTypeOptions" @change="search()"></el-select-v2>
</el-row>
<br />
<el-table id="stock-table" :data="displayStocks" stripe border v-loading="loading" class="table-class"
max-height="650px" highlight-current-row @row-click="getCurrentRow" :row-style="rowStyle"
:header-cell-style="{ 'text-align': 'center' }" :cell-style="{ 'text-align': 'center' }">
<el-table-column width="65px" fixed="left">
<template v-slot="scope">
<el-radio :label="scope.row.stockId" v-model="stockId">&nbsp;</el-radio>
</template>
</el-table-column>
<el-table-column prop="stockId" label="库存ID" min-width="120px" show-overflow-tooltip/>
<el-table-column prop="goodsId" label="物料号" min-width="120px" />
<el-table-column prop="batchNo" v-if="dataType == 1" label="批次号" min-width="120px" />
<el-table-column prop="goodsName" label="零件描述" min-width="120px" />
<el-table-column prop="availableNum" v-if="dataType == 1" label="可用数量" min-width="120px" />
<el-table-column prop="remainNum" v-if="dataType == 1" label="剩余数量" min-width="120px" />
<el-table-column prop="realNum" label="实际数量" min-width="120px" />
<el-table-column prop="vehicleId" v-if="dataType == 1" label="料箱号" fixed="left" min-width="120px" />
<el-table-column prop="providerId" v-if="dataType == 1" label="供应商编号" min-width="130px" />
<el-table-column prop="providerName" v-if="dataType == 1" label="供应商名称" min-width="130px" />
<el-table-column prop="shelfLife" v-if="dataType == 1" label="保质期" min-width="120px" />
<el-table-column prop="expirationDate" v-if="dataType == 1" label="有效日期" :formatter="dateFormat" min-width="140px" />
<el-table-column prop="locationId" v-if="dataType == 1" label="库位" :formatter="locationFormat" min-width="160px" />
<el-table-column prop="currentLocation" v-if="dataType == 1" label="当前位置" min-width="120px" />
<el-table-column prop="isInventory" v-if="dataType == 1" label="是否盘点" min-width="120px" />
<el-table-column prop="createTime" v-if="dataType == 1" label="上架时间" :formatter="timeFormat" min-width="140px" />
<el-table-column prop="goodsStatus" v-if="dataType == 1" label="物料状态" :formatter="goodsStatusFormat" min-width="120px" />
<el-table-column prop="stockStatus" v-if="dataType == 1" label="库存状态" :formatter="stockStatusFormat" fixed="right"
min-width="120px" />
<el-table-column fixed="right" label="操作" width="135px" v-if="selStock == null">
<template v-slot="scope">
<el-button size="small" plain type="primary" @click="editCurrentRowStock(scope.row)">编辑</el-button>
<!--<el-button size="small" plain type="warning" @click="outRowStock(scope.row)">出库</el-button>-->
</template>
</el-table-column>
<!-- <el-table-column prop="areaCode" label="库区代码" fixed="right" sortable min-width="120px" /> -->
</el-table>
<br />
<el-pagination v-model:current-page="currentPage" v-model:page-size="pageSize" :page-sizes="[10, 25, 50]"
:small="false" :disabled="false" :background="false" :default-page-size="10" @size-change="search"
@current-change="search" layout="total, sizes, prev, pager, next, jumper" :total="total" />
<el-dialog v-model="dialogVisible" title="物料信息" width="40%" draggable :show-close="false">
<el-form ref="stockFormRef" :model="stockFormEntity" :label-position="labelPosition" label-width="100px"
style="max-width: 100%" :rules="rules" status-icon>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="零件号" prop="goodsId">
<el-input v-model="stockFormEntity.goodsId" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="零件描述" prop="goodsName">
<el-input v-model="stockFormEntity.goodsName" readonly />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="可用数量" prop="availableNum">
<el-input-number v-model.number="stockFormEntity.availableNum" clearable
controls-position="right" :min="0" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="剩余数量" prop="remainNum">
<el-input-number v-model.number="stockFormEntity.remainNum" clearable
controls-position="right" :min="0" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="实际数量为0时删除库存" prop="realNum">
<el-input-number v-model.number="stockFormEntity.realNum" controls-position="right"
:min="0" clearable />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="货箱号" prop="vehicleId">
<el-input v-model="stockFormEntity.vehicleId" clearable readonly />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="库存状态" prop="stockStatus">
<el-select-v2 v-model="stockFormEntity.stockStatus" placeholder="请选择库存状态"
:options="stockStatusOptions"></el-select-v2>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="物料状态" prop="goodsStatus">
<el-select-v2 v-model="stockFormEntity.goodsStatus" placeholder="请选择物料状态"
:options="goodsStatusOptions"></el-select-v2>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitStockInfo(stockFormEntity)">
确定
</el-button>
</span>
</template>
</el-dialog>
</el-config-provider>
</div>
</template>
<script setup>
import { getAllStocks, updateStockInfo, getAllStocksByGoodsId } from '@/api/stock.js'
import { downloadStockExcel } from '@/api/excel.js'
import { dateFormatter, locationFormatter, timeFormatter } from '@/utils/formatter.js'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import { Search } from '@element-plus/icons-vue'
import { ref, reactive } from 'vue'
//import { ElMessage } from 'element-plus'
import {ElMessage, ElMessageBox} from 'element-plus'
import apiOrderOut from '@/api/order.out'
// import FileSaver from 'file-saver';
// import * as XLSX from 'xlsx';
</script>
<script>
export default {
name: 'stock',
props: ['selStock'],
emits: ['update:selStock'],
data() {
return {
pageInfo: {},
displayStocks: [],
currentPage: 1,
pageSize: 10,
total: 0,
queryKey: '',
loading: true,
stockId: '',
stockFormRef: ref(),
stockFormEntity: reactive({}),
rules: reactive({}),
labelPosition: 'top',
dialogVisible: false,
goodsStatusOptions: [
{
value: 0,
label: '合格'
},
{
value: 1,
label: '不合格'
},
{
value: 2,
label: '延期'
},
{
value: 3,
label: '过期'
},
{
value: 5,
label: '长时间未使用'
}
],
stockStatusOptions: [
{
value: 0,
label: '库存正常'
},
{
value: 1,
label: '准备出库'
},
{
value: 2,
label: '正在出库'
},
{
value: 3,
label: '出库完成,环线运输中'
},
{
value: 4,
label: '站台拣货中'
},
{
value: 5,
label: '站台盘点中'
},
{
value: 6,
label: '正在回库'
},
{
value: 9,
label: '库存锁定'
}
],
dataType: 1,
dataTypeOptions: [
{
value: 1,
label: '按料箱分类'
},
{
value: 2,
label: '按零件分类'
}
],
goodsIdQuery: ''
}
},
mounted() {
this.refresh()
},
methods: {
locationFormat: (row, column, cellValue, index) => {
return locationFormatter(cellValue)
},
dateFormat: (row, column, cellValue, index) => {
return dateFormatter(cellValue)
},
timeFormat: (row, column, cellValue, index) => {
return timeFormatter(cellValue)
},
goodsStatusFormat: (row, column, cellValue, index) => {
if (cellValue === 0) {
return '合格'
} else if (cellValue === 1) {
return '不合格'
} else if (cellValue === 2) {
return '延期'
} else if (cellValue === 3) {
return '过期'
} else if (cellValue === 5) {
return '长时间未使用'
}
},
stockStatusFormat: (row, column, cellValue, index) => {
switch (cellValue) {
case 0:
return '库存正常'
case 1:
return '准备出库'
case 2:
return '正在出库'
case 3:
return '出库完成,环线运输中'
case 4:
return '站台拣货中'
case 5:
return '站台盘点中'
case 6:
return '正在回库'
case 7:
return '到达拣选站台'
case 9:
return '库存锁定'
default:
return '异常'
}
},
rowStyle: ({ row, rowIndex }) => {
if (row.goodsStatus == 3) {
return { "color": "red" }
}
if (row.goodsStatus == 5) {
return { "color": "yellow" }
}
},
search() {
this.loading = true
this.pageInfo.pageNum = this.currentPage
this.pageInfo.pageSize = this.pageSize
if (this.dataType == 1) {
const tableRequest = {
page: this.pageInfo,
param: this.queryKey.trim(),
}
getAllStocks(tableRequest).then(res => {
const tableResponse = res.data
if (tableResponse.code != 0) {
ElMessage.error(tableResponse.message)
}
this.displayStocks = tableResponse.rows
this.total = tableResponse.total
}).catch(err => {
console.log(err)
ElMessage.error('查询库存错误')
})
} else if (this.dataType == 2) {
const tableRequest = {
page: this.pageInfo,
param: this.goodsIdQuery.trim(),
}
getAllStocksByGoodsId(tableRequest).then(res => {
const tableResponse = res.data
if (tableResponse.code != 0) {
ElMessage.error(tableResponse.message)
}
this.displayStocks = tableResponse.rows
this.total = tableResponse.total
}).catch(err => {
console.log(err)
ElMessage.error('查询库存错误')
})
}
this.loading = false
},
reset() {
this.queryKey = ''
this.goodsIdQuery = ''
this.search()
},
refresh() {
this.search()
},
getCurrentRow(row) {
this.stockId = row.stockId
this.$emit('update:selStock', row)
},
exportExcel() {
downloadStockExcel().then(res => {
const link = document.createElement('a');//a
try {
// let blob = new Blob([res.data],{type: 'application/vnd.ms-excel'}); //blobblobtypexls
let blob = res.data //blob
// let _fileName = res.headers['content-disposition'].split(';')[1].split('=')[1]; //
let _fileName = "库存报表" + dateFormatter(new Date) + ".xlsx"
link.style.display = 'none'//
// URL
const url = window.URL || window.webkitURL || window.moxURL
link.href = url.createObjectURL(blob)
link.setAttribute('download', _fileName.substring(_fileName.lastIndexOf('_') + 1))
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
url.revokeObjectURL(link.href)//url
} catch (e) {
ElMessage({
message: '下载文件失败:: ' + e,
type: 'error',
showClose: true
})
}
}).catch(err => {
ElMessage({
message: '导出失败:: ' + err,
type: 'error',
showClose: true
})
})
},
editCurrentRowStock(row) {
this.stockFormEntity = row
this.dialogVisible = true
},
outRowStock(row) {
const stockId = row.stockId;
ElMessageBox.confirm(`是否执行 ${stockId} 的出库?`, '提示')
.then(() => {
apiOrderOut.outRowStock(stockId).then(res => {
const responseData = res.data;
if (responseData.code === 0) {
//
ElMessage({
message: '执行成功',
type: 'success',
});
this.queryGoodsOrderOut();
} else {
//
ElMessageBox.alert(`服务器返回失败:${responseData.message}`, '执行失败', {
type: 'warning',
confirmButtonText: '确定',
showClose: false
})
}
}).catch(err => {
//
ElMessageBox.alert(`请求服务器失败::${err}`, '任务添加失败', {
type: 'warning',
confirmButtonText: '确定'
})
})
})
.catch(() => {
})
},
submitStockInfo(stockFormEntity) {
console.log(stockFormEntity)
updateStockInfo(stockFormEntity).then(res => {
if (res.data.code == 0) {
this.dialogVisible = false
ElMessage({
message: '更新库存成功',
type: 'success'
})
this.search()
} else {
ElMessage.error(res.data.message)
}
}).catch(err => {
ElMessage({
message: '更新料箱信息失败: ' + err,
type: 'error',
showClose: true
})
})
}
},
}
</script>
<style scoped>
.el-pagination {
padding-left: 5px;
}
.el-row .el-button {
width: 72px;
margin-left: 0px;
margin-right: 5px;
}
.table-class {
width: 100%;
}
.el-row .el-form-item .el-select-v2 {
width: 100% !important;
}
.el-row .el-form-item .el-input-number {
width: 100% !important;
}
</style>

View File

@ -0,0 +1,326 @@
<template>
<div style="margin-bottom: 15px">
<el-config-provider :locale="zhCn">
<el-row>
<el-input v-model="goodsIdQuery" style="width: 256px; margin-right: 10px;" placeholder="零件号" />
<el-input v-model="vehicleNoQuery" style="width: 256px; margin-right: 10px;" placeholder="箱号" />
<el-button type="primary" @click="search()">搜索</el-button>
<el-button type="warning" @click="reset()">重置</el-button>
<el-button type="success" @click="search()">刷新</el-button>
</el-row>
<br />
<el-table :data="tasks" stripe border v-loading="loading" style="width: 100%" max-height="684px"
class="table-class" :header-cell-style="{ 'text-align': 'center' }" :cell-style="{ 'text-align': 'center' }"
@row-click="getCurrentRow">
<el-table-column width="65px" fixed="left">
<template v-slot="scope">
<el-radio :label="scope.row.taskId" v-model="taskId">&nbsp;</el-radio>
</template>
</el-table-column>
<el-table-column prop="goodsId" label="零件号" fixed="left" min-width="120px" />
<el-table-column prop="vehicleNo" label="箱号" fixed="left" min-width="120px" />
<el-table-column prop="goodsName" label="零件名称" min-width="120px" />
<el-table-column prop="taskType" label="任务类型" :formatter="taskTypeFormat" min-width="120px" />
<el-table-column prop="taskGroup" label="任务组" min-width="120px" />
<el-table-column prop="origin" label="起点" min-width="120px" />
<el-table-column prop="destination" label="终点" min-width="120px" />
<el-table-column prop="pickStand" label="拣选站台" min-width="120px" />
<el-table-column prop="weight" label="重量" min-width="120px" />
<el-table-column prop="productionDate" label="生产日期" :formatter="dateFormat" min-width="120px" />
<el-table-column prop="expirationDate" label="有效日期" :formatter="dateFormat" min-width="120px" />
<el-table-column prop="operateNum" label="操作数量" min-width="120px" />
<el-table-column prop="totalNum" label="库存数量" min-width="120px" />
<el-table-column prop="taskPriority" label="任务优先级" min-width="120px" />
<el-table-column prop="kateTaskId" label="配件任务号" min-width="140px" />
<el-table-column prop="createTime" label="创建时间" :formatter="timeFormat" min-width="120px" />
<el-table-column prop="createTime" label="运行时长" :formatter="dueFormat" min-width="120px" />
<el-table-column prop="userName" label="操作人员姓名" min-width="120px" />
<el-table-column prop="taskStatus" label="任务状态" fixed="right" :formatter="taskStatusFormat"
min-width="120px" />
<el-table-column fixed="right" label="操作" width="120px">
<template v-slot="scope">
<el-button plain type="primary" @click="editCurrentRowTask(scope.row)">编辑</el-button>
</template>
</el-table-column>
</el-table>
<br />
<el-pagination v-model:current-page="currentPage" v-model:page-size="pageSize" :page-sizes="[10, 25, 50]"
:small="false" :disabled="false" :background="false" :default-page-size="10"
layout="total, sizes, prev, pager, next, jumper" :total="total" @size-change="search"
@current-change="search" />
<el-dialog v-model="dialogVisible" title="任务信息" width="40%" draggable :show-close="false">
<el-form ref="taskFormRef" :model="taskFormEntity" :label-position="labelPosition" label-width="100px"
style="max-width: 100%" :rules="rules" status-icon>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="料箱号" prop="vehicleNo">
<el-input v-model="taskFormEntity.vehicleNo" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="零件号" prop="goodsId">
<el-input v-model="taskFormEntity.goodsId" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="起点" prop="origin">
<el-input v-model="taskFormEntity.origin" disabled />
</el-form-item>
</el-col>
<el-col :span="12" v-if="taskFormEntity.taskType == 1">
<el-form-item label="终点" prop="destination">
<el-select-v2 v-model="taskFormEntity.destination"
:options="availableLocationOptions"></el-select-v2>
</el-form-item>
</el-col>
<el-col :span="12" v-if="taskFormEntity.taskType == 2">
<el-form-item label="终点" prop="destination">
<el-input v-model="taskFormEntity.destination" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="任务类型" prop="taskType">
<el-select-v2 v-model="taskFormEntity.taskType" placeholder="请选择任务类型" disabled
:options="taskTypeOptions"></el-select-v2>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="任务状态" prop="taskStatus">
<el-select-v2 v-model="taskFormEntity.taskStatus" placeholder="请选择任务状态"
:options="taskStatusOptions"></el-select-v2>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitTaskInfo(taskFormEntity)">
确定
</el-button>
</span>
</template>
</el-dialog>
</el-config-provider>
</div>
</template>
<script setup>
import { getTasks, changeTaskStatus } from '@/api/task.js'
import { getAvailableLocations } from '@/api/location.js'
import { dateFormatter, locationFormatter, taskStatusFormatter, timeFormatter, dueFormatter } from '@/utils/formatter.js'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import { ElMessage } from 'element-plus'
import store from '@/store'
import { ref, reactive } from 'vue'
</script>
<script>
export default {
name: 'taskMonitor',
data() {
return {
pageInfo: {},
tasks: [],
currentPage: 1,
pageSize: 10,
total: 0,
goodsIdQuery: '',
vehicleNoQuery: '',
loading: true,
dialogVisible: false,
taskFormEntity: reactive({}),
labelPosition: 'top',
taskFormRef: ref(),
rules: reactive({}),
taskId: '',
taskTypeOptions: [
{
value: 1,
label: '入库'
},
{
value: 2,
label: '出库'
},
{
value: 3,
label: '盘点'
},
],
taskStatusOptions: [
{
value: 0,
label: '任务重置'
},
{
value: 1,
label: '任务取消'
},
{
value: 2,
label: '任务完成'
}
],
availableLocationOptions: []
}
},
mounted() {
this.search()
},
methods: {
dateFormat: (row, column, cellValue, index) => {
return dateFormatter(cellValue)
},
timeFormat: (row, column, cellValue, index) => {
return timeFormatter(cellValue)
},
taskStatusFormat: (row, column, cellValue, index) => {
return taskStatusFormatter(cellValue)
},
taskTypeFormat: (row, column, cellValue, index) => {
switch (cellValue) {
case 1:
if (row.taskId.substr(0, 2) == 'HK') {
return '回库'
} else {
return '入库'
}
case 2: return '出库'
case 3: return '盘点'
default: return '未知'
}
},
dueFormat: (row, column, cellValue, index) => {
return dueFormatter(cellValue)
},
search() {
this.loading = true
this.pageInfo.pageNum = this.currentPage
this.pageInfo.pageSize = this.pageSize
const tableRequest = {
page: this.pageInfo,
param: {
goodsId: this.goodsIdQuery.trim(),
vehicleNo: this.vehicleNoQuery.trim(),
userName: store.getters.getUserName
}
}
getTasks(tableRequest).then(res => {
const tableResponse = res.data
if (tableResponse.code != 0) {
console.log(tableResponse.code + ':' + tableResponse.message)
ElMessage.error(tableResponse.message)
}
this.tasks = tableResponse.rows
this.total = tableResponse.total
}).catch(err => {
console.log(err)
ElMessage.error('查询任务错误')
})
this.loading = false
},
reset() {
this.goodsIdQuery = ''
this.vehicleNoQuery = ''
},
editCurrentRowTask(row) {
if (row.taskType == 1) {
this.availableLocationOptions = []
var currentOption = {
value: row.destination,
label: locationFormatter(row.destination)
}
this.availableLocationOptions.push(currentOption)
//
const requestParam = {
areaId: 1
}
getAvailableLocations(requestParam).then(res => {
if (res.data.code == 0) {
for (const location of res.data.returnData) {
var newOption = {}
newOption.value = location.locationId
newOption.label = locationFormatter(location.locationId)
this.availableLocationOptions.push(newOption)
}
}
}).catch(err => {
ElMessage.error('查找可用库位失败:' + err)
})
}
this.taskFormEntity.taskId = row.taskId
this.taskFormEntity.vehicleNo = row.vehicleNo
this.taskFormEntity.goodsId = row.goodsId
this.taskFormEntity.origin = row.origin
this.taskFormEntity.destination = row.destination
this.taskFormEntity.taskType = row.taskType
this.taskFormEntity.taskStatus = null
this.dialogVisible = true
},
submitTaskInfo(formData) {
if (formData.taskStatus == null || formData.taskStatus == undefined) {
ElMessage.error('请选择任务状态')
return
}
formData.userName = store.getters.getUserName
changeTaskStatus(formData).then(res => {
if (res.data.code == 0) {
this.dialogVisible = false
ElMessage({
message: '更新任务状态成功',
type: 'success',
})
this.taskFormEntity.taskId = ''
this.taskFormEntity.vehicleNo = ''
this.taskFormEntity.goodsId = ''
this.taskFormEntity.origin = ''
this.taskFormEntity.destination = ''
this.taskFormEntity.taskType = null
this.taskFormEntity.taskStatus = null
this.search()
} else {
ElMessage.error(res.data.message)
}
}).catch(err => {
ElMessage.error('更新任务状态失败:' + err)
})
},
getCurrentRow(row) {
this.taskId = row.taskId
}
},
}
</script>
<style scoped>
.el-pagination {
padding-left: 5px;
}
.el-row .el-button {
width: 72px;
margin-left: 0px;
margin-right: 5px;
}
.table-class {
width: 100%;
}
.el-row .el-form-item .el-select-v2 {
width: 100% !important;
}
.el-row .el-form-item .el-input-number {
width: 100% !important;
}
.el-row .el-form-item .el-button {
margin: auto;
}
</style>

View File

@ -0,0 +1,265 @@
<template>
<div style="margin-bottom: 10px">
<el-config-provider :locale="zhCn">
<el-row>
<el-input v-model="queryKey" style="width: 256px; margin-right: 10px;" placeholder="箱号" />
<el-button type="primary" @click="search()">搜索</el-button>
<el-button type="warning" @click="reset()">刷新</el-button>
<el-button type="success" @click="inserthandOut = true">添加</el-button>
<!-- <el-button type="success" @click="refresh()">刷新</el-button> -->
</el-row>
<br />
<el-table :data="vehicles" stripe border v-loading="loading" class="table-class" max-height="650px"
highlight-current-row @row-click="getCurrentRow" :header-cell-style="{ 'text-align': 'center' }"
:cell-style="{ 'text-align': 'center' }">
<el-table-column width="65px" fixed="left">
<template v-slot="scope">
<el-radio :label="scope.row.vehicleId" v-model="vehicleId">&nbsp;</el-radio>
</template>
</el-table-column>
<el-table-column prop="vehicleId" label="箱号" fixed="left" min-width="120px" />
<el-table-column prop="currentLocation" label="当前位置" fixed="left" min-width="120px" />
<el-table-column prop="vehicleStatus" label="料箱状态" :formatter="vehicleStatusFormat" min-width="120px" />
<el-table-column prop="isEmpty" label="是否空箱" :formatter="isEmptyFormat" min-width="120px" />
<el-table-column fixed="right" label="操作" width="200px" v-if="selVehicle == null">
<template v-slot="scope">
<el-button plain type="primary" @click="editCurrentRowVehicle(scope.row)">编辑</el-button>
<el-button plain type="danger" @click="deleteCurrentRowVehicle(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<br />
<el-pagination v-model:current-page="currentPage" v-model:page-size="pageSize" :page-sizes="[10, 25, 50]"
:small="false" :disabled="false" :background="false" :default-page-size="10"
layout="total, sizes, prev, pager, next, jumper" :total="total" @size-change="search"
@current-change="search" />
<el-dialog v-model="dialogVisible" title="托盘信息" width="40%" draggable :show-close="false">
<el-form ref="vehicleFormRef" :model="vehicleFormEntity" :label-position="labelPosition" label-width="100px"
style="max-width: 100%" :rules="rules" status-icon>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="料箱号" prop="vehicleId">
<el-input v-model="vehicleFormEntity.vehicleId" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="当前位置" prop="currentLocation">
<el-input v-model="vehicleFormEntity.currentLocation" placeholder="请输入当前位置" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="是否空箱" prop="isEmpty">
<el-select-v2 v-model="vehicleFormEntity.isEmpty" placeholder="请选择托盘状态"
:options="isEmptyOptions"></el-select-v2>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="托盘状态" prop="vehicleStatus">
<el-select-v2 v-model="vehicleFormEntity.vehicleStatus" placeholder="请选择托盘状态"
:options="vehicleStatusOptions"></el-select-v2>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitVehicleInfo(vehicleFormEntity)">
确定
</el-button>
</span>
</template>
</el-dialog>
</el-config-provider>
<insertHandOut v-model="inserthandOut"/>
</div>
</template>
<script setup>
import insertHandOut from '@/components/inserthandOut.vue'
import { getAllVehicles, updateVehicleInfo, deleteCurrentVehicle } from '@/api/vehicle'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import { ElMessage } from 'element-plus'
import { ref, reactive } from 'vue'
import { vehicleStatusFormatter, locationFormatter } from '@/utils/formatter.js'
</script>
<script>
export default {
name: 'vehicle',
props: ['selVehicle'],
emits: ['update:selVehicle'],
data() {
return {
pageInfo: {},
vehicles: [],
currentPage: 1,
pageSize: 10,
total: 0,
queryKey: '',
loading: true,
dialogVisible: false,
vehicleId: '',
vehicleFormEntity: reactive({}),
labelPosition: 'top',
vehicleFormRef: ref(),
rules: reactive({
locationId: [
{ required: true, message: '请输入库位' }
]
}),
//
isEmptyOptions: [
{
value: 0,
label: '带料'
},
{
value: 1,
label: '空箱'
}
],
//
vehicleStatusOptions: [
{
value: 1,
label: '入库中'
},
{
value: 2,
label: '在库中'
},
{
value: 3,
label: '出库中'
}
],
inserthandOut: false,
}
},
mounted() {
this.search()
},
methods: {
search() {
this.loading = true
this.pageInfo.pageNum = this.currentPage
this.pageInfo.pageSize = this.pageSize
const tableRequest = {
page: this.pageInfo,
param: {
vehicleId: this.queryKey.trim()
},
}
getAllVehicles(tableRequest).then(res => {
const tableResponse = res.data
if (tableResponse.code != 0) {
console.log(tableResponse.code + ':' + tableResponse.message)
ElMessage.error(tableResponse.message)
}
this.vehicles = tableResponse.rows
this.total = tableResponse.total
}).catch(err => {
ElMessage.error('查询托盘信息错误' + err.message)
})
this.loading = false
},
vehicleStatusFormat: (row, column, cellValue, index) => {
return vehicleStatusFormatter(cellValue)
},
locationFormat: (row, column, cellValue, index) => {
return locationFormatter(cellValue)
},
isEmptyFormat: (row, column, cellValue, index) => {
if (cellValue == 0) {
return '带料'
}
if (cellValue == 1) {
return '空箱'
}
},
reset() {
this.queryKey = ''
this.search()
},
editCurrentRowVehicle(row) {
this.vehicleFormEntity = row
this.dialogVisible = true
},
deleteCurrentRowVehicle(row) {
this.vehicleId = row.vehicleId
const vehicle = {
vehicleId: row.vehicleId
}
deleteCurrentVehicle(vehicle).then(res => {
if (res.data.code == 0) {
ElMessage({
message: '删除料箱成功',
type: 'success',
})
this.search()
} else {
ElMessage.error(res.data.message)
}
}).catch(err => {
ElMessage.error('删除料箱信息失败:' + err)
})
},
submitVehicleInfo(formData) {
updateVehicleInfo(formData).then(res => {
if (res.data.code == 0) {
this.dialogVisible = false
ElMessage({
message: '更新料箱信息成功',
type: 'success',
})
this.search()
} else {
ElMessage.error(res.data.message)
}
}).catch(err => {
ElMessage.error('更新料箱信息失败:' + err)
})
},
getCurrentRow(row) {
this.vehicleId = row.vehicleId
this.$emit('update:selVehicle', row)
}
}
}
</script>
<style scoped>
.el-pagination {
padding-left: 5px;
}
.el-row .el-button {
width: 72px;
margin-left: 0px;
margin-right: 5px;
}
.table-class {
width: 100%;
/* font-size: 5px; */
}
.el-row .el-form-item {
width: 10% inherit;
justify-content: center;
}
.el-row .el-form-item .el-select-v2 {
width: 100% !important;
}
.el-row .el-form-item .el-input-number {
width: 100% !important;
}
.el-row .el-form-item .el-button {
margin: auto;
}
</style>

19
wms_client/src/main.js Normal file
View File

@ -0,0 +1,19 @@
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import './styles/index.scss'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
import print from 'vue3-print-nb'
const app = createApp(App)
app.use(store)
app.use(router)
app.use(ElementPlus)
app.use(print)
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
app.mount('#app')

View File

@ -0,0 +1,85 @@
<template>
<el-config-provider :locale="zhCn">
<el-row>
<el-button style="margin-left: 25px;" color="#626aef" v-print="'#printArea'"><el-icon>
<Printer />
</el-icon></el-button>
</el-row>
<el-container class="content">
<!-- <div style="width: 0;height: 0;overflow: hidden"> -->
<div>
<div id="printArea" class="objectDialogFlowPrint">
<div class="myPrint">
<div class="pageWarp" v-for="item in printTabs">
<el-card :body-style="{ padding: '0px', display: 'flex' }">
<qrcode-vue :value="item.name + '&' + item.quantity" :size="size" :foreground="color"
level="H" style="margin: 15px" />
<div style="padding: 14px; text-align: left;">
<span style="font-size: 27pt;font-weight: bold; margin-left: 0;">零件号{{ item.name
}}</span>
<br />
<span style="font-size: 27pt;font-weight: bold; margin-left: 0;">&#8195;{{
item.quantity }}</span>
</div>
</el-card>
</div>
</div>
</div>
</div>
</el-container>
</el-config-provider>
</template>
<script setup>
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import { ref } from 'vue'
import QrcodeVue from 'qrcode.vue'
</script>
<script>
export default {
name: 'printDemo',
components: {
},
data() {
return {
printTabs: [
{
name: '测试物料1',
quantity: 1
},
{
name: '测试物料2',
quantity: 2
}
],
size: ref(200),
color: ref('#000000')
}
},
methods: {
}
}
</script>
<style scoped>
.content {
display: flex;
width: 100%;
}
.objectDialogFlowPrint .pageWarp {
/*这句话很重要,控制时候强制分页 https://www.w3school.com.cn/cssref/pr_page-break-after.asp*/
page-break-after: always;
height: 100%;
width: 100%;
text-align: center;
margin: 5px auto;
padding: auto;
}
.objectDialogFlowPrint .myPrint {
/* 打印的时候是否显示底色 */
print-color-adjust: exact;
}</style>

View File

@ -0,0 +1,62 @@
import { createRouter, createWebHashHistory } from 'vue-router'
import HomeView from '@/views/HomeView.vue'
import stock from '@/layout/stock.vue'
import login from '@/views/login.vue'
import systemCenter from'@/views/SystemCenter.vue'
import goodsInPda from '@/layout/goodsInForPDA.vue'
const routes = [
{
path: '/home',
name: 'home',
component: HomeView,
redirect: '/stock',
children: [
{ path: '/stock', component: stock },// 库存
{ path: '/goodsIn', component: () => import('@/layout/goodsIn.vue') },// 入库
{ path: '/goodsOut', component: () => import('@/layout/goodsOut.vue') },// 出库
{ path: '/inTaskRecord', component: () => import('@/layout/inTaskRecord.vue') },// 入库记录
{ path: '/outTaskRecord', component: () => import('@/layout/outTaskRecord.vue') },// 出库记录
{ path: '/location', component: () => import('@/layout/location.vue') },// 库位
{ path: '/goods', component: () => import('@/layout/goods.vue') },// 物料
{ path: '/standSettings', component: () => import('@/layout/standSettings.vue') },// 站台(库口)设置
{ path: '/config', component: () => import('@/layout/config.vue') },// 系统配置
{ path: '/taskMonitor', component: () => import('@/layout/taskMonitor.vue') },// 任务监控
{ path: '/inventory', component: () => import('@/layout/inventory.vue') },// 盘点
{ path: '/inventoryRecord', component: () => import('@/layout/inventoryRecord.vue') },// 盘点
{ path: '/vehicle', component: () => import('@/layout/vehicle.vue') },// 料箱
]
},
{
path: '/',
name: 'login',
component: login
},
{
path: '/systemCenter',
name: 'systemCenter',
component: systemCenter
},
{
path: '/goodsInPda',
name: 'goodsInPda',
component: goodsInPda
},
]
const router = createRouter({
base: '/',
history: createWebHashHistory(),
routes
})
// 挂载路由导航守卫
router.beforeEach((to, from, next) => {
if (to.path === '/') return next()
// 获取token
const user = sessionStorage.getItem('user')
if (!user) return next('/')
next()
})
export default router

View File

@ -0,0 +1,82 @@
import { createStore } from 'vuex'
export default createStore({
state: {
stateTagsList: [{
id: '21',
labelName: '库存',
path: '/stock'
}],
user: {},
menuList: [],
token: '',
verifier: ''
},
getters: {
getUserName(state) {
return state.user.userName
},
getMenuList(state) {
return state.menuList
},
getToken(state) {
return state.token
},
getVerify(state) {
return state.verifier
},
},
mutations: {
/**
* 选择tag标签
*/
mutationSelectTags(state, data) {
let result = false
for (let i = 0; i < state.stateTagsList.length; i++) {
if (state.stateTagsList[i].path == data.path) {
return result = true
}
}
result === false ? state.stateTagsList.push(data) : ''
},
/**
* 关闭tag标签
*/
mutationCloseTag(state, data) {
let result = state.stateTagsList.findIndex(item => item.path === data.path)
state.stateTagsList.splice(result, 1)
},
/**
* 存储用户信息
*/
mutationUser(state, data) {
state.user = data
sessionStorage.setItem("user", state.user)
},
/**
* 存储菜单信息
*/
mutationMenu(state, data) {
state.menuList = data
sessionStorage.setItem("menuList", state.menuList)
},
/**
* 存储认证
*/
mutationAddVerify(state, data) {
state.verifier = data
},
mutationClearVerify(state) {
state.verifier = ''
},
},
actions: {
},
modules: {
}
})

View File

@ -0,0 +1,9 @@
/* 只需要重写你需要的即可 */
@forward 'element-plus/theme-chalk/src/common/var.scss' with ($colors: ('primary': ('base': green,
),
),
);
// 如果只是按需导入则可以忽略以下内容
// 如果你想导入所有样式:
// @use "element-plus/theme-chalk/src/index.scss" as *;

View File

@ -0,0 +1,23 @@
function revertSeconds(originSeconds) {
const dayRule = 60*60*24
const hourRule = 60*60
const days = Math.floor(originSeconds/dayRule)
const hours = Math.floor((originSeconds%dayRule)/hourRule)
const minutes = Math.floor((originSeconds%hourRule)/60)
const seconds = originSeconds%60
var dueTime = ''
if (days > 0) {
dueTime = dueTime.concat(days).concat('天')
}
if (hours > 0) {
dueTime = dueTime.concat(hours).concat('小时')
}
if (minutes > 0) {
dueTime = dueTime.concat(minutes).concat('分')
}
return dueTime.concat(seconds).concat('秒')
}
export {
revertSeconds
}

View File

@ -0,0 +1,153 @@
import moment from "moment";
import { revertSeconds } from '@/utils/dateUtils'
function timeFormatter(date) {
if (date === null || date === undefined) {
return ''
}
return moment(date).format('yyyy-MM-DD HH:mm:ss');
}
function formatCellValueTime(row, column, cellValue) {
if (cellValue === null || cellValue === '') {
return ''
}
try {
return moment(cellValue).format('yyyy-MM-DD HH:mm:ss')
}catch {
return cellValue
}
}
function dateFormatter(date) {
if (date === null || date === undefined) {
return ''
}
return moment(date).format('yyyy-MM-DD');
}
function dueFormatter(date) {
if (date === null || date === undefined) {
return ''
}
return revertSeconds(moment(new Date().getTime()).diff(moment(date), 'seconds'));
}
function taskStatusFormatter(value) {
switch (value) {
case 0:
return '任务新建,待下发'
case 1:
return '任务已下发'
case 2:
return '任务开始执行'
case 3:
return '出库完成'
case 4:
return '输送线转运中'
case 5:
return '到达拣选站台'
case 6:
return '正在拣货'
case 7:
return '正在回库'
case 8:
return '盘点中'
case 100:
return '任务完成'
case 998:
return '任务取消'
case 999:
return '任务异常'
default:
return '未完成'
}
}
function locationFormatter(locationId) {
if (locationId === null || locationId == undefined) {
return ''
}
const parts = locationId.split('-');
if (parts.length === 4) {
return parts[0] + '排' + parts[1] + '列' + parts[2] + '层' + parts[3] + '深';
} else if (parts.length === 3) {
return parts[0] + '排' + parts[1] + '列' + parts[2] + '层';
} else {
return '格式错误';
}
// const parts = locationId.split('-');
// return parts[0] + '排' + parts[1] + '列' + parts[2] + '层' + parts[3] + '深度';
//return locationId.substr(0, 2) + '排' + locationId.substr(2, 2) + '列' + locationId.substr(4, 2) + '层'
}
function kateTaskStatusFormatter(value) {
switch (value) {
case 0:
return '待下发'
case 1:
return '已下发'
case 2:
return '执行中'
case 3:
return '正在拣货'
case 5:
return '任务完成'
default:
return '异常状态'
}
}
function pickingStatusFormatter(value) {
switch (value) {
case 0:
return '待拣货'
case 1:
return '正在拣货'
case 2:
return '拣货完成'
default:
return '未拣货'
}
}
function vehicleStatusFormatter(value) {
switch (value) {
case 1:
return '入库中'
case 2:
return '在库中'
case 3:
return '出库中'
default:
return '异常状态'
}
}
function kateTaskTypeFormatter(value) {
switch (value) {
case 1:
return '配件'
case 2:
return '合件'
case 3:
return '紧急'
case 4:
return '原包装'
default:
return '任务类型异常'
}
}
export {
timeFormatter,
dateFormatter,
taskStatusFormatter,
locationFormatter,
kateTaskStatusFormatter,
pickingStatusFormatter,
vehicleStatusFormatter,
kateTaskTypeFormatter,
dueFormatter,
formatCellValueTime
}

View File

@ -0,0 +1,9 @@
import { ElLoading } from 'element-plus'
const loading = ElLoading.service({
lock: true,
text: 'Loading',
background: 'rgba(0, 0, 0, 0.7)',
})
export default loading

View File

@ -0,0 +1,146 @@
import axios from 'axios'
import { ElNotification, ElMessageBox, ElMessage, ElLoading } from 'element-plus'
import { getToken } from '@/utils/auth'
import errorCode from '@/utils/errorCode'
import { tansParams, blobValidate } from '@/utils/ruoyi'
import cache from '@/plugins/cache'
import { saveAs } from 'file-saver'
import useUserStore from '@/store/modules/user'
let downloadLoadingInstance;
// 是否显示重新登录
export let isRelogin = { show: false };
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
// 创建axios实例
const service = axios.create({
// axios中请求配置有baseURL选项表示请求URL公共部分
baseURL: import.meta.env.VITE_APP_BASE_API,
// 超时
timeout: 10000
})
// request拦截器
service.interceptors.request.use(config => {
// 是否需要设置 token
const isToken = (config.headers || {}).isToken === false
// 是否需要防止数据重复提交
const isRepeatSubmit = (config.headers || {}).repeatSubmit === false
if (getToken() && !isToken) {
config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
}
// get请求映射params参数
if (config.method === 'get' && config.params) {
let url = config.url + '?' + tansParams(config.params);
url = url.slice(0, -1);
config.params = {};
config.url = url;
}
if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {
const requestObj = {
url: config.url,
data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
time: new Date().getTime()
}
const sessionObj = cache.session.getJSON('sessionObj')
if (sessionObj === undefined || sessionObj === null || sessionObj === '') {
cache.session.setJSON('sessionObj', requestObj)
} else {
const s_url = sessionObj.url; // 请求地址
const s_data = sessionObj.data; // 请求数据
const s_time = sessionObj.time; // 请求时间
const interval = 1000; // 间隔时间(ms),小于此时间视为重复提交
if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {
const message = '数据正在处理,请勿重复提交';
console.warn(`[${s_url}]: ` + message)
return Promise.reject(new Error(message))
} else {
cache.session.setJSON('sessionObj', requestObj)
}
}
}
return config
}, error => {
console.log(error)
Promise.reject(error)
})
// 响应拦截器
service.interceptors.response.use(res => {
// 未设置状态码则默认成功状态
const code = res.data.code || 200;
// 获取错误信息
const msg = errorCode[code] || res.data.msg || errorCode['default']
// 二进制数据则直接返回
if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
return res.data
}
if (code === 401) {
if (!isRelogin.show) {
isRelogin.show = true;
ElMessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => {
isRelogin.show = false;
useUserStore().logOut().then(() => {
location.href = '/index';
})
}).catch(() => {
isRelogin.show = false;
});
}
return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
} else if (code === 500) {
ElMessage({ message: msg, type: 'error' })
return Promise.reject(new Error(msg))
} else if (code === 601) {
ElMessage({ message: msg, type: 'warning' })
return Promise.reject(new Error(msg))
} else if (code !== 200) {
ElNotification.error({ title: msg })
return Promise.reject('error')
} else {
return Promise.resolve(res.data)
}
},
error => {
console.log('err' + error)
let { message } = error;
if (message == "Network Error") {
message = "后端接口连接异常";
} else if (message.includes("timeout")) {
message = "系统接口请求超时";
} else if (message.includes("Request failed with status code")) {
message = "系统接口" + message.substr(message.length - 3) + "异常";
}
ElMessage({ message: message, type: 'error', duration: 5 * 1000 })
return Promise.reject(error)
}
)
// 通用下载方法
export function download(url, params, filename, config) {
downloadLoadingInstance = ElLoading.service({ text: "正在下载数据,请稍候", background: "rgba(0, 0, 0, 0.7)", })
return service.post(url, params, {
transformRequest: [(params) => { return tansParams(params) }],
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
responseType: 'blob',
...config
}).then(async (data) => {
const isLogin = await blobValidate(data);
if (isLogin) {
const blob = new Blob([data])
saveAs(blob, filename)
} else {
const resText = await data.text();
const rspObj = JSON.parse(resText);
const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']
ElMessage.error(errMsg);
}
downloadLoadingInstance.close();
}).catch((r) => {
console.error(r)
ElMessage.error('下载文件出现错误,请联系管理员!')
downloadLoadingInstance.close();
})
}
export default service

View File

@ -0,0 +1,165 @@
<template>
<el-container class="wms-home">
<el-header class="header">
<div class="icon-img">
<el-image :src="icon_img_url" :fit="'fill'" />
</div>
<div class="title">
<span>WMS仓库管理系统</span>
</div>
<div class="user">{{ userName }}</div>
</el-header>
<el-container class="content">
<el-aside class="aside">
<el-scrollbar style="max-height: 95%;">
<sideMenu></sideMenu>
</el-scrollbar>
<div :class="$route.path === '/location' ? 'locationsSel' : 'locations'" @click="openLocations">
<el-icon>
<View />
</el-icon>
<span>库位监控</span>
</div>
</el-aside>
<el-container>
<el-header class="tag">
<appTag></appTag>
</el-header>
<el-main>
<!-- 路由占位符 -->
<el-scrollbar>
<router-view v-slot="{ Component }">
<!-- // TODO keepAlive -->
<keep-alive>
<component :is="Component" />
</keep-alive>
</router-view>
</el-scrollbar>
</el-main>
<el-footer class="footer">© 1970-2023 江苏菲达宝开电气股份有限公司</el-footer>
</el-container>
</el-container>
</el-container>
</template>
<script setup>
// @ is an alias to /src
import sideMenu from '@/components/sideMenu.vue'
import appTag from '@/components/appTag.vue'
const icon_img_url = require('@/assets/fdbk_log.png')
</script>
<script>
export default {
name: 'HomeView',
components: {
sideMenu,
appTag
},
computed: {
userName() {
return this.$store.state.user.userName
}
},
methods: {
openLocations() {
this.$store.commit('mutationSelectTags', {
id: '25',
labelName: '库位监控',
path: '/location'
})
this.$router.push('/location')
}
}
}
</script>
<style scoped>
.wms-home {
height: 100%;
background-color: #CCCCCC;
}
.content {
height: 95%;
background-color: #FFFFFF;
}
.header {
/* background-color: #66CCFF; */
background-color: #D9E3EE;
display: flex;
align-items: center;
height: 5%;
/* font-size: 15px; */
}
.aside {
background-color: #fff;
height: 100%;
width: 10%;
border-right: 1px solid #66CCFF;
}
.footer {
background-color: #F0FFFF;
display: flex;
justify-content: center;
flex-direction: column;
height: 3%;
}
.tag {
padding-left: 1px;
display: flex;
align-items: center;
height: 30px;
border-bottom: solid 1px;
}
.icon-img {
height: 100%;
width: 3%;
}
.icon-img .el-image {
height: 100%;
width: 100%;
}
.title {
margin-left: 2px;
}
.user {
margin-left: auto;
}
.locations {
padding: 5px;
display: flex;
justify-content: center;
align-items: center;
height: 3.8%;
border-top: solid 1px;
cursor: pointer;
color: #5A9CF8;
}
.locationsSel {
padding: 5px;
display: flex;
justify-content: center;
align-items: center;
height: 3.8%;
border-top: solid 1px;
cursor: pointer;
background-color: #5A9CF8;
color: #000;
}
.locations:hover {
background-color: #5A9CF8;
color: #000;
}
</style>

View File

@ -0,0 +1,112 @@
<template>
<body id="login-page">
<el-form class="login-container" label-position="left" label-width="0px">
<h3 class="login_title">请选择系统</h3>
<el-form-item style="width: 100%">
<el-button color="#87CEFA" style="width: 100%; border: none" @click="loginToWms">WMS系统</el-button>
</el-form-item>
<!-- <el-form-item style="width: 100%">
<el-button color="#87CEEB" style="width: 100%; border: none" @click="loginToPda">手持入库系统</el-button>
</el-form-item>
<el-form-item style="width: 100%">
<el-button color="#AFEEEE" style="width: 100%; border: none" @click="loginToSideScan">线边扫码系统</el-button>
</el-form-item>
<el-form-item style="width: 100%">
<el-button color="#ADD8E6" style="width: 100%; border: none" @click="loginToWcs">WCS系统</el-button>
</el-form-item>
<el-form-item style="width: 100%">
<el-button color="#B0E0E6" style="width: 100%; border: none" @click="loginToMonitor">监控系统</el-button>
</el-form-item> -->
</el-form>
</body>
</template>
<script setup>
import { getUser } from '@/api/login.js'
import { ElMessage, ElLoading } from 'element-plus'
import { onMounted } from 'vue';
import store from '@/store'
import router from '@/router'
const user = store.getters.getUserNam//
const token = store.getters.getToken//
// WMS
const loginToWms = () => {
router.replace({ path: '/home' })
}
const loginToPda = () => {
router.replace({ path: '/goodsInPda' })
}
const loginToSideScan = () => {
router.replace({ path: '/sideScan' })
}
// WCS
const loginToWcs = () => {
const wcsUrl = `https://cxlasrs.ecorp.cat.com/wcs/#/login?user=user&pwd=user`
window.location.href = wcsUrl//
}
const loginToMonitor = () => {
const mpnitorUrl = `https://cxlasrs.ecorp.cat.com?user=${user}&token=${token}`
window.location.href = mpnitorUrl//
}
onMounted(() => {
if (router.currentRoute.value.query.code != undefined) {
console.log(router.currentRoute.value.query.code)
const loading = ElLoading.service({
lock: true,
text: 'Loading',
background: 'rgba(0, 0, 0, 0.7)',
})
const codeInfo = {
code: router.currentRoute.value.query.code,
state: router.currentRoute.value.query.state
}
getUser(codeInfo).then(res => {
loading.close()
if (res.data.code == 0) {
store.commit('mutationUser', res.data.returnData.user)//
store.commit('mutationMenu', res.data.returnData.menuList)//
router.replace({ path: '/' })
} else {
ElMessage.error(res.data.message)
}
}).catch(err => {
console.log(err)
loading.close()
ElMessage.error('登录失败!')
})
}
})
</script>
<style scoped>
#login-page {
/* background: url("../assets/img/bg.jpg") no-repeat; */
background-position: center;
height: 100%;
width: 100%;
background-size: cover;
position: fixed;
}
body {
margin: 0px;
}
.login-container {
border-radius: 15px;
background-clip: padding-box;
margin: 90px auto;
width: 350px;
padding: 35px 35px 15px 35px;
background: #fff;
border: 1px solid #eaeaea;
box-shadow: 0 0 25px #cac6c6;
}
.login_title {
margin: 0px auto 40px auto;
text-align: center;
color: #505458;
}
</style>

View File

@ -0,0 +1,83 @@
<template>
<body id="login-page">
<el-form class="login-container" :model="loginForm" label-position="left" label-width="0px">
<h3 class="login_title">系统登录</h3>
<el-form-item>
<el-input type="text" v-model="loginForm.loginAccount" auto-complete="off" placeholder="账号"></el-input>
</el-form-item>
<el-form-item>
<el-input type="password" v-model="loginForm.loginPassword" auto-complete="off" placeholder="密码"></el-input>
</el-form-item>
<el-form-item style="width: 100%">
<el-button type="primary" style="width: 100%; border: none" @click="login">登录</el-button>
</el-form-item>
</el-form>
</body>
</template>
<script setup>
import { loginWithAuth } from '@/api/login.js'
import { ElMessage, ElLoading } from 'element-plus'
import { reactive } from 'vue';
import store from '@/store'
import router from '@/router'
const loginForm = reactive({
loginAccount: "",
loginPassword: "",
})
//
const login = () => {
const loading = ElLoading.service({
lock: true,
text: 'Loading',
background: 'rgba(0, 0, 0, 0.7)',
})
loginWithAuth(loginForm).then(res => {
loading.close()
if (res.data.code == 0) {
store.commit('mutationUser', res.data.returnData.user)//
store.commit('mutationMenu', res.data.returnData.menuList)//
// router.replace({ path: '/' })//
router.replace({ path: '/systemCenter' })//
} else {
ElMessage.error(res.data.message)
}
}).catch(err => {
console.log(err)
loading.close()
ElMessage.error('登录失败!')
})
}
</script>
<style scoped>
#login-page {
/* background: url("../assets/img/bg.jpg") no-repeat; */
background-position: center;
height: 100%;
width: 100%;
background-size: cover;
position: fixed;
}
body {
margin: 0px;
}
.login-container {
border-radius: 15px;
background-clip: padding-box;
margin: 90px auto;
width: 350px;
padding: 35px 35px 15px 35px;
background: #fff;
border: 1px solid #eaeaea;
box-shadow: 0 0 25px #cac6c6;
}
.login_title {
margin: 0px auto 40px auto;
text-align: center;
color: #505458;
}
</style>

20
wms_client/vue.config.js Normal file
View File

@ -0,0 +1,20 @@
const { defineConfig } = require('@vue/cli-service')
const NodePolyfillPlugin = require('node-polyfill-webpack-plugin')
module.exports = defineConfig({
transpileDependencies: true,
configureWebpack: {
plugins: [new NodePolyfillPlugin()]
},
devServer: {
port: 12306, // 端口
proxy: {
'/authorize': { // 若请求的前缀不是这个'/wms',那请求就不会走代理服务器
target: "https://login.microsoftonline.com/caterpillar.onmicrosoft.com/", //这里写路径
pathRewrite: { '^/authorize': '' }, //将所有含/wms路径的去掉/wms转发给服务器
ws: true, //用于支持websocket
changeOrigin: true //用于控制请求头中的host值
},
}
},
})

BIN
wms_client/wms_client.zip Normal file

Binary file not shown.

1081
wms_fdbk_xuzhou.sql Normal file

File diff suppressed because it is too large Load Diff

36
wms_serve/.gitignore vendored Normal file
View File

@ -0,0 +1,36 @@
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
/log
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
.log
### VS Code ###
.vscode/
log

316
wms_serve/mvnw vendored Normal file
View File

@ -0,0 +1,316 @@
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Maven Start Up Batch script
#
# Required ENV vars:
# ------------------
# JAVA_HOME - location of a JDK home dir
#
# Optional ENV vars
# -----------------
# M2_HOME - location of maven2's installed home dir
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
# e.g. to debug Maven itself, use
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ] ; then
if [ -f /usr/local/etc/mavenrc ] ; then
. /usr/local/etc/mavenrc
fi
if [ -f /etc/mavenrc ] ; then
. /etc/mavenrc
fi
if [ -f "$HOME/.mavenrc" ] ; then
. "$HOME/.mavenrc"
fi
fi
# OS specific support. $var _must_ be set to either true or false.
cygwin=false;
darwin=false;
mingw=false
case "`uname`" in
CYGWIN*) cygwin=true ;;
MINGW*) mingw=true;;
Darwin*) darwin=true
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
if [ -z "$JAVA_HOME" ]; then
if [ -x "/usr/libexec/java_home" ]; then
export JAVA_HOME="`/usr/libexec/java_home`"
else
export JAVA_HOME="/Library/Java/Home"
fi
fi
;;
esac
if [ -z "$JAVA_HOME" ] ; then
if [ -r /etc/gentoo-release ] ; then
JAVA_HOME=`java-config --jre-home`
fi
fi
if [ -z "$M2_HOME" ] ; then
## resolve links - $0 may be a link to maven's home
PRG="$0"
# need this for relative symlinks
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG="`dirname "$PRG"`/$link"
fi
done
saveddir=`pwd`
M2_HOME=`dirname "$PRG"`/..
# make it fully qualified
M2_HOME=`cd "$M2_HOME" && pwd`
cd "$saveddir"
# echo Using m2 at $M2_HOME
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --unix "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
fi
# For Mingw, ensure paths are in UNIX format before anything is touched
if $mingw ; then
[ -n "$M2_HOME" ] &&
M2_HOME="`(cd "$M2_HOME"; pwd)`"
[ -n "$JAVA_HOME" ] &&
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
fi
if [ -z "$JAVA_HOME" ]; then
javaExecutable="`which javac`"
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
# readlink(1) is not available as standard on Solaris 10.
readLink=`which readlink`
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
if $darwin ; then
javaHome="`dirname \"$javaExecutable\"`"
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
else
javaExecutable="`readlink -f \"$javaExecutable\"`"
fi
javaHome="`dirname \"$javaExecutable\"`"
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
JAVA_HOME="$javaHome"
export JAVA_HOME
fi
fi
fi
if [ -z "$JAVACMD" ] ; then
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD="`\\unset -f command; \\command -v java`"
fi
fi
if [ ! -x "$JAVACMD" ] ; then
echo "Error: JAVA_HOME is not defined correctly." >&2
echo " We cannot execute $JAVACMD" >&2
exit 1
fi
if [ -z "$JAVA_HOME" ] ; then
echo "Warning: JAVA_HOME environment variable is not set."
fi
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
if [ -z "$1" ]
then
echo "Path not specified to find_maven_basedir"
return 1
fi
basedir="$1"
wdir="$1"
while [ "$wdir" != '/' ] ; do
if [ -d "$wdir"/.mvn ] ; then
basedir=$wdir
break
fi
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
if [ -d "${wdir}" ]; then
wdir=`cd "$wdir/.."; pwd`
fi
# end of workaround
done
echo "${basedir}"
}
# concatenates all lines of a file
concat_lines() {
if [ -f "$1" ]; then
echo "$(tr -s '\n' ' ' < "$1")"
fi
}
BASE_DIR=`find_maven_basedir "$(pwd)"`
if [ -z "$BASE_DIR" ]; then
exit 1;
fi
##########################################################################################
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
# This allows using the maven wrapper in projects that prohibit checking in binary data.
##########################################################################################
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found .mvn/wrapper/maven-wrapper.jar"
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
fi
if [ -n "$MVNW_REPOURL" ]; then
jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
else
jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
fi
while IFS="=" read key value; do
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
esac
done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
if [ "$MVNW_VERBOSE" = true ]; then
echo "Downloading from: $jarUrl"
fi
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
if $cygwin; then
wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
fi
if command -v wget > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found wget ... using wget"
fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
else
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
fi
elif command -v curl > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found curl ... using curl"
fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
curl -o "$wrapperJarPath" "$jarUrl" -f
else
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Falling back to using Java to download"
fi
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
# For Cygwin, switch paths to Windows format before running javac
if $cygwin; then
javaClass=`cygpath --path --windows "$javaClass"`
fi
if [ -e "$javaClass" ]; then
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Compiling MavenWrapperDownloader.java ..."
fi
# Compiling the Java class
("$JAVA_HOME/bin/javac" "$javaClass")
fi
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
# Running the downloader
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Running MavenWrapperDownloader.java ..."
fi
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
fi
fi
fi
fi
##########################################################################################
# End of extension
##########################################################################################
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
if [ "$MVNW_VERBOSE" = true ]; then
echo $MAVEN_PROJECTBASEDIR
fi
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --path --windows "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
fi
# Provide a "standardized" way to retrieve the CLI args that will
# work with both Windows and non-Windows executions.
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
export MAVEN_CMD_LINE_ARGS
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
exec "$JAVACMD" \
$MAVEN_OPTS \
$MAVEN_DEBUG_OPTS \
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
"-Dmaven.home=${M2_HOME}" \
"-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"

188
wms_serve/mvnw.cmd vendored Normal file
View File

@ -0,0 +1,188 @@
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM https://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Maven Start Up Batch script
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM M2_HOME - location of maven2's installed home dir
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM set title of command window
title %0
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
:skipRcPre
@setlocal
set ERROR_CODE=0
@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
echo.
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init
echo.
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
@REM ==== END VALIDATION ====
:init
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir
:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir
:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"
:endDetectBaseDir
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
:endReadAdditionalConfig
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
)
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
if "%MVNW_VERBOSE%" == "true" (
echo Found %WRAPPER_JAR%
)
) else (
if not "%MVNW_REPOURL%" == "" (
SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
)
if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %DOWNLOAD_URL%
)
powershell -Command "&{"^
"$webclient = new-object System.Net.WebClient;"^
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
"}"^
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
"}"
if "%MVNW_VERBOSE%" == "true" (
echo Finished downloading %WRAPPER_JAR%
)
)
@REM End of extension
@REM Provide a "standardized" way to retrieve the CLI args that will
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*
%MAVEN_JAVA_EXE% ^
%JVM_CONFIG_MAVEN_PROPS% ^
%MAVEN_OPTS% ^
%MAVEN_DEBUG_OPTS% ^
-classpath %WRAPPER_JAR% ^
"-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
%WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
:error
set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%"=="on" pause
if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
cmd /C exit /B %ERROR_CODE%

159
wms_serve/pom.xml Normal file
View File

@ -0,0 +1,159 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com</groupId>
<artifactId>WMS</artifactId>
<version>1.0</version>
<name>WMS</name>
<description>WMS</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- 自定义验证注解 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!--常用工具类 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!-- JSON工具类 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.21</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
<!-- MAP工具 -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.1-jre</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.3.0</version>
</dependency>
<dependency>
<groupId>com.github.jsqlparser</groupId>
<artifactId>jsqlparser</artifactId>
<version>4.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpmime -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.5.14</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.3</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.oltu.oauth2/org.apache.oltu.oauth2.client -->
<dependency>
<groupId>org.apache.oltu.oauth2</groupId>
<artifactId>org.apache.oltu.oauth2.client</artifactId>
<version>1.0.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.auth0/java-jwt -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>4.4.0</version>
</dependency>
<!--Swagger-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>10.1.25</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>16</source>
<target>16</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,3 @@
Manifest-Version: 1.0
Main-Class: com.wuxiShenNan_W8.WmsTestversionApplication

View File

@ -0,0 +1,24 @@
package com.wms;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@SpringBootApplication
@EnableScheduling
@EnableTransactionManagement
@MapperScan("com.wms.mapper")
public class WmsApplication {
/**
* 主函数程序的入口
*
* @param args 命令行参数以字符串数组形式传入
*/
public static void main(String[] args) {
SpringApplication.run(WmsApplication.class, args);
}
}

View File

@ -0,0 +1,708 @@
package com.wms.bussiness;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.wms.constants.enums.*;
import com.wms.controller.BaseController;
import com.wms.entity.app.ResponseEntity;
import com.wms.entity.app.container.ContainerApiLocalResponse;
import com.wms.entity.app.container.CreateInstoreTaskRequest;
import com.wms.entity.app.container.SendContainerTaskRequest;
import com.wms.entity.app.wcs.WcsTask;
import com.wms.entity.table.*;
import com.wms.mapper.LocationMapper;
import com.wms.mapper.StockMapper;
import com.wms.mapper.TaskMapper;
import com.wms.mapper.VehicleMapper;
import com.wms.service.*;
import com.wms.utils.HttpUtils;
import com.wms.utils.StringUtils;
import com.wms.utils.storage.LocationUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.*;
/**
* 定期任务类
*/
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class JobComponent extends BaseController {
/**
* 任务服务
*/
private final TaskService taskService;
/**
* 任务 Mapper
*/
private final TaskMapper taskMapper;
/**
* 载具/料箱 服务
*/
private final VehicleService vehicleService;
/**
* 库位服务
*/
private final LocationService locationService;
/**
* 库位 Mapper
*/
private final LocationMapper locationMapper;
/**
* 库位操作类
*/
private final LocationUtils locationUtils;
/**
* 站台服务
*/
private final StandService standService;
/**
* 配置服务
*/
private final ConfigService configService;
/**
* 库存服务
*/
private final StockService stockService;
private final TaskRecordService taskRecordService;
private final StockMapper stockMapper;
private final VehicleMapper vehicleMapper;
@Scheduled(fixedDelay = 1000)
public void sendTasksToWcs() {
try {
// 查找待下发的任务
Task taskForQuery = new Task();
taskForQuery.setTaskStatus(WmsTaskStatus.NEW.getCode());
List<Task> tasks = taskService.selTasks(taskForQuery);
if(tasks == null) {
logger.error("定时器下发任务发生异常,数据库查询任务列表失败");
return;
}
for(Task task : tasks){
if(task.getTaskType().equals(TaskType.IN.getCode())) {
sendTasksInToWcs(task);
return;
}
if(task.getTaskType().equals(TaskType.OUT.getCode()) || task.getTaskType().equals(TaskType.INVENTORY.getCode())){
sendTasksOutToWcs(task);
return;
}
if(task.getTaskType().equals(TaskType.MOVE.getCode())){
sendTasksMoveToWcs(task);
return;
}
}
}catch (Exception exception){
logger.error("定时器下发任务发生异常:{}", exception.toString());
}
}
/**
* 发送入库任务给WCS
* @param task 任务
*/
private void sendTasksInToWcs(Task task) {
try {
List<Location> thisLocations = locationService.selLocations(new Location(task.getDestination()));
if(thisLocations == null) {
logger.warn("下发入库任务查询库位详细信息失败,数据库网络连接异常,任务号:{}", task.getTaskId());
return;
}
if(thisLocations.isEmpty()) {
logger.warn("下发入库任务查询库位详细信息异常,不存在详细信息,该库位可能不存在,任务号:{}", task.getTaskId());
Task taskForUpdate = new Task();
taskForUpdate.setTaskId(task.getTaskId());
taskForUpdate.setTaskStatus(WmsTaskStatus.EXCEPTION.getCode());
taskForUpdate.setRemark1("该库位不存在");
taskService.executeTask(taskForUpdate);
return;
}
Location thisLocation = thisLocations.get(0);
if(thisLocation.getAreaId() == 1){
List<WcsTask> request = new ArrayList<>();
// 创建发送的任务
WcsTask tempTask = new WcsTask();
tempTask.setTaskId(task.getTaskId());
tempTask.setTaskType(TaskType.IN.getCode());
tempTask.setOrigin(task.getOrigin());
tempTask.setDestination(task.getDestination());
tempTask.setVehicleNo(task.getVehicleNo());
tempTask.setVehicleSize(1);
tempTask.setWeight(task.getWeight() == null ? 0 : task.getWeight());
tempTask.setPriority(task.getTaskPriority());
request.add(tempTask);
// 发送任务
ResponseEntity result = JSON.parseObject(HttpUtils.sendHttpPostWithoutToken(UrlEnums.URL_WMS_TO_WCS_SEND_TASK.getValue(), JSON.toJSONString(request)), ResponseEntity.class);
if (result != null && Objects.equals(ResponseCode.OK.getCode(), result.getCode())) {
logger.info("下发立库入库任务成功任务ID{},任务信息:{}", tempTask.getTaskId(), JSON.toJSONString(request));
Task taskForUpdate = new Task();
taskForUpdate.setTaskId(task.getTaskId());
taskForUpdate.setTaskStatus(WmsTaskStatus.WAIT.getCode());
taskService.executeTask(taskForUpdate);
return;
}
logger.info("下发立库入库任务失败任务ID{},信息:{}", tempTask.getTaskId(), JSON.toJSONString(result));
}
// else { //四向车库
// //List<WcsTask> request = new ArrayList<>();
// // 创建发送的任务
// String uuid = UUID.randomUUID().toString();
// CreateInstoreTaskRequest request = new CreateInstoreTaskRequest();
// request.setRequestId(uuid);
// request.setKey(StringUtils.containerMd5(uuid).toUpperCase());
// request.setPalletNo(task.getVehicleNo());
// request.setHeight("0");
// request.setWeight("0");
// request.setFromCellNo(task.getOrigin());
// // 发送任务
// String requestString = JSON.toJSONString(request);
// String responseString = HttpUtils.sendHttpPostWithoutToken(UrlEnums.URL_WMS_TO_WCS_CONTAINERIN_TASK.getValue(), requestString);
// if (responseString == null || responseString.isEmpty()) {
// logger.error("Response string is null or empty");
// }
// ContainerApiLocalResponse result = JSON.parseObject(responseString, ContainerApiLocalResponse.class);
// if (result != null && result.getCode().equals("200")) {
// logger.info("下发托盘库入库任务成功任务ID{}", task.getTaskId());
// Task taskForUpdate = new Task();
// taskForUpdate.setTaskId(task.getTaskId());
// taskForUpdate.setTaskStatus(WmsTaskStatus.WAIT.getCode());
// taskService.executeTask(taskForUpdate);
// return;
// }
// logger.info("下发托盘库入库任务失败任务ID{},信息:{}", task.getTaskId(), JSON.toJSONString(result));
// }
}catch (Exception exception){
logger.error("下发入库任务发生异常:{}", exception.toString());
}
}
/**
* 发送出库任务给WCS
* @param task 任务
*/
private void sendTasksOutToWcs(Task task) {
/* 检查该库位前一个深度是否存在库存,若存在库存则生成一个移库任务,此任务暂不下发 */
List<Location> thisLocations = locationService.selLocations(new Location(task.getOrigin()));
if(thisLocations == null) {
logger.warn("下发出库任务查询库位详细信息失败,数据库网络连接异常,任务号:{}", task.getTaskId());
logger.info("下发出库任务查询库位详细信息失败,数据库网络连接异常");
return;
}
if(thisLocations.isEmpty()) {
logger.warn("下发出库任务查询库位详细信息异常,不存在详细信息,该库位可能不存在,任务号:{}", task.getTaskId());
logger.info("下发出库任务查询库位详细信息异常,不存在详细信息,该库位可能不存在");
Task taskForUpdate = new Task();
taskForUpdate.setTaskId(task.getTaskId());
taskForUpdate.setTaskStatus(WmsTaskStatus.EXCEPTION.getCode());
taskForUpdate.setRemark1("该库位不存在");
taskService.executeTask(taskForUpdate);
return;
}
Location thisLocation = thisLocations.get(0); // 找出当前库位详细信息
int depth = thisLocation.getDepth();
while (depth > 1) {
depth--;
/* 检查该库位有没有任务,若有则退出函数,若没有则检查有没有库存,若没有库存则继续,若有库存则生成一个移库任务,生成之后退出函数 */
Location beforLocationsQuery = new Location();
// logger.info("{},{},{},{},{}",thisLocation.getAreaId(),thisLocation.getQueue(),thisLocation.getLine(),thisLocation.getLayer(),depth);
beforLocationsQuery.setAreaId(thisLocation.getAreaId());
//beforLocationsQuery.setQueue(thisLocation.getQueue());
beforLocationsQuery.setLine(thisLocation.getLine());
beforLocationsQuery.setLayer(thisLocation.getLayer());
beforLocationsQuery.setLocationType(1);
beforLocationsQuery.setDepth(depth);
List<Location> beforLocations = locationService.selLocations(beforLocationsQuery);
if(beforLocations == null) {
logger.warn("下发出库任务查询库位详细信息失败,数据库网络连接异常,任务号:{}", task.getTaskId());
logger.info("下发出库任务查询库位详细信息失败,数据库网络连接异常");
return;
}
if(beforLocations.isEmpty()) {
logger.info("beforLocations.isEmpty()");
return;
}
Location beforLocation = beforLocations.get(0); // 前一个库位
List<Task> notCompleteTasks = taskMapper.haveNotCompleteTask(beforLocation.getLocationId());
if(notCompleteTasks == null) {
logger.info("notCompleteTasks为null");
return;
}
if(!notCompleteTasks.isEmpty()) {
logger.info("存在未完成的任务,退出函数");
return; // 存在未完成的任务退出函数
}
// 检查是否有库存因为存在空框所以不在库存表中检验
Vehicle nextVehicle = new Vehicle();
nextVehicle.setCurrentLocation(beforLocation.getLocationId());
List<Vehicle> beforVehicleCheckIfEmpty = vehicleMapper.selVehicles(nextVehicle);
if(beforVehicleCheckIfEmpty == null) {
logger.info("beforLocationsCheckIfEmpty == null");
return;
}
if(beforVehicleCheckIfEmpty.isEmpty()) {
logger.info("位置{}没有框",beforLocation.getLocationId());
continue; // 没有库存继续
}
/* 生成一个移库任务 */
/* 查找一个空库位 */
Location emptyLocation = new Location();
emptyLocation.setLocationStatus(LocationStatus.EMPTY.getCode());
emptyLocation.setAreaId(beforLocation.getAreaId());
List<Location> emptyLocations = locationMapper.selLocations(emptyLocation);
if(emptyLocations == null) {
logger.info("emptyLocations == null");
return;
}
if(emptyLocations.isEmpty()){
logger.warn("移库没有可用库位,任务号:{}", task.getTaskId());
logger.info("移库没有可用库位");
return; // 移库没有可用库位
}
Location emptyLocationItem = locationUtils.checkCanUse(emptyLocations); // 取得新库位
if(emptyLocationItem == null) {
logger.info("emptyLocationItem == null");
return; // 没有可用库位或者m库位存在干涉
}
// 锁定旧库位库存
stockMapper.updateStockStatusWithLocationId(beforLocation.getLocationId(), StockStatus.LOCK.getCode());
// 锁定新库位
Location locationForUpdate = new Location();
locationForUpdate.setLocationId(emptyLocationItem.getLocationId());
locationForUpdate.setLocationStatus(LocationStatus.OCCUPY.getCode());
locationMapper.modifyLocation(locationForUpdate);
//创建移库任务
Task moveTask = new Task();
moveTask.setTaskId(String.valueOf(Calendar.getInstance().getTimeInMillis()));
moveTask.setTaskType(TaskType.MOVE.getCode());
moveTask.setTaskGroup(task.getTaskGroup());
moveTask.setTaskStatus(OrderOutStatusEnum.CREATED.getCode());
moveTask.setOrigin(beforLocation.getLocationId());
moveTask.setDestination(emptyLocationItem.getLocationId());
moveTask.setPickStand(null);
moveTask.setWeight(0.0);
moveTask.setVehicleNo(beforVehicleCheckIfEmpty.get(0).getVehicleId());
moveTask.setCreateTime(new Date());
moveTask.setUserName("WMS");
if(depth == 2){
moveTask.setTaskPriority(8);
} else if (depth == 1) {
moveTask.setTaskPriority(9);
}
if (beforVehicleCheckIfEmpty.get(0).getIsEmpty() == 1){
moveTask.setRemark1("空框");
}else {
moveTask.setRemark1("带料");
}
int a = taskService.addTask(moveTask);
if (a == 1 && depth == 2){
logger.info("生成移库任务成功,任务号:{}", moveTask.getTaskId());
continue;
} else if (a == 1 && depth == 1) {
return;
} else {
logger.info("生成移库任务失败,任务号:{}", moveTask.getTaskId());
}
return;
}
if(thisLocation.getAreaId() == 1) { // 宝开立库
List<WcsTask> request = new ArrayList<>();
// 创建发送的任务
WcsTask tempTask = new WcsTask();
tempTask.setTaskId(task.getTaskId());
tempTask.setTaskType(TaskType.OUT.getCode());
tempTask.setOrigin(task.getOrigin());
tempTask.setDestination(task.getDestination());
tempTask.setVehicleNo(task.getVehicleNo());
tempTask.setVehicleSize(1);
tempTask.setWeight(task.getWeight() == null ? 0 : task.getWeight());
tempTask.setPriority(task.getTaskPriority());
request.add(tempTask);
// 发送任务
ResponseEntity result = JSON.parseObject(HttpUtils.sendHttpPostWithoutToken(UrlEnums.URL_WMS_TO_WCS_SEND_TASK.getValue(), JSON.toJSONString(request)), ResponseEntity.class);
if (result != null && Objects.equals(ResponseCode.OK.getCode(), result.getCode())) {
logger.info("下发立库出库任务成功任务ID{}", tempTask.getTaskId());
Task taskForUpdate = new Task();
taskForUpdate.setTaskId(task.getTaskId());
taskForUpdate.setTaskStatus(WmsTaskStatus.WAIT.getCode());
taskService.executeTask(taskForUpdate);
return;
}
logger.info("下发立库出库任务失败任务ID{},信息:{}result结果{}", tempTask.getTaskId(), JSON.toJSONString(result),result.getCode());
} else { // 四向车库
String uuid = UUID.randomUUID().toString();
SendContainerTaskRequest request = new SendContainerTaskRequest();
request.setRequestid(uuid);
request.setKey(StringUtils.containerMd5(uuid).toUpperCase());
request.setWmstaskid(task.getTaskId());
request.setPalletno(task.getVehicleNo());
request.setTasktype("2"); // 出库
request.setFromcellno(task.getOrigin());
request.setTocellno("111"); // ???????
String requestString = JSON.toJSONString(request);
String responseString = HttpUtils.sendHttpPostWithoutToken(UrlEnums.URL_WMS_TO_WCS_CONTAINER_TASK.getValue(), requestString);
//JSONObject jsonResponse = JSON.parseObject(responseString);
ContainerApiLocalResponse result = JSON.parseObject(responseString, ContainerApiLocalResponse.class);
if(result != null && result.getCode().equals("200")) {
logger.info("下发四向车出库任务成功任务ID{}", task.getTaskId());
Task taskForUpdate = new Task();
taskForUpdate.setTaskId(task.getTaskId());
taskForUpdate.setTaskStatus(WmsTaskStatus.WAIT.getCode());
taskService.executeTask(taskForUpdate);
return;
}
logger.info("下发四向车出库任务失败任务ID{},信息:{}", task.getTaskId(), JSON.toJSONString(result));
}
}
/**
* 发送移库任务给WCS
* @param task 任务
*/
private void sendTasksMoveToWcs(Task task){
/* 检查该库位前一个深度是否存在库存,若存在库存则生成一个移库任务,此任务暂不下发 */
List<Location> thisLocations = locationService.selLocations(new Location(task.getOrigin()));
if(thisLocations == null) {
logger.info("下发移库任务查询库位详细信息失败,数据库网络连接异常");
return;
}
if(thisLocations.isEmpty()) {
logger.info("下发移库任务查询库位详细信息异常,不存在详细信息,该库位可能不存在");
Task taskForUpdate = new Task();
taskForUpdate.setTaskId(task.getTaskId());
taskForUpdate.setTaskStatus(WmsTaskStatus.EXCEPTION.getCode());
taskForUpdate.setRemark1("该库位不存在");
taskService.executeTask(taskForUpdate);
return;
}
Location thisLocation = thisLocations.get(0); // 找出当前库位详细信息
int depth = thisLocation.getDepth();
while (depth > 1) {
depth--;
/* 检查该库位有没有任务,若有则退出函数,若没有则检查有没有库存,若没有库存则继续,若有库存则生成一个移库任务,生成之后退出函数 */
Location beforLocationsQuery = new Location();
// logger.info("{},{},{},{},{}",thisLocation.getAreaId(),thisLocation.getQueue(),thisLocation.getLine(),thisLocation.getLayer(),depth);
beforLocationsQuery.setAreaId(thisLocation.getAreaId());
//beforLocationsQuery.setQueue(thisLocation.getQueue());
beforLocationsQuery.setLine(thisLocation.getLine());
beforLocationsQuery.setLayer(thisLocation.getLayer());
beforLocationsQuery.setLocationType(1);
beforLocationsQuery.setDepth(depth);
List<Location> beforLocations = locationService.selLocations(beforLocationsQuery);
if (beforLocations == null) {
logger.info("下发移库任务查询库位详细信息失败,数据库网络连接异常");
return;
}
if (beforLocations.isEmpty()) {
logger.info(".isEmpty()");
return;
}
Location beforLocation = beforLocations.get(0); // 前一个库位
List<Task> notCompleteTasks = taskMapper.haveNotCompleteTask(beforLocation.getLocationId());
if (notCompleteTasks == null) {
logger.info("eteTasks为null");
return;
}
if (!notCompleteTasks.isEmpty()) {
return; // 存在未完成的任务退出函数
}
}
logger.info("开始发送移库任务给WCS任务号{}", task.getTaskId());
String uuid = UUID.randomUUID().toString();
SendContainerTaskRequest request = new SendContainerTaskRequest();
request.setRequestid(uuid);
request.setKey(StringUtils.containerMd5(uuid).toUpperCase());
request.setWmstaskid(task.getTaskId());
request.setPalletno(task.getVehicleNo());
request.setTasktype("3"); // 移库
request.setFromcellno(task.getOrigin());
request.setTocellno(task.getDestination());
String requestString = JSON.toJSONString(request);
String responseString = HttpUtils.sendHttpPostWithoutToken(UrlEnums.URL_WMS_TO_WCS_CONTAINER_TASK.getValue(), requestString);
ContainerApiLocalResponse result = JSON.parseObject(responseString, ContainerApiLocalResponse.class);
if(result != null && result.getCode().equals("200")) {
logger.info("下发四向车移库任务成功任务ID{}", task.getTaskId());
Task taskForUpdate = new Task();
taskForUpdate.setTaskId(task.getTaskId());
taskForUpdate.setTaskStatus(WmsTaskStatus.WAIT.getCode());
taskService.executeTask(taskForUpdate);
return;
}
logger.info("下发四向车移库任务失败任务ID{},信息:{}", task.getTaskId(), JSON.toJSONString(result));
}
private void sendTasksMoveToWcs1(Task task) {
/* 检查该库位前一个深度是否存在库存,若存在库存则生成一个移库任务,此任务暂不下发 */
List<Location> thisLocations = locationService.selLocations(new Location(task.getOrigin()));
if(thisLocations == null) {
logger.warn("下发移库任务查询库位详细信息失败,数据库网络连接异常,任务号:{}", task.getTaskId());
return;
}
if(thisLocations.isEmpty()) {
logger.warn("下发移库任务查询库位详细信息异常,不存在详细信息,该库位可能不存在,任务号:{}", task.getTaskId());
Task taskForUpdate = new Task();
taskForUpdate.setTaskId(task.getTaskId());
taskForUpdate.setTaskStatus(WmsTaskStatus.EXCEPTION.getCode());
taskForUpdate.setRemark1("该库位不存在");
taskService.executeTask(taskForUpdate);
return;
}
Location thisLocation = thisLocations.get(0); // 找出当前库位详细信息
int depth = thisLocation.getDepth();
while (depth > 1) {
depth--;
/* 检查该库位有没有任务,若有则退出函数,若没有则检查有没有库存,若没有库存则继续,若有库存则生成一个移库任务,生成之后退出函数 */
Location beforLocationsQuery = new Location();
beforLocationsQuery.setAreaId(thisLocation.getAreaId());
beforLocationsQuery.setQueue(thisLocation.getQueue());
beforLocationsQuery.setLine(thisLocation.getLine());
beforLocationsQuery.setLayer(thisLocation.getLayer());
beforLocationsQuery.setDepth(depth);
List<Location> beforLocations = locationService.selLocations(beforLocationsQuery);
if(beforLocations == null) {
logger.warn("下发移库任务查询库位详细信息失败,数据库网络连接异常,任务号:{}", task.getTaskId());
return;
}
if(beforLocations.isEmpty()) {
return;
}
Location beforLocation = beforLocations.get(0); // 前一个库位
List<Task> notCompleteTasks = taskMapper.haveNotCompleteTask(beforLocation.getLocationId());
if(notCompleteTasks == null) {
return;
}
for(Task notCompleteTask : notCompleteTasks) {
String taskId = notCompleteTask.getTaskId();
if(!taskId.equals(task.getTaskId())) {
return;
}
}
// 检查是否有库存
Stock stockQuery = new Stock();
stockQuery.setLocationId(beforLocation.getLocationId());
List<Stock> stocks = stockService.selStocks(stockQuery);
if(stocks == null) {
return;
}
if(stocks.isEmpty()) {
continue; // 没有库存继续
}
/* 生成一个移库任务 */
/* 查找一个空库位 */
Location emptyLocation = new Location();
emptyLocation.setLocationStatus(LocationStatus.EMPTY.getCode());
emptyLocation.setAreaId(beforLocation.getAreaId());
List<Location> emptyLocations = locationMapper.selLocations(emptyLocation);
if(emptyLocations == null) {
return;
}
if(emptyLocations.isEmpty()){
return; // 移库没有可用库位
}
Location emptyLocationItem = locationUtils.checkCanUse(emptyLocations); // 取得新库位
if(emptyLocationItem == null) {
return; // 没有可用库位或者m库位存在干涉
}
// 锁定旧库位库存
stockMapper.updateStockStatusWithLocationId(beforLocation.getLocationId(), StockStatus.LOCK.getCode());
// 锁定新库位
Location locationForUpdate = new Location();
locationForUpdate.setLocationId(emptyLocationItem.getLocationId());
locationForUpdate.setLocationStatus(LocationStatus.OCCUPY.getCode());
locationMapper.modifyLocation(locationForUpdate);
// 构造移库任务
Task moveTask = new Task();
moveTask.setTaskId(UUID.randomUUID().toString());
moveTask.setTaskGroup(task.getTaskGroup());
moveTask.setTaskType(TaskType.MOVE.getCode());
moveTask.setOrigin(beforLocation.getLocationId());
moveTask.setDestination(emptyLocationItem.getLocationId());
moveTask.setVehicleNo(stocks.get(0).getVehicleId());
moveTask.setVehicleSize(0);
moveTask.setWeight(0.0);
moveTask.setTaskPriority(9);
moveTask.setTaskStatus(WmsTaskStatus.NEW.getCode());
taskService.addTask(moveTask);
return;
}
if(thisLocation.getAreaId() == 1) { // 宝开立库
List<WcsTask> request = new ArrayList<>();
// 创建发送的任务
WcsTask tempTask = new WcsTask();
tempTask.setTaskId(task.getTaskId());
tempTask.setTaskType(TaskType.MOVE.getCode());
tempTask.setOrigin(task.getOrigin());
tempTask.setDestination(task.getDestination());
tempTask.setVehicleNo(task.getVehicleNo());
tempTask.setVehicleSize(1);
tempTask.setWeight(task.getWeight() == null ? 0 : task.getWeight());
tempTask.setPriority(task.getTaskPriority());
request.add(tempTask);
// 发送任务
ResponseEntity result = JSON.parseObject(HttpUtils.sendHttpPostWithoutToken(UrlEnums.URL_WMS_TO_WCS_SEND_TASK.getValue(), JSON.toJSONString(request)), ResponseEntity.class);
if (result != null && Objects.equals(ResponseCode.OK.getCode(), result.getCode())) {
logger.info("下发立库移库任务成功任务ID{}", tempTask.getTaskId());
Task taskForUpdate = new Task();
taskForUpdate.setTaskId(task.getTaskId());
taskForUpdate.setTaskStatus(WmsTaskStatus.WAIT.getCode());
taskService.executeTask(taskForUpdate);
return;
}
logger.info("下发立库移库任务失败任务ID{},信息:{}", tempTask.getTaskId(), JSON.toJSONString(result));
} else {
String uuid = UUID.randomUUID().toString();
SendContainerTaskRequest request = new SendContainerTaskRequest();
request.setRequestid(uuid);
request.setKey(StringUtils.containerMd5(uuid).toUpperCase());
request.setWmstaskid(task.getTaskId());
request.setPalletno(task.getVehicleNo());
request.setTasktype("3"); // 移库
request.setFromcellno(task.getOrigin());
request.setTocellno(task.getDestination());
String requestString = JSON.toJSONString(request);
String responseString = HttpUtils.sendHttpPostWithoutToken(UrlEnums.URL_WMS_TO_WCS_CONTAINER_TASK.getValue(), requestString);
ContainerApiLocalResponse result = JSON.parseObject(responseString, ContainerApiLocalResponse.class);
if(result != null && result.getCode().equals("200")) {
// logger.info("下发四向车移库任务成功任务ID{}", task.getTaskId());
Task taskForUpdate = new Task();
taskForUpdate.setTaskId(task.getTaskId());
taskForUpdate.setTaskStatus(WmsTaskStatus.WAIT.getCode());
taskService.executeTask(taskForUpdate);
return;
}
// logger.info("下发四向车移库任务失败任务ID{},信息:{}", task.getTaskId(), JSON.toJSONString(result));
}
}
/**
* 每隔一秒检索一遍任务列表同时向WCS下发任务
*/
// @Scheduled(fixedDelay = 1000)
public void executeTasks() {
try {
// 检索任务列表查询状态为等待状态的任务
Task taskForQuery = new Task();
taskForQuery.setTaskStatus(WmsTaskStatus.NEW.getCode());
List<Task> tasks = taskService.selTasks(taskForQuery);
// 相同任务组的任务只发一次
List<String> taskGroupIds = new LinkedList<>();
List<WcsTask> request = new ArrayList<>();
if (!tasks.isEmpty()) {// 存在等待中的任务
for (Task task : tasks) {
if (taskGroupIds.contains(task.getTaskGroup())) {// 该taskGroup的任务已经发送过
task.setTaskStatus(WmsTaskStatus.WAIT.getCode());
continue;
}
// 创建发送的任务
WcsTask tempTask = new WcsTask();
tempTask.setTaskId(task.getTaskGroup());
if (TaskType.OUT.getCode().equals(task.getTaskType()) || TaskType.INVENTORY.getCode().equals(task.getTaskType())) {
tempTask.setTaskType(TaskType.OUT.getCode());
} else {
tempTask.setTaskType(TaskType.IN.getCode());
}
tempTask.setOrigin(task.getOrigin());
tempTask.setDestination(task.getDestination());
tempTask.setVehicleNo(task.getVehicleNo());
tempTask.setVehicleSize(1);
tempTask.setWeight(task.getWeight() == null ? 0 : task.getWeight());
tempTask.setPriority(task.getTaskPriority());
request.add(tempTask);
taskGroupIds.add(task.getTaskGroup());
task.setTaskStatus(WmsTaskStatus.WAIT.getCode());
}
if (request.isEmpty()) {
return;
}
// 发送任务
ResponseEntity result = JSON.parseObject(HttpUtils.sendHttpPostWithoutToken(UrlEnums.URL_WMS_TO_WCS_SEND_TASK.getValue(), JSON.toJSONString(request)), ResponseEntity.class);
if (result != null && Objects.equals(ResponseCode.OK.getCode(), result.getCode())) {
// 更新任务列表
for (Task task : tasks) {
// 更新任务
taskService.executeTask(task);
}
}
}
} catch (Exception exception) {
logger.error("发生异常:{}", exception.getMessage());
}
}
/**
* 定期检查设备状态
* 5秒钟
*/
// @Scheduled(fixedDelay = 5000)
public void checkEquipmentStatus() {
}
/**
* 每天查询一次是否有过期的库存
* 每天晚上8点执行一次
*/
// @Scheduled(cron = "0 0 20 * * ?")
public void detectOutOfDateStock() {
logger.info("执行定时任务:查询过期库存");
List<Stock> outOfDateStocks = stockService.selStockOutOfDate();
if (!outOfDateStocks.isEmpty()) {
logger.info("过期库存数量不为0准备更新过期库存");
for (Stock outOfDateStock : outOfDateStocks) {
try {
outOfDateStock.setGoodsStatus(GoodsStatus.OVERDUE.getCode());
stockService.modifyStock(outOfDateStock);
logger.info("过期库存更新成功");
} catch (Exception e) {
logger.error("过期库存更新异常:{}", e.getMessage());
}
}
}
}
/**
* 每天查询一次是否有入库后长期未使用的库存
* 每天晚上9点执行一次
*/
// @Scheduled(cron = "0 0 21 * * ?")
public void detectStockLongTimeNoUse() {
logger.info("执行定时任务:查询是否有入库后长期未使用的库存");
List<Stock> stocksLongTimeNoUse = stockService.selStockLongTimeNoUse(7);
if (!stocksLongTimeNoUse.isEmpty()) {
logger.info("有入库后长期未使用的库存, 准备更新库存状态");
for (Stock stockLongTimeNoUse : stocksLongTimeNoUse) {
try {
stockLongTimeNoUse.setGoodsStatus(GoodsStatus.SCRAP.getCode());
stockService.modifyStock(stockLongTimeNoUse);
logger.info("长时间未使用库存状态更新成功");
} catch (Exception e) {
logger.error("长时间未使用库存状态更新异常:{}", e.getMessage());
}
}
}
}
/**
* 每天查询一次是否有过期记录
* 每天晚上10点执行一次
*/
//@Scheduled(cron = "0 0 22 * * ?")
public void deleteOutOfDateData() {
logger.info("执行定时任务:删除过期数据");
taskRecordService.deleteTaskRecordRegularly();
}
}

View File

@ -0,0 +1,800 @@
package com.wms.bussiness;
import com.alibaba.fastjson2.JSON;
import com.wms.constants.enums.*;
import com.wms.entity.app.ResponseEntity;
import com.wms.entity.app.mes.*;
import com.wms.entity.app.wcs.WmsReceiveTaskResultEntity;
import com.wms.entity.common.WmsApiResponse;
import com.wms.entity.table.*;
import com.wms.mapper.*;
import com.wms.service.PartInfoService;
import com.wms.utils.HttpUtils;
import com.wms.utils.WmsUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.formula.functions.Now;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestBody;
import javax.swing.plaf.synth.Region;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
/**
* 对任务的操作
*/
@Slf4j
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class TaskOperation {
/**
* 库存 Mapper
*/
private final StockMapper stockMapper;
/**
* 任务表操作类
*/
private final TaskMapper taskMapper;
/**
* 库位表操作类
*/
private final LocationMapper locationMapper;
private final VehicleMapper vehicleMapper;
private final OrderOutMapper orderOutMapper;
/**
* 零件
*/
private final PartInfoService partInfoService;
/**
* 订单入库
*/
private final com.wms.mapper.AppOrderInMapper appOrderInMapper;
//region 完成任务
/**
* 完成任务
* @param task 要完成的任务A21-15-2
* @return 操作结果
*/
public boolean completeTask(Task task) {
if(task == null) {
return false;
}
TaskType taskType = TaskType.getTaskType(task.getTaskType());
if(taskType == null) {
return false;
}
/* 根据任务类型判断 */
return switch (taskType) {
case IN -> completeInTask(task);
case OUT -> completeOutTask(task);
case INVENTORY -> completeInventoryTask(task);
case MOVE -> completeMoveTask(task);
};
}
/**
* 完成入库任务
* @param task 要完成的入库任务
* @return 结果
*/
private boolean completeInTask(Task task) {
/* 找出任务完成该任务找出该任务终点更新库存为OK */
// 完成任务
Task completeTask = new Task();
completeTask.setTaskId(task.getTaskId());
completeTask.setTaskStatus(WmsTaskStatus.FINISH.getCode());
completeTask.setFinishTime(new Date());
taskMapper.executeTask(completeTask); // 完成任务
// 占掉新库位生成的时候会占这里重复操作保护
Location occupyLocation = new Location();
occupyLocation.setLocationId(task.getDestination());
occupyLocation.setLocationStatus(LocationStatus.OCCUPY.getCode());
occupyLocation.setVehicleId(task.getVehicleNo());
locationMapper.modifyLocation(occupyLocation); // 更新库位
//根据task表的载具号前16位去入库表里面找对应的批次号的入库单数据 数量相等 入库单载具号为空
// 根据载具号获取入库单入库数据行
List<AppOrderIn> appOrderIns = appOrderInMapper.selectWithVehicle(task.getVehicleNo());
if (appOrderIns == null || appOrderIns.isEmpty()) {
log.error("四向车入库完成更新库存失败,任务:{},原因:没有找到入库单入库数据行", task.toLoggerString());
return false;
}
AppOrderIn appOrderInForCheck = appOrderIns.get(0);
if (appOrderInForCheck.getGoodsId() == null || appOrderInForCheck.getGoodsId().isEmpty()){
//表示这个为空托盘入库没有零件号不记录到库存表中,更新到料箱监控表中
Vehicle a = new Vehicle();
a.setVehicleId(appOrderInForCheck.getVehicleNo());
a.setCurrentLocation(task.getDestination());
a.setIsEmpty(1);
a.setVehicleStatus(2);
int b = vehicleMapper.addVehicle(a);
if (b == 0){
log.error("四向车空托盘入库完成更新料箱监控失败,任务:{},原因:更新载具为空状态失败", task.toLoggerString());
return false;
}else{
log.info("四向车空托盘入库完成更新料箱监控成功,任务:{}", task.toLoggerString());
}
//删除入库单
int dele = appOrderInMapper.delete(appOrderInForCheck.getRowId());
if (dele == 0){
log.info("四向车空托入库删除订单入库单数据行失败,任务:{},原因:删除失败", task.toLoggerString());
}else if (dele == 1){
log.info("四向车空托入库删除订单入库单数据行成功,任务:{}", task.toLoggerString());
}
}else{
// 将入库数据行数据插入库存表
for (AppOrderIn appOrderIn : appOrderIns){
//将批次号一部分裁下来做生产日期
Stock addStock = new Stock();
addStock.setStockId(WmsUtils.generateUUIDString());
addStock.setWarehouseName("四向车立体库");
addStock.setLocationId(task.getDestination());
//addStock.setLocationId(appOrderIn.getVehicleNo());
addStock.setVehicleId(appOrderIn.getVehicleNo());
addStock.setGoodsId(appOrderIn.getGoodsId());
addStock.setGoodsName("");
addStock.setBatchNo("");
addStock.setAvailableNum(appOrderIn.getGoodsNum().intValue());
addStock.setRealNum(appOrderIn.getGoodsNum().intValue());
addStock.setProviderId("");
addStock.setProviderName("");
//addStock.setProductionDate(null);
addStock.setExpirationDate(null);
addStock.setStockStatus(0);
addStock.setGoodsStatus(null);
addStock.setCreateTime(new Date());
addStock.setLastUpdateTime(null);
addStock.setLastUpdateUser(null);
addStock.setRemark(appOrderIn.getRemark());
addStock.setProductionDate(null);
//添加到库存里
if (Objects.equals(addStock.getVehicleId(), task.getVehicleNo())){
int a = stockMapper.addStock(addStock);//
if (a == 0){//表示添加库存失败
log.info("四向车入库完成更新库存失败,任务:{},原因:添加库存失败", task.toLoggerString());
for (int i = 0; i < 5; i++) {
int b =stockMapper.addStock(addStock);
if (b != 0){
log.info("四向车入库更新库存重试成功,任务:{}", task.toLoggerString());
break;
}
}
}else {
log.info("四向车入库完成更新库存成功,任务:{}", task.toLoggerString());
}
int b = appOrderInMapper.delete(appOrderIn.getRowId());
if (b == 0){
log.info("四向车入库删除订单入库数据行失败,任务:{},原因:删除失败", task.toLoggerString());
}else if (b == 1){
log.info("四向车入库删除订单入库数据行成功,任务:{}", task.toLoggerString());
}
}else{
log.error("四向车入库完成更新库存失败,任务:{}原因载具号前16位与入库单载具号前16位不一致", task.toLoggerString());
}
}
Vehicle ab = new Vehicle();
ab.setVehicleId(appOrderIns.get(0).getVehicleNo());
ab.setCurrentLocation(task.getDestination());
ab.setIsEmpty(0);
ab.setVehicleStatus(2);
int bd = vehicleMapper.addVehicle(ab);
if (bd == 0){
log.error("四向车入库完成更新料箱监控失败,任务:{},原因:更新载具为空状态失败", task.toLoggerString());
return false;
}else{
log.info("四向车入库完成更新料箱监控成功,任务:{}", task.toLoggerString());
}
}
return true;
}
// /**
// * 发送 mes 上架入库信息
// * @param stock 库存记录
// * @param locationId 库位
// */
// private void sendMesPutInGoods(Stock stock, String locationId) {
// try {
// SendMesPutInGoodsRequest request = new SendMesPutInGoodsRequest();
// request.setGuid(stock.getStockId());
// request.setLosnr(stock.getBatchNo());
// request.setItemCode(stock.getGoodsId());
// request.setLotQty(String.valueOf(stock.getRealNum()));
// request.setBinCode(locationId);
// String requestString = JSON.toJSONString(request);
// String responseString = HttpUtils.sendHttpPostWithoutToken(UrlEnums.URL_WMS_TO_MES_IN.getValue(), requestString);
// MesApiLocalResponse result = JSON.parseObject(responseString, MesApiLocalResponse.class);
// if(result != null && result.getTransFlag().equals(1)) {
// log.info("发送MES入库上架成功信息{}", requestString);
// }
// log.warn("发送MES入库上架失败信息{},返回信息:{}", requestString, responseString);
// }catch (Exception e){
// log.error("发送MES入库上架失败异常信息{}", e.getMessage());
// }
// }
// private void sendMesLocation(Stock stock, String locationId) {
// try {
// SendMesStockRequest request = new SendMesStockRequest();
// request.setGuid(stock.getStockId());
// request.setWarehouse(stock.getWarehouseName());
// request.setItemCode(stock.getGoodsId());
// request.setLosnr(stock.getBatchNo());
// request.setLotQty(Integer.toString(stock.getAvailableNum()));
// request.setUnit(null);
// request.setBinCode(locationId);
// request.setVehicleNo(stock.getVehicleId());
// String requestString = JSON.toJSONString(request);
// String responseString = HttpUtils.sendHttpPostWithoutToken(UrlEnums.URL_WMS_TO_MES_STOCK.getValue(), requestString);
// MesApiLocalResponse result = JSON.parseObject(responseString, MesApiLocalResponse.class);
// if (result != null && result.getTransFlag().equals(1)){
// log.info("发送MES库存成功信息{}", requestString);
// }else {
// log.warn("发送MES库存失败信息{},返回信息:{}", requestString, responseString);
// }
// }catch (Exception e){
// log.error("发送MES库存失败异常信息{}", e.getMessage());
// }
// }
/**
* 完成出库任务
* @param task 要完成的出库任务
* @return 执行结果
*/
private boolean completeOutTask(Task task) {
/* 找出任务,完成该任务;找出该任务终点,删除库存;释放库位 */
// 完成任务
Task completeTask = new Task();
completeTask.setTaskId(task.getTaskId());
completeTask.setTaskStatus(WmsTaskStatus.FINISH.getCode());
completeTask.setFinishTime(new Date());
taskMapper.executeTask(completeTask); // 完成任务
// 释放库位
Location updateLocation = new Location();
updateLocation.setLocationId(task.getOrigin());
updateLocation.setLocationStatus(LocationStatus.EMPTY.getCode());
updateLocation.setVehicleId("");
locationMapper.modifyLocation(updateLocation); // 更新库位为空
if (Objects.equals(task.getRemark1(), "手动出库")){
// 根据起点拉取库位库存,剩下数量不为零的数据搬运到入库单 生成回库任务删除该库位所有库存
List<Stock> stocks = stockMapper.selStocksByLocationId(task.getOrigin());
if (stocks == null || stocks.isEmpty()){
log.error("拉取库存失败,任务:{},原因:没有找到库存数据", task.toLoggerString());
return false;
}
int totalNum = stocks.size();
if (totalNum > 1){
for (Stock stock : stocks){
if (stock.getAvailableNum() > 0){
AppOrderIn appOrderIn = new AppOrderIn();
appOrderIn.setRowId(WmsUtils.generateUUIDString());
appOrderIn.setGuid(stock.getStockId());
appOrderIn.setInType(1);
appOrderIn.setBatchNo(stock.getBatchNo());
appOrderIn.setVehicleNo(task.getVehicleNo());
appOrderIn.setGoodsId(stock.getGoodsId());
appOrderIn.setGoodsNum(BigDecimal.valueOf(stock.getAvailableNum()));
appOrderIn.setWareHouse("A");
if (stock.getVehicleId() != null && !stock.getVehicleId().isEmpty()){
appOrderIn.setOrderStatus(2);
}else {
appOrderIn.setOrderStatus(0);
}
//appOrderIn.setOrderStatus(2);
appOrderIn.setCreateTime(LocalDateTime.now());
appOrderIn.setUpdateTime(LocalDateTime.now());
appOrderIn.setCreatePerson("BACK");
appOrderIn.setRemark("回库");
int isSuessInsert = appOrderInMapper.insert(appOrderIn);
if(isSuessInsert > 0){
log.info("多物料回库任务生成成功,任务:{}", task.toLoggerString());
}else{
log.error("多物料回库任务生成失败,任务:{}", task.toLoggerString());
}
}
}
} else{
for (Stock stock : stocks){
if (stock.getAvailableNum() > 0){
AppOrderIn appOrderIn = new AppOrderIn();
appOrderIn.setRowId(WmsUtils.generateUUIDString());
appOrderIn.setGuid(stock.getStockId());
appOrderIn.setInType(1);
appOrderIn.setBatchNo(stock.getBatchNo());
appOrderIn.setVehicleNo(task.getVehicleNo());
appOrderIn.setGoodsId(stock.getGoodsId());
appOrderIn.setGoodsNum(BigDecimal.valueOf(stock.getAvailableNum()));
appOrderIn.setWareHouse("A");
if (stock.getVehicleId() != null && !stock.getVehicleId().isEmpty()){
appOrderIn.setOrderStatus(2);
}else {
appOrderIn.setOrderStatus(0);
}
//appOrderIn.setOrderStatus(2);
appOrderIn.setCreateTime(LocalDateTime.now());
appOrderIn.setUpdateTime(LocalDateTime.now());
appOrderIn.setCreatePerson("BACK");
appOrderIn.setRemark("回库");
int isSuessInsert = appOrderInMapper.insert(appOrderIn);
if(isSuessInsert > 0){
log.info("回库任务生成成功,任务:{}", task.toLoggerString());
}else{
log.error("回库任务生成失败,任务:{}", task.toLoggerString());
}
}else{
log.error("库存数量为零,即将生成空托盘回库任务");
AppOrderIn appOrderIn = new AppOrderIn();
appOrderIn.setRowId(UUID.randomUUID().toString());
appOrderIn.setGuid(UUID.randomUUID().toString());
appOrderIn.setInType(1);
appOrderIn.setBatchNo(null);
appOrderIn.setVehicleNo(task.getVehicleNo());
appOrderIn.setGoodsId(null);
appOrderIn.setGoodsNum(null);
appOrderIn.setWareHouse("A");
appOrderIn.setOrderStatus(0);
appOrderIn.setCreateTime(LocalDateTime.now());
appOrderIn.setCreatePerson("WMS");
appOrderIn.setUpdateTime(LocalDateTime.now());
appOrderIn.setRemark("空托盘入库");
//appOrderIn.setProductionDate(request.abcSelect);
int a = appOrderInMapper.insert(appOrderIn);
if (a > 0){
log.info("空托盘回库任务生成成功,任务:{}", task.toLoggerString());
}else{
log.error("空托盘回库任务生成失败,任务:{}", task.toLoggerString());
}
}
}
}
//出库完成删除出库单
int deleteOrderOut = orderOutMapper.deleteOrderOut(task.getPickStand());
if (deleteOrderOut > 0){
log.info("出库单删除成功,任务:{}", task.toLoggerString());
}else{
log.error("出库单删除失败,任务:{}", task.toLoggerString());
}
//出库完成发送mes
Stock checkIsExist = new Stock();
checkIsExist.setLocationId(task.getOrigin());
List<Stock> checkIsExistListResult = stockMapper.selStocks(checkIsExist);
//List<Stock> stockUseSend = new ArrayList<>();
if (checkIsExistListResult == null || checkIsExistListResult.isEmpty()){
log.info("没有找到对应的数据,表中数据为空,信息:{}", task.toLoggerString());
return false;
}
Vehicle ab = new Vehicle();
ab.setVehicleId(checkIsExistListResult.get(0).getVehicleId());
ab.setCurrentLocation(task.getOrigin());
ab.setIsEmpty(0);
ab.setVehicleStatus(2);
int bd = vehicleMapper.deleteVehicle(ab);
if (bd == 0){
log.error("四向车出库完成更新料箱监控失败,任务:{},原因:更新载具为空状态失败", task.toLoggerString());
//return false;
}else{
log.info("四向车出库完成更新料箱监控成功,任务:{}", task.toLoggerString());
}
// 删除库存
int updateStock = stockMapper.deleteStockWithLocationId(task.getOrigin());
if(updateStock > 0){
log.info("出库完成删除库存成功,任务:{}", task.toLoggerString());
return true;
}else{
log.error("出库完成删除库存失败,任务:{}", task.toLoggerString());
return false;
}
} else if (Objects.equals(task.getRemark1(), "空托盘出库")) {
//出库完成删除出库单
int deleteOrderOut = orderOutMapper.deleteOrderOut(task.getPickStand());
if (deleteOrderOut > 0){
log.info("空托盘出库单删除成功,任务:{}", task.toLoggerString());
}else{
log.error("空托盘出库单删除失败,任务:{}", task.toLoggerString());
}
Vehicle ab = new Vehicle();
ab.setVehicleId(task.getVehicleNo());
ab.setCurrentLocation(task.getOrigin());
ab.setIsEmpty(1);
ab.setVehicleStatus(2);
int bd = vehicleMapper.deleteVehicle(ab);
if (bd == 0){
log.error("四向车空托出库完成更新料箱监控失败,任务:{},原因:更新载具为空状态失败", task.toLoggerString());
return false;
}else{
log.info("四向车空托出库完成更新料箱监控成功,任务:{}", task.toLoggerString());
return true;
}
}
log.error("不处理的出库任务,表中数据为空,信息:{}", task.toLoggerString());
return false;
}
/**
* 发送 mes 出库下架信息
* @param stocks 库存记录
* @param task 任务
*/
// private void sendMesPutOutGoods(List<Stock> stocks, Task task) {
// try {
// SendMesPutOutGoodsRequest request = new SendMesPutOutGoodsRequest();
// request.setGuid(task.getTaskId());
// request.setTransferNo(task.getTaskGroup());
// if (Objects.equals(task.getRemark1(), "手动出库")){
// request.setType(4);
// }else{
// request.setType(task.getTaskType());
// }
// List<SendMesPutOutGoodsRow> rows = new ArrayList<>();
// int lint = 1;
// if (stocks == null || stocks.isEmpty()){
// log.error("发送MES出库下架失败没有收到ROW所需要的数据信息{}", task.toLoggerString());
// return;
// }
// for(Stock stock : stocks) {
// SendMesPutOutGoodsRow row = new SendMesPutOutGoodsRow();
// row.setTransferLine(String.valueOf(lint));
// row.setLosnr(stock.getBatchNo());
// row.setVehicleNo(stock.getVehicleId());
// row.setWarehouse(stock.getWarehouseName());
// row.setLotQty(String.valueOf(stock.getRealNum() - stock.getAvailableNum()));
// rows.add(row);
// lint++;
// }
// request.setRow(rows);
// String requestString = JSON.toJSONString(request);
// String responseString = HttpUtils.sendHttpPostWithoutToken(UrlEnums.URL_WMS_TO_MES_OUT.getValue(), requestString);
// MesApiLocalResponse result = JSON.parseObject(responseString, MesApiLocalResponse.class);
// if(result != null && result.getTransFlag().equals(1)) {
// log.info("发送MES出库下架成功信息{}", requestString);
// }else{
// log.warn("发送MES出库下架失败信息{},返回信息:{}", requestString, responseString);
// }
// }catch (Exception e){
// log.error("发送MES出库下架失败异常信息{}", e.getMessage());
// }
// }
/**
* 完成盘点任务
* @param task 任务
* @return 完成结果
*/
private boolean completeInventoryTask(Task task) {
/* 找出任务,完成该任务;找出该任务终点,删除库存;释放库位 */
// 完成任务
Task completeTask = new Task();
completeTask.setTaskId(task.getTaskId());
completeTask.setTaskStatus(WmsTaskStatus.FINISH.getCode());
completeTask.setFinishTime(new Date());
taskMapper.executeTask(completeTask); // 完成任务
// 释放库位
Location updateLocation = new Location();
updateLocation.setLocationId(task.getOrigin());
updateLocation.setLocationStatus(LocationStatus.EMPTY.getCode());
updateLocation.setVehicleId("");
locationMapper.modifyLocation(updateLocation); // 更新库位为空
// 根据起点拉取库位库存,剩下数量不为零的数据搬运到入库单 生成回库任务删除该库位所有库存
List<Stock> stocks = stockMapper.selStocksByLocationId(task.getOrigin());
if (stocks == null || stocks.isEmpty()){
log.error("完成盘点出库拉取库存失败,任务:{},原因:没有找到库存数据", task.toLoggerString());
return false;
}
for (Stock stock : stocks){
if (stock.getAvailableNum() > 0){
AppOrderIn appOrderIn = new AppOrderIn();
appOrderIn.setRowId(WmsUtils.generateUUIDString());
appOrderIn.setGuid(stock.getStockId());
appOrderIn.setInType(1);
appOrderIn.setBatchNo(stock.getBatchNo());
appOrderIn.setVehicleNo(task.getVehicleNo());
appOrderIn.setGoodsId(stock.getGoodsId());
appOrderIn.setGoodsNum(BigDecimal.valueOf(stock.getAvailableNum()));
appOrderIn.setWareHouse(stock.getWarehouseName());
if (stock.getVehicleId() != null && !stock.getVehicleId().isEmpty()){
appOrderIn.setOrderStatus(2);
}else {
appOrderIn.setOrderStatus(0);
}
//appOrderIn.setOrderStatus(2);
appOrderIn.setCreateTime(LocalDateTime.now());
appOrderIn.setUpdateTime(LocalDateTime.now());
appOrderIn.setCreatePerson("BACK");
appOrderIn.setRemark("盘点回库");
int isSuessInsert = appOrderInMapper.insert(appOrderIn);
if(isSuessInsert > 0){
log.info("盘点回库任务生成成功,任务:{}", task.toLoggerString());
}else{
log.error("盘点回库任务生成失败,任务:{}", task.toLoggerString());
}
}
}
// 盘点出库完成发送mes
// Stock checkIsExist = new Stock();
// checkIsExist.setLocationId(task.getOrigin());
// List<Stock> checkIsExistListResult = stockMapper.selStocks(checkIsExist);
// sendMesInventoryGoods(checkIsExistListResult, task);
// Stock addStock = stocks.get(0);
// addStock.setAvailableNum(0);
// 发送库存接口给mes
//sendMesLocation(addStock, task.getOrigin());
// 删除库存????
int updateStock = stockMapper.deleteStockWithLocationId(task.getOrigin());
if(updateStock > 0){
log.info("盘点出库完成删除库存成功,任务:{}", task.toLoggerString());
return true;
}
return false;
}
// /**
// * 完成盘点任务
// * @param task 任务
// */
// private void sendMesInventoryGoods(List<Stock> stocks, Task task) {
// try {
// SendMesGoodsInventoryRequest request = new SendMesGoodsInventoryRequest();
// request.setGuid(task.getTaskId());
// request.setInventoryNo(task.getTaskGroup());
//
// List<SendMesGoodsInventoryRow> rows = new ArrayList<>();
// for(Stock stock : stocks) {
// SendMesGoodsInventoryRow row = new SendMesGoodsInventoryRow();
// row.setLosnr(stock.getBatchNo());
// row.setWarehouse(stock.getWarehouseName());
// row.setLotQty(String.valueOf(stock.getRealNum()));
// rows.add(row);
// }
// request.setRow(rows);
// String requestString = JSON.toJSONString(request);
// String responseString = HttpUtils.sendHttpPostWithoutToken(UrlEnums.URL_WMS_TO_MES_INVENTORY.getValue(), requestString);
// MesApiLocalResponse result = JSON.parseObject(responseString, MesApiLocalResponse.class);
// if(result != null && result.getTransFlag().equals(1)) {
// log.info("发送MES盘点执行成功信息{}", requestString);
// }else{
// log.warn("发送MES盘点执行失败信息{},返回信息:{}", requestString, responseString);
// }
// }catch (Exception e){
// log.error("发送MES盘点执行失败异常信息{}", e.getMessage());
// }
// }
/**
* 完成移库任务
* @param task 任务
* @return 完成结果
*/
private boolean completeMoveTask(Task task) {
/* 找出任务,更新任务为完成;释放原库位;更新库存到新库位 */
// 完成任务
Task completeTask = new Task();
completeTask.setTaskId(task.getTaskId());
completeTask.setTaskStatus(WmsTaskStatus.FINISH.getCode());
completeTask.setFinishTime(new Date());
taskMapper.executeTask(completeTask); // 完成任务
// 释放原库位
// 释放库位
Location updateLocation = new Location();
updateLocation.setLocationId(task.getOrigin());
updateLocation.setLocationStatus(LocationStatus.EMPTY.getCode());
updateLocation.setVehicleId("");
locationMapper.modifyLocation(updateLocation); // 更新库位为空
// 占掉新库位生成的时候会占这里重复操作保护
Location occupyLocation = new Location();
occupyLocation.setLocationId(task.getDestination());
occupyLocation.setLocationStatus(LocationStatus.OCCUPY.getCode());
occupyLocation.setVehicleId(task.getVehicleNo());
locationMapper.modifyLocation(occupyLocation); // 更新库位
String checkUse = task.getRemark1();
// if (Objects.equals(checkUse, "空框")){
//只需要更新料箱监控
Vehicle vehicle = new Vehicle();
vehicle.setCurrentLocation(task.getDestination());
vehicle.setVehicleId(task.getVehicleNo());
int a = vehicleMapper.modifyVehicle(vehicle);
if (a > 0){
log.info("更新料箱监控成功");
}else{
log.info("更新料箱监控失败");
}
// }
if (Objects.equals(checkUse, "带料")) {
//需要额外更新库存
int updatedLocation = stockMapper.updateLocationAndStatus(task.getOrigin(), task.getDestination(), StockStatus.OK.getCode());
if(updatedLocation > 0){
log.info("移库库位更新成功,任务:{}", task.toLoggerString());
return true;
}else {
log.info("移库库位更新失败,任务:{}", task.toLoggerString());
}
} else if (Objects.equals(checkUse, "空框")) {
log.info("空框移库库位更新成功");
return true;
}
// 更新库位
return false;
}
// /**
// * 完成移库任务
// * @param task 任务
// * @return 完成结果
// */
// private void sendMesPutMoveGoods(Stock stock, Task task) {
// try {
// SendMesGoodsMoveRequest request = new SendMesGoodsMoveRequest();
// request.setGuid(stock.getStockId());
// request.setLosnr(stock.getBatchNo());
// request.setFBinCode(task.getOrigin());
// request.setLotQty(String.valueOf(stock.getRealNum()));
// request.setTBinCode(task.getDestination());
// String requestString = JSON.toJSONString(request);
// String responseString = HttpUtils.sendHttpPostWithoutToken(UrlEnums.URL_WMS_TO_MES_MOVE.getValue(), requestString);
// MesApiLocalResponse result = JSON.parseObject(responseString, MesApiLocalResponse.class);
// if(result != null && result.getTransFlag().equals(1)) {
// log.info("发送MES批次调整移库成功信息{}", requestString);
// }
// log.warn("发送MES批次调整移库失败信息{},返回信息:{}", requestString, responseString);
// }catch (Exception e){
// log.error("发送MES批次调整移库失败异常信息{}", e.getMessage());
// }
// }
//endregion
//region 取消任务
/**
* 取消任务
* @param task 要完成的任务
* @return 操作结果
*/
public boolean cancelTask(Task task) {
if(task == null) {
return false;
}
TaskType taskType = TaskType.getTaskType(task.getTaskType());
if(taskType == null) {
return false;
}
/* 根据任务类型判断 */
return switch (taskType) {
case IN -> cancelInTask(task);
case OUT -> cancelOutTask(task);
case INVENTORY -> cancelInventoryTask(task);
case MOVE -> cancelMoveTask(task);
};
}
/**
* 取消入库任务
* @param task 要取消的入库任务
* @return 结果
*/
private boolean cancelInTask(Task task) {
/* 找出任务取消该任务找出该任务终点更新库存为OK */
// 取消任务
Task completeTask = new Task();
completeTask.setTaskId(task.getTaskId());
completeTask.setTaskStatus(WmsTaskStatus.CANCEL.getCode());
completeTask.setFinishTime(new Date());
taskMapper.executeTask(completeTask); // 取消任务
// 释放库位
Location updateLocation = new Location();
updateLocation.setLocationId(task.getDestination());
updateLocation.setLocationStatus(LocationStatus.EMPTY.getCode());
updateLocation.setVehicleId("");
locationMapper.modifyLocation(updateLocation); // 更新库位为空
// 更新库存为 ok ???????
int updateStock = stockMapper.updateStockStatusWithLocationId(task.getDestination(), StockStatus.OK.getCode());
if(updateStock > 0){
log.info("入库取消更新库存成功,任务:{}", task.toLoggerString());
return true;
}
return false;
}
/**
* 取消出库任务
* @param task 要取消的出库任务
* @return 执行结果
*/
private boolean cancelOutTask(Task task) {
/* 找出任务,取消该任务;找出该任务终点,删除库存;释放库位 */
// 取消任务
Task completeTask = new Task();
completeTask.setTaskId(task.getTaskId());
completeTask.setTaskStatus(WmsTaskStatus.CANCEL.getCode());
completeTask.setFinishTime(new Date());
taskMapper.executeTask(completeTask); // 取消任务
// 更新库存为 ok
int updateStock = stockMapper.updateStockStatusWithLocationId(task.getDestination(), StockStatus.OK.getCode());
if(updateStock > 0){
log.info("出库取消更新库存成功,任务:{}", task.toLoggerString());
return true;
}
return false;
}
/**
* 取消盘点任务
* @param task 任务
* @return 取消结果
*/
private boolean cancelInventoryTask(Task task) {
/* 找出任务,取消该任务;找出该任务终点,删除库存;释放库位 */
// 取消任务
Task completeTask = new Task();
completeTask.setTaskId(task.getTaskId());
completeTask.setTaskStatus(WmsTaskStatus.CANCEL.getCode());
completeTask.setFinishTime(new Date());
taskMapper.executeTask(completeTask); // 取消任务
// 更新库存为 ok
int updateStock = stockMapper.updateStockStatusWithLocationId(task.getDestination(), StockStatus.OK.getCode());
if(updateStock > 0){
log.info("盘点出库取消更新库存成功,任务:{}", task.toLoggerString());
return true;
}
return false;
}
/**
* 取消移库任务
* @param task 任务
* @return 取消结果
*/
private boolean cancelMoveTask(Task task) {
/* 找出任务更新任务为取消释放新库位更新库存为OK */
// 取消任务
Task completeTask = new Task();
completeTask.setTaskId(task.getTaskId());
completeTask.setTaskStatus(WmsTaskStatus.CANCEL.getCode());
completeTask.setFinishTime(new Date());
taskMapper.executeTask(completeTask); // 取消任务
// 释放库位
Location updateLocation = new Location();
updateLocation.setLocationId(task.getDestination());
updateLocation.setLocationStatus(LocationStatus.EMPTY.getCode());
updateLocation.setVehicleId("");
locationMapper.modifyLocation(updateLocation); // 更新库位为空
// 更新库位
int updatedLocation = stockMapper.updateStockStatusWithLocationId(task.getOrigin(), StockStatus.OK.getCode());
if(updatedLocation > 0){
log.info("移库取消库位状态更新成功,任务:{}", task.toLoggerString());
return true;
}
return false;
}
//endregion
}

View File

@ -0,0 +1,24 @@
package com.wms.bussiness;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* 任务定时器
*/
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class TaskTimer {
}

View File

@ -0,0 +1,22 @@
package com.wms.config;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component
@Order(1)
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class InitLocalConfig implements ApplicationRunner {
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
public void run(ApplicationArguments args) throws Exception {
logger.info("加载设置到内存中...");
logger.info("加载配置到内存中...");
}
}

View File

@ -0,0 +1,23 @@
package com.wms.config;
import com.github.pagehelper.PageHelper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Properties;
@Configuration
public class PageHelperConfig {
@Bean
public PageHelper pageHelper() {
PageHelper pageHelper = new PageHelper();
//添加配置也可以指定文件路径
Properties p = new Properties();
p.setProperty("helperDialect", "mysql");
p.setProperty("reasonable", "true");
p.setProperty("supportMethodsArguments", "true");
p.setProperty("params", "count=countSql");
pageHelper.setProperties(p);
return pageHelper;
}
}

View File

@ -0,0 +1,61 @@
package com.wms.constants;
import java.math.BigDecimal;
import java.util.Map;
import com.google.common.collect.ImmutableMap;
import com.wms.constants.enums.WcsTaskStatus;
import com.wms.constants.enums.WmsTaskStatus;
/**
* WMS系统所需的常量
* @author 梁州
* &#064;date 2023/2/13
*/
public class WmsConstants {
public static String EMPTY_STRING = "";
public static BigDecimal NUMBER_ONE = BigDecimal.valueOf(1);
public static String ROOT_MENU_ID = "0";
/**
* 虚拟库位设备号
*/
public static Integer VIRTUAL_LOCATION_EQUIP_ID = 11;
/**
* 入库库位类型虚拟库位
*/
public static String VIRTUAL_LOCATION_IN = "0";
/**
* 虚拟库位库区编码
*/
public static int VIRTUAL_LOCATION_AREA_ID = 99;
/**
* 空托盘编号
*/
public static String EMPTY_STOCK_GOODS_ID = "000000000";
/**
* 空托盘批次号
*/
public static String EMPTY_STOCK_BATCH_NO = "EMPTY";
/**
* 设备号对应入库口
*/
public static Map<Integer, Integer> LOCATOR_AREA_MAP = ImmutableMap.<Integer, Integer>builder()
.put(WcsTaskStatus.WAIT.getCode(), WmsTaskStatus.WAIT.getCode())
.put(WcsTaskStatus.RUN.getCode(), WmsTaskStatus.RUN.getCode())
.put(WcsTaskStatus.LEAVE.getCode(), WmsTaskStatus.RUN.getCode())
.put(WcsTaskStatus.PARK.getCode(), WmsTaskStatus.RUN.getCode())
.put(WcsTaskStatus.ARRIVE.getCode(), WmsTaskStatus.RUN.getCode())
.put(WcsTaskStatus.FINISH.getCode(), WmsTaskStatus.FINISH.getCode())
.put(WcsTaskStatus.CANCEL.getCode(), WmsTaskStatus.CANCEL.getCode())
.put(WcsTaskStatus.EXCEPTION.getCode(), WmsTaskStatus.EXCEPTION.getCode())
.build();
}

View File

@ -0,0 +1,29 @@
package com.wms.constants.enums;
/**
* 物料状态枚举
*/
public enum GoodsStatus {
OK(0, "合格"),
BAD(1, "不合格"),
DELAY(2, "延期"),
OVERDUE(3, "过期"),
SCRAP(5, "长时间未使用");
private final Integer code;
private final String value;
GoodsStatus(Integer code, String value) {
this.code = code;
this.value = value;
}
public Integer getCode() {
return code;
}
public String getValue() {
return value;
}
}

View File

@ -0,0 +1,25 @@
package com.wms.constants.enums;
public enum KateTaskStatus {
NEW(0, "待下发"),
WAIT(1, "已下发"),
RUN(2, "执行中"),
PICKING(3, "正在拣货"),
FINISH(5, "任务完成");
private final Integer code;
private final String name;
KateTaskStatus(Integer code, String name) {
this.code = code;
this.name = name;
}
public Integer getCode() {
return code;
}
public String getName() {
return name;
}
}

View File

@ -0,0 +1,27 @@
package com.wms.constants.enums;
/**
* 库位状态枚举
* /// 托盘状态和站台状态通用
*/
public enum LocationStatus {
EMPTY(0, "空闲"),
OCCUPY(1, "占用");
private final Integer code;
private final String value;
LocationStatus(Integer code, String value) {
this.code = code;
this.value = value;
}
public Integer getCode() {
return code;
}
public String getValue() {
return value;
}
}

View File

@ -0,0 +1,28 @@
package com.wms.constants.enums;
import lombok.Getter;
/**
* 盘点表状态枚举
*/
@Getter
public enum OrderCheckStatusEnum {
CREATED(0, "已创建"),
CHECKING(1, "盘点中"),
CHECKED(2, "已盘点"),
CANCELED(3, "已取消");
private final int code;
private final String desc;
OrderCheckStatusEnum(int code, String desc) {
this.code = code;
this.desc = desc;
}
}

View File

@ -0,0 +1,26 @@
package com.wms.constants.enums;
import lombok.Data;
import lombok.Getter;
/**
* 订单入库状态枚举
*
* @author 菻蔃
*/
@Getter
public enum OrderInStatusEnum {
CREATE(0, "创建"),
IN(1, "入库中"),
BINDING(2, "已绑定"),
;
private final int code;
private final String desc;
OrderInStatusEnum(int code, String desc) {
this.code = code;
this.desc = desc;
}
}

View File

@ -0,0 +1,22 @@
package com.wms.constants.enums;
import lombok.Getter;
/**
* 出库单状态的枚举
*/
@Getter
public enum OrderOutStatusEnum {
CREATED(0, "已创建"),
RUNNING(1, "执行中");
private final int code;
private final String desc;
OrderOutStatusEnum(int code, String desc) {
this.code = code;
this.desc = desc;
}
}

View File

@ -0,0 +1,27 @@
package com.wms.constants.enums;
/**
* 接口响应码枚举
*/
public enum ResponseCode {
OK(0, "正常"),
WARNING(200, "警告"),
ERROR(999, "异常");
private final Integer code;
private final String value;
ResponseCode(Integer code, String value) {
this.code = code;
this.value = value;
}
public Integer getCode() {
return code;
}
public String getValue() {
return value;
}
}

View File

@ -0,0 +1,34 @@
package com.wms.constants.enums;
/**
* 库存状态枚举
*/
public enum StockStatus {
WAIT_IN(-2, "待入库"),
IN_ING(-1, "正在入库"),
OK(0, "库存正常"),
OUT(1, "准备出库"),
MOVING(2, "正在出库"),
TRANS(3, "出库完成"),
PICKING(4, "站台拣货中"),
INVENTORY_OUT(5, "站台盘点中"),
BACKING(6, "正在回库"),
LOCK(9, "库存锁定");
private final Integer code;
private final String value;
StockStatus(Integer code, String value) {
this.code = code;
this.value = value;
}
public Integer getCode() {
return code;
}
public String getValue() {
return value;
}
}

View File

@ -0,0 +1,37 @@
package com.wms.constants.enums;
/**
* 任务类型枚举
*/
public enum TaskType {
IN(1, "入库"),
OUT(2, "出库"),
INVENTORY(3, "盘点"),
MOVE(9, "移库");
private final Integer code;
private final String value;
TaskType(Integer code, String value) {
this.code = code;
this.value = value;
}
public Integer getCode() {
return code;
}
public String getValue() {
return value;
}
public static TaskType getTaskType(Integer code) {
for (TaskType taskType : TaskType.values()) {
if (taskType.getCode().equals(code)) {
return taskType;
}
}
return null;
}
}

View File

@ -0,0 +1,31 @@
package com.wms.constants.enums;
//172.21.80.151
public enum UrlEnums {
URL_WMS_TO_WCS_SEND_TASK("WMS向WCS发送任务", "http://172.21.80.151:18990/api/wms/wmsTask/setStackerTask"),
URL_WMS_TO_WCS_CHANGE_TASK("WMS请求变更任务状态", "http://172.21.80.151:18990/api/Wms/WmsTask/ChangeTaskStatus"),
URL_WMS_TO_WCS_CONTAINER_TASK("WMS向四向车发送任务","http://192.168.16.53:9991/api/Wcs/PushTask"),
URL_WMS_TO_WCS_CONTAINERIN_TASK("WMS向四向车发送入库任务","http://192.168.16.53:19990/api/container/createInstoreTask");
//URL_WMS_TO_MES_IN("扫码上架", "http://172.21.73.210:9000/Asimco/vmesserver/wms_interface/LotGround"),
//URL_WMS_TO_MES_OUT("批次出库", "http://172.21.73.210:9000/Asimco/vmesserver/wms_interface/ReceiptOut"),
//URL_WMS_TO_MES_INVENTORY("盘点执行", "http://172.21.73.210:9000/Asimco/vmesserver/wms_interface/InventoryResult"),
//URL_WMS_TO_MES_STOCK("库存", "http://172.21.73.210:9000/Asimco/vmesserver/wms_interface/WMSStorage");
//URL_WMS_TO_MES_MOVE("批次调整", "http://172.21.73.210:9000/Asimco/vmesserver/wms_interface/LotAD");
private final String description;
private final String value;
UrlEnums(String description, String value) {
this.description = description;
this.value = value;
}
public String getDescription() {
return description;
}
public String getValue() {
return value;
}
}

View File

@ -0,0 +1,27 @@
package com.wms.constants.enums;
/**
* 载具状态
*/
public enum VehicleStatus {
IN(1, "入库中"),
ON(2, "在库中"),
OUT(3, "出库中");
private final Integer code;
private final String value;
VehicleStatus(Integer code, String value) {
this.code = code;
this.value = value;
}
public Integer getCode() {
return code;
}
public String getValue() {
return value;
}
}

View File

@ -0,0 +1,31 @@
package com.wms.constants.enums;
/**
* Wcs任务状态的枚举
*/
public enum WcsTaskStatus {
WAIT(1, "任务排队中"),
RUN(2, "任务开始执行"),
LEAVE(3, "任务已经离开初始位置"),
PARK(4, "任务到达中间点"),
ARRIVE(5, "任务到达目的地"),
FINISH(100, "任务完成"),
CANCEL(998, "任务取消"),
EXCEPTION(999, "任务异常");
private final Integer code;
private final String name;
WcsTaskStatus(Integer code, String name) {
this.code = code;
this.name = name;
}
public Integer getCode() {
return code;
}
public String getName() {
return name;
}
}

View File

@ -0,0 +1,35 @@
package com.wms.constants.enums;
/**
* Wms任务状态的枚举
*/
public enum WmsTaskStatus {
NEW(0, "任务新建,待下发"),
WAIT(1, "任务已下发"),
RUN(2, "任务开始执行"),
OUT_SUCCESS(3, "出库完成"),
TRANS_MOVE(4, "输送线转运中"),
ARRIVE_STAND(5, "到达拣选站台"),
PICKING(6, "正在拣货"),
BACKING(7, "正在回库"),
INVENTORY(8, "盘点中"),
FINISH(100, "任务完成"),
CANCEL(998, "任务取消"),
EXCEPTION(999, "任务异常");
private final Integer code;
private final String name;
WmsTaskStatus(Integer code, String name) {
this.code = code;
this.name = name;
}
public Integer getCode() {
return code;
}
public String getName() {
return name;
}
}

View File

@ -0,0 +1,8 @@
package com.wms.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class BaseController {
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
}

View File

@ -0,0 +1,87 @@
package com.wms.controller;
import com.alibaba.fastjson2.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.wms.constants.enums.ResponseCode;
import com.wms.entity.app.ResponseEntity;
import com.wms.entity.page.PageDomain;
import com.wms.entity.page.TableRequest;
import com.wms.entity.page.TableResponse;
import com.wms.entity.table.Config;
import com.wms.service.ConfigService;
import com.wms.utils.HttpUtils;
import com.wms.utils.StringUtils;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
import java.util.List;
/**
* WMS系统配置控制类
* @author 梁州
* &#064;date 2023/3/23
*/
@Controller
@CrossOrigin
@RequestMapping(value = "/wms/config")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class ConfigController extends BaseController{
/**
* 系统配置服务
*/
private final ConfigService configService;
/**
* 请求头部信息
*/
private final HttpServletRequest servletRequest;
/**
* 查找所有配置
* @return 配置
*/
@GetMapping("/getConfigs")
@ResponseBody
public List<Config> getConfigs(){
logger.info("查询系统配置");
return configService.selectConfigs("");
}
/**
* 更新系统配置
*
* @param config 配置
* @return 结果
*/
@PostMapping("/updateConfig")
@ResponseBody
@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
public String updateConfig(@RequestBody Config config) {
logger.info("更新系统配置,{}{}", config.getConfigName(), config.getConfigValue());
// 创建响应信息
ResponseEntity rsp = new ResponseEntity();
try {
configService.updateConfig(config);
} catch (Exception e) {
// 回滚事务
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
logger.info("更新系统配置错误:{}", e.getMessage());
// 返回其他异常
rsp.setCode(ResponseCode.ERROR.getCode());
rsp.setMessage(e.getMessage());
return JSON.toJSONString(rsp);
}
// 返回成功
rsp.setCode(ResponseCode.OK.getCode());
rsp.setMessage("更新系统配置成功!");
return JSON.toJSONString(rsp);
}
}

View File

@ -0,0 +1,104 @@
package com.wms.controller;
import com.alibaba.fastjson2.JSON;
import com.wms.constants.WmsConstants;
import com.wms.constants.enums.ResponseCode;
import com.wms.entity.app.ResponseEntity;
import com.wms.entity.app.display.LocationData;
import com.wms.entity.app.display.LocationInfo;
import com.wms.entity.table.Location;
import com.wms.entity.table.Stock;
import com.wms.service.LocationService;
import com.wms.service.StockService;
import com.wms.utils.HttpUtils;
import com.wms.utils.StringUtils;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.util.LinkedList;
import java.util.List;
@Controller
@CrossOrigin
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@RequestMapping(value = "/api/query")
public class DisplayController extends BaseController{
private final StockService stockService;
private final LocationService locationService;
private final HttpServletRequest servletRequest;
/**
* 大屏查询库位信息
* @param location 参数---库位
* @return 结果
*/
@GetMapping("/queryLocationInfo")
@ResponseBody
public String queryLocationInfo(@RequestParam String location) {
logger.info("接收到查询大屏库位信息请求ip地址{},参数:{}", HttpUtils.getIpAddr(servletRequest), location);
ResponseEntity response = new ResponseEntity();
if (StringUtils.isEmpty(location)) {
logger.error("查询失败,参数中库位号为空");
response.setCode(ResponseCode.ERROR.getCode());
response.setMessage("查询失败,参数中库位号为空");
return JSON.toJSONString(response);
}
Location locationQuery = new Location();
locationQuery.setLocationId(location);
List<Location> locations = locationService.selLocations(locationQuery);
if (locations.size() == 0) {
logger.error("查询失败,该库位立体库中不存在");
response.setCode(ResponseCode.ERROR.getCode());
response.setMessage("查询失败,请检查库位号正确性");
return JSON.toJSONString(response);
}
Location currentLocation = locations.get(0);
String vehicleNo = currentLocation.getVehicleId();
if (StringUtils.isEmpty(vehicleNo)) {
// 设定
LocationInfo returnData = new LocationInfo();
returnData.setLocationId(location);
returnData.setVehicleNo(WmsConstants.EMPTY_STRING);
response.setCode(ResponseCode.OK.getCode());
response.setMessage("查询成功");
response.setReturnData(returnData);
return JSON.toJSONString(response);
}
// 查询库存
Stock stockQuery = new Stock();
stockQuery.setLocationId(location);
stockQuery.setVehicleId(vehicleNo);
List<Stock> stocks = stockService.selStocks(stockQuery);
List<LocationData> locationData = new LinkedList<>();
for (Stock tempStock : stocks) {
LocationData tempData = new LocationData();
tempData.setGoodsId(tempStock.getGoodsId());
tempData.setGoodsName(tempStock.getGoodsName());
tempData.setGoodsNum(tempStock.getRealNum());
locationData.add(tempData);
}
// 设定
LocationInfo returnData = new LocationInfo();
returnData.setLocationId(location);
returnData.setVehicleNo(WmsConstants.EMPTY_STRING);
returnData.setLocationData(locationData);
response.setCode(ResponseCode.OK.getCode());
response.setMessage("查询成功");
response.setReturnData(returnData);
return JSON.toJSONString(response);
}
/**
* 查询所有库位
* @return 结果
*/
@GetMapping("/getAllLocations")
@ResponseBody
public String queryLocationInfo() {
logger.info("接收到查询大屏所有库位信息请求ip地址{}", HttpUtils.getIpAddr(servletRequest));
return JSON.toJSONString(locationService.selLocations(new Location()));
}
}

View File

@ -0,0 +1,110 @@
package com.wms.controller;
import com.alibaba.fastjson2.JSON;
import com.wms.constants.enums.KateTaskStatus;
import com.wms.constants.enums.ResponseCode;
import com.wms.entity.app.ResponseEntity;
import com.wms.entity.table.*;
import com.wms.service.*;
import com.wms.utils.HttpUtils;
import com.wms.utils.StringUtils;
import com.wms.utils.WmsUtils;
import com.wms.utils.excel.ExcelUtils;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.util.*;
/**
*
*/
@Controller
@CrossOrigin
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@RequestMapping(value = "/wms/excel")
public class ExcelController extends BaseController {
private final StockService stockService;// 库存服务
private final PartInfoService partInfoService;// 零件服务
private final HttpServletRequest servletRequest;// 请求服务
private final TaskRecordService taskRecordService;// 任务记录服务
/**
* 导入零件信息
*
* @param file 文件
* @return 导入结果
*/
@PostMapping("/uploadPartInfos")
@ResponseBody
@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
public String uploadPartInfos(@RequestPart("file") MultipartFile file) {
logger.info("接收到导入零件信息请求ip地址{}", HttpUtils.getIpAddr(servletRequest));
ResponseEntity response = new ResponseEntity();
try {
List<PartInfo> files = ExcelUtils.readMultipartFile(file, PartInfo.class);
// 添加进物料表
for (PartInfo pageInfo : files) {
if (partInfoService.selPartByPartNo(pageInfo.getMaterial()) != null) {// 当前零件号的数据已经存在过
partInfoService.modifyPart(pageInfo);
} else {// 新零件
partInfoService.addPart(pageInfo);
}
}
response.setCode(ResponseCode.OK.getCode());
response.setMessage("导入excel成功");
response.setReturnData(files);
} catch (Exception e) {
// 回滚事务
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
response.setCode(ResponseCode.ERROR.getCode());
response.setMessage(e.getMessage());
}
return JSON.toJSONString(response);
}
/**
* 导出库存数据
*
* @param response 请求
*/
@GetMapping("/downloadStockExcel")
@ResponseBody
public void downloadStockExcel(HttpServletResponse response) {
List<Stock> stocks = stockService.selStocks(new Stock());
ExcelUtils.export(response, "库存报表", stocks, Stock.class);
}
/**
* 导出入库记录
*
* @param response 请求
*/
@GetMapping("/downloadRukuExcel")
@ResponseBody
public void downloadRukuExcel(HttpServletResponse response) {
List<Task> ruku = taskRecordService.selTasks(new Task());
ExcelUtils.export(response, "入库记录报表", ruku, Task.class);
}
/**
* 导出物料信息
*
* @param response 请求
*/
@GetMapping("/downloadMaterialExcel")
@ResponseBody
public void downloadMaterialExcel(HttpServletResponse response) {
List<PartInfo> Material = partInfoService.selParts(new PartInfo());
ExcelUtils.export(response, "物料信息", Material, PartInfo.class);
}
}

View File

@ -0,0 +1,274 @@
package com.wms.controller;
import com.alibaba.fastjson2.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.wms.constants.enums.ResponseCode;
import com.wms.entity.app.ResponseEntity;
import com.wms.entity.page.PageDomain;
import com.wms.entity.page.TableRequest;
import com.wms.entity.page.TableResponse;
import com.wms.entity.table.Goods;
import com.wms.entity.table.PartInfo;
import com.wms.service.GoodsService;
import com.wms.service.PartInfoService;
import com.wms.utils.HttpUtils;
import com.wms.utils.StringUtils;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* WMS物料控制类
* @author 梁州
* &#064;date 2023/3/9
*/
@Controller
@CrossOrigin
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@RequestMapping(value = "/wms/goods")
public class GoodsController extends BaseController{
/**
* 物料服务
*/
private final GoodsService goodsService;
/**
* 零件服务
*/
private final PartInfoService partInfoService;
/**
* 请求头部信息
*/
private final HttpServletRequest servletRequest;
/**
* 查找所有零件信息
*/
@PostMapping("/getPartInfo")
@ResponseBody
public String getPartInfo(@RequestBody TableRequest<PartInfo, String> tableRequest){
logger.info("请求的ip地址{}", HttpUtils.getIpAddr(servletRequest));
logger.info("接收到查询零件数据请求:{}", JSON.toJSONString(tableRequest));
TableResponse tblResp = new TableResponse();
// 解析请求数据
if (tableRequest == null || tableRequest.getPage() == null) {
tblResp.setCode(ResponseCode.ERROR.getCode());
tblResp.setMessage("请求数据为空,无法处理!");
logger.error("请求数据为空,无法处理!");
return JSON.toJSONString(tblResp);
}
// 处理分页信息
PageDomain pageRequest = tableRequest.getPage();
// String[] orderByArr = {"location_id", "vehicle_id", "goods_id", "batch_no", "remain_num", "expiration_date", "create_time"};
String orderByStr = "material asc";
// if (StringUtils.isNotEmpty(pageRequest.getOrderByColumn()) && Arrays.asList(orderByArr).contains(StringUtils.toUnderScoreCase(pageRequest.getOrderByColumn()))) {
// orderByStr = pageRequest.getOrderBy();
// } else {
// // 默认排序
// orderByStr = "expiration_date desc";
// }
PageHelper.startPage(pageRequest.getPageNum(), pageRequest.getPageSize(), orderByStr);
List<PartInfo> parts = partInfoService.selParts(tableRequest.getParam());
PageInfo<PartInfo> partPageInfo = new PageInfo<>(parts);
tblResp.setCode(ResponseCode.OK.getCode());
tblResp.setMessage("查询零件信息成功!");
tblResp.setRows(partPageInfo.getList());
tblResp.setTotal(partPageInfo.getTotal());
return JSON.toJSONString(tblResp);
}
/**
* 更新零件信息
*
* @param partInfo 零件信息
* @return 结果
*/
@PostMapping("/updatePartInfo")
@ResponseBody
@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
public String updatePartInfo(@RequestBody PartInfo partInfo) {
logger.info("请求的ip地址{}", HttpUtils.getIpAddr(servletRequest));
logger.info("接收到更新零件信息请求:{}", JSON.toJSONString(partInfo));
// 创建响应信息
ResponseEntity rsp = new ResponseEntity();
try {
if (StringUtils.isEmpty(partInfo.getMaterial())) {// 箱号为空不执行
logger.error("请求零件号为空");
rsp.setCode(ResponseCode.ERROR.getCode());
rsp.setMessage("请求零件号为空");
return JSON.toJSONString(rsp);
}
partInfoService.modifyPart(partInfo);
} catch (Exception e) {
// 回滚事务
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
logger.info("发生异常:{}", e.getMessage());
// 返回其他异常
rsp.setCode(ResponseCode.ERROR.getCode());
rsp.setMessage(e.getMessage());
return JSON.toJSONString(rsp);
}
// 返回成功
rsp.setCode(ResponseCode.OK.getCode());
rsp.setMessage("更新零件信息成功");
return JSON.toJSONString(rsp);
}
/**
* 更新物料信息
*
* @param goods 物料
* @return 结果
*/
@PostMapping("/updateGoodsInfo")
@ResponseBody
@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
public String updateGoodsInfo(@RequestBody Goods goods) {
// 创建响应信息
ResponseEntity rsp = new ResponseEntity();
try {
goodsService.modifyGoods(goods);
} catch (Exception e) {
// 回滚事务
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
logger.info("更新物料信息发生错误:{}", e.getMessage());
// 返回其他异常
rsp.setCode(ResponseCode.ERROR.getCode());
rsp.setMessage(e.getMessage());
return JSON.toJSONString(rsp);
}
logger.info("更新物料信息成功:{}", goods.toLoggerString());
// 返回成功
rsp.setCode(ResponseCode.OK.getCode());
rsp.setMessage("更新物料信息成功");
return JSON.toJSONString(rsp);
}
@PostMapping("/queryPartInfoByPartNo")
@ResponseBody
@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
public String queryPartInfoByPartNo(@RequestBody PartInfo partInfo) {
logger.info("前台查询零件数据");
ResponseEntity rsp = new ResponseEntity();
if (partInfo == null || StringUtils.isEmpty(partInfo.getMaterial())) {
logger.info("请求查询的参数为空");
// 返回其他异常
rsp.setCode(ResponseCode.ERROR.getCode());
rsp.setMessage("请求查询的参数为空");
return JSON.toJSONString(rsp);
}
try {
PartInfo partInfoNeed = partInfoService.selPartByPartNo(partInfo.getMaterial());
if (partInfoNeed == null) {
logger.info("查询零件信息发生错误,零件号:{}", partInfo.getMaterial());
// 返回其他异常
rsp.setCode(ResponseCode.ERROR.getCode());
rsp.setMessage("查询的零件信息为空");
return JSON.toJSONString(rsp);
}
rsp.setReturnData(partInfoNeed);
} catch (Exception e) {
// 回滚事务
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
logger.info("查询零件信息发生错误:{}", e.getMessage());
// 返回其他异常
rsp.setCode(ResponseCode.ERROR.getCode());
rsp.setMessage(e.getMessage());
return JSON.toJSONString(rsp);
}
logger.info("查询零件信息成功");
// 返回成功
rsp.setCode(ResponseCode.OK.getCode());
rsp.setMessage("查询零件信息成功");
return JSON.toJSONString(rsp);
}
@PostMapping("/queryPartNo")
@ResponseBody
@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
public String queryPartNo(@RequestBody PartInfo partInfo) {
logger.info("前台查询零件数据");
ResponseEntity rsp = new ResponseEntity();
if (partInfo == null || StringUtils.isEmpty(partInfo.getMaterial())) {
logger.info("请求查询的参数为空");
// 返回其他异常
rsp.setCode(ResponseCode.ERROR.getCode());
rsp.setMessage("请求查询的参数为空");
return JSON.toJSONString(rsp);
}
try {
PartInfo query = new PartInfo();
query.setMaterial(partInfo.getMaterial());
List<PartInfo> partInfoNeed = partInfoService.selParts(query);
if (partInfoNeed.size() == 0) {
logger.info("查询零件信息发生错误,零件号:{}", partInfo.getMaterial());
// 返回其他异常
rsp.setCode(ResponseCode.ERROR.getCode());
rsp.setMessage("查询的零件信息为空");
return JSON.toJSONString(rsp);
}
rsp.setReturnData(partInfoNeed);
} catch (Exception e) {
// 回滚事务
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
logger.info("查询零件信息发生错误:{}", e.getMessage());
// 返回其他异常
rsp.setCode(ResponseCode.ERROR.getCode());
rsp.setMessage(e.getMessage());
return JSON.toJSONString(rsp);
}
logger.info("查询零件信息成功");
// 返回成功
rsp.setCode(ResponseCode.OK.getCode());
rsp.setMessage("查询零件信息成功");
return JSON.toJSONString(rsp);
}
/**
* 删除当前零件信息
*
* @param partInfo 零件
* @return 结果
*/
@PostMapping("/deletePartInfo")
@ResponseBody
@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
public String deleteVehicle(@RequestBody PartInfo partInfo) {
logger.info("请求的ip地址{}", HttpUtils.getIpAddr(servletRequest));
logger.info("接收到更新料箱信息请求:{}", JSON.toJSONString(partInfo));
// 创建响应信息
ResponseEntity rsp = new ResponseEntity();
try {
if (StringUtils.isEmpty(partInfo.getMaterial())) {// 零件号为空不做处理
logger.error("请求删除的零件号为空");
rsp.setCode(ResponseCode.ERROR.getCode());
rsp.setMessage("请求删除的零件号为空");
return JSON.toJSONString(rsp);
}
partInfoService.deletePartByPartNo(partInfo.getMaterial());
} catch (Exception e) {
// 回滚事务
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
logger.info("发生异常:{}", e.getMessage());
// 返回其他异常
rsp.setCode(ResponseCode.ERROR.getCode());
rsp.setMessage(e.getMessage());
return JSON.toJSONString(rsp);
}
// 返回成功
rsp.setCode(ResponseCode.OK.getCode());
rsp.setMessage("删除零件信息成功");
return JSON.toJSONString(rsp);
}
}

View File

@ -0,0 +1,340 @@
package com.wms.controller;
import com.alibaba.fastjson2.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.wms.constants.enums.ResponseCode;
import com.wms.constants.enums.VehicleStatus;
import com.wms.entity.app.LayerLocation;
import com.wms.entity.app.ResponseEntity;
import com.wms.entity.app.RowLocation;
import com.wms.entity.page.PageDomain;
import com.wms.entity.page.TableRequest;
import com.wms.entity.page.TableResponse;
import com.wms.entity.table.Location;
import com.wms.entity.table.Vehicle;
import com.wms.constants.WmsConstants;
import com.wms.constants.enums.LocationStatus;
import com.wms.service.LocationService;
import com.wms.service.VehicleService;
import com.wms.utils.HttpUtils;
import com.wms.utils.StringUtils;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.bind.annotation.*;
import java.util.*;
/**
* WMS库位控制类
*
* @author 梁州
* &#064;date 2023/3/6
*/
@Controller
@CrossOrigin
@RequestMapping(value = "/wms/location")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class LocationController extends BaseController {
/**
* 库位服务
*/
private final LocationService locationService;
/**
* 料箱服务
*/
private final VehicleService vehicleService;
/**
* 请求头部信息
*/
private final HttpServletRequest servletRequest;
/**
* 查询库位
*
* @param location 查询参数
* @return 结果
*/
@PostMapping("/getLocations")
@ResponseBody
public String getLocations(@RequestBody Location location) {
// 创建响应信息
ResponseEntity rsp = new ResponseEntity();
try {
// 查询出所有符合条件的库位
Location location1 = new Location();
//location1.setLocationId("A11-15-2");
//location1.setWareArea("A");
location1.setAreaId(2);
List<Location> locations = locationService.selLocations(location1);
if (locations.isEmpty()) {
logger.error("查询库位发生错误:库位不存在");
// 返回错误
rsp.setCode(ResponseCode.ERROR.getCode());
rsp.setMessage("查询库位发生错误:库位不存在");
return JSON.toJSONString(rsp);
}
List<RowLocation> rowLocations = new LinkedList<>();
// 查找到最大的排
locations.sort(Comparator.comparing(Location::getQueue).reversed());
int maxRow = locations.get(0).getQueue();
// 按排查找库位
for (int i = 0; i < maxRow; i++) {
int finalI = i;
List<Location> currentRowLocations = new ArrayList<>(locations.stream()
.filter(l -> l.getQueue().equals(finalI + 1))
.toList());
// 先查找每一层的库位
List<LayerLocation> layerLocations = new LinkedList<>();
// 找到这一排最大的层
currentRowLocations.sort(Comparator.comparing(Location::getLayer).reversed());
int maxLayer = currentRowLocations.get(0).getLayer();
// 按照每一列查找库位
for (int j = 0; j < maxLayer; j++) {
int finalJ = j;
List<Location> currentLayerLocations = currentRowLocations.stream()
.filter(l -> l.getLayer().equals(finalJ + 1))
.toList();
LayerLocation tempLayerLocation = new LayerLocation();
tempLayerLocation.setLayer(finalJ + 1);
tempLayerLocation.setCurrentColLocations(currentLayerLocations);
layerLocations.add(tempLayerLocation);
}
RowLocation tempRowLocation = new RowLocation();
tempRowLocation.setRow(finalI + 1);
tempRowLocation.setCurrentLayerLocations(layerLocations);
rowLocations.add(tempRowLocation);
}
logger.info("查询库位数据成功,库区:{}", location.getAreaId());
// 设置最终数据
rsp.setReturnData(rowLocations);
// 返回成功
rsp.setCode(ResponseCode.OK.getCode());
rsp.setMessage("查询库位成功");
return JSON.toJSONString(rsp);
} catch (Exception e) {
logger.info("查询库位发生错误:{}", e.getMessage());
// 返回其他异常
rsp.setCode(ResponseCode.ERROR.getCode());
rsp.setMessage(e.getMessage());
return JSON.toJSONString(rsp);
}
}
/**
* 更新库位状态
*
* @param location 库位
* @return 结果
*/
@PostMapping("/updateLocation")
@ResponseBody
@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
public String updateLocation(@RequestBody Location location) {
// 创建响应信息
ResponseEntity rsp = new ResponseEntity();
try {
// TODO 这里要更新料箱信息
if (StringUtils.isNotEmpty(location.getVehicleId())) {// 载具号不为空
// 判断是不是需要往载具表里面添加数据
if (vehicleService.selVehicleById(location.getVehicleId()) == null) {
// 添加新载具
Vehicle newVehicle = new Vehicle();
newVehicle.setVehicleId(location.getVehicleId());
newVehicle.setVehicleStatus(VehicleStatus.ON.getCode());
newVehicle.setCurrentLocation(location.getLocationId());
newVehicle.setIsEmpty(1);
vehicleService.addVehicle(newVehicle);
}
}
locationService.modifyLocation(location);
} catch (Exception e) {
// 回滚事务
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
logger.info("更新库位状态发生错误:{}", e.getMessage());
// 返回其他异常
rsp.setCode(ResponseCode.ERROR.getCode());
rsp.setMessage(e.getMessage());
return JSON.toJSONString(rsp);
}
// 返回成功
rsp.setCode(ResponseCode.OK.getCode());
rsp.setMessage("更新库位状态成功");
return JSON.toJSONString(rsp);
}
/**
* 更新库位状态
*
* @param location 库位
* @return 结果
*/
@PostMapping("/getAvailableLocations")
@ResponseBody
@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
public String getAvailableLocations(@RequestBody Location location) {
logger.info("查询空闲可用库位");
// 创建响应信息
ResponseEntity rsp = new ResponseEntity();
try {
Location locationQuery = new Location();
locationQuery.setAreaId(location.getAreaId());
locationQuery.setLocationStatus(LocationStatus.EMPTY.getCode());
locationQuery.setIsLock(0);
List<Location> availableLocations = locationService.selLocations(locationQuery);
rsp.setReturnData(availableLocations);
} catch (Exception e) {
// 回滚事务
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
logger.info("查询可用库位错误:{}", e.getMessage());
// 返回其他异常
rsp.setCode(ResponseCode.ERROR.getCode());
rsp.setMessage(e.getMessage());
return JSON.toJSONString(rsp);
}
// 返回成功
rsp.setCode(ResponseCode.OK.getCode());
rsp.setMessage("查询可用库位成功");
return JSON.toJSONString(rsp);
}
/**
* 查询料箱信息
* @param tableRequest 请求
* @return 结果
*/
@PostMapping("/getVehicles")
@ResponseBody
@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
public String getVehicles(@RequestBody TableRequest<Vehicle, String> tableRequest) {
logger.info("请求的ip地址{}", HttpUtils.getIpAddr(servletRequest));
logger.info("接收到查询料箱请求:{}", JSON.toJSONString(tableRequest));
TableResponse tblResp = new TableResponse();
// 解析请求数据
if (tableRequest == null || tableRequest.getPage() == null) {
tblResp.setCode(ResponseCode.ERROR.getCode());
tblResp.setMessage("请求数据为空,无法处理!");
logger.error("请求数据为空,无法处理!");
return JSON.toJSONString(tblResp);
}
// 处理分页信息
PageDomain pageRequest = tableRequest.getPage();
// String[] orderByArr = {"task_id", "task_type", "task_status", "goods_id", "goods_name", "task_priority", "expiration_date", "create_time"};
String orderByStr = "";
// if (StringUtils.isNotEmpty(pageRequest.getOrderByColumn()) && Arrays.asList(orderByArr).contains(StringUtils.toUnderScoreCase(pageRequest.getOrderByColumn()))) {
// orderByStr = pageRequest.getOrderBy();
// } else {
// // 默认排序
// orderByStr = "";
// }
Vehicle vehicleQuery = new Vehicle();
vehicleQuery.setVehicleId(tableRequest.getParam().getVehicleId());
PageHelper.startPage(pageRequest.getPageNum(), pageRequest.getPageSize(), orderByStr);
List<Vehicle> vehicles = vehicleService.selVehicles(vehicleQuery);
PageInfo<Vehicle> vehiclePageInfo = new PageInfo<>(vehicles);
tblResp.setCode(ResponseCode.OK.getCode());
tblResp.setMessage("查询料箱成功!");
tblResp.setRows(vehiclePageInfo.getList());
tblResp.setTotal(vehiclePageInfo.getTotal());
return JSON.toJSONString(tblResp);
}
/**
* 更新料箱信息
*
* @param vehicle 料箱
* @return 结果
*/
@PostMapping("/updateVehicleInfo")
@ResponseBody
@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
public String updateVehicleInfo(@RequestBody Vehicle vehicle) {
logger.info("请求的ip地址{}", HttpUtils.getIpAddr(servletRequest));
logger.info("接收到更新料箱信息请求:{}", JSON.toJSONString(vehicle));
// 创建响应信息
ResponseEntity rsp = new ResponseEntity();
try {
if (StringUtils.isEmpty(vehicle.getVehicleId())) {// 箱号为空不执行
logger.error("请求箱号为空");
rsp.setCode(ResponseCode.ERROR.getCode());
rsp.setMessage("请求箱号为空");
return JSON.toJSONString(rsp);
}
vehicleService.modifyVehicle(vehicle);
} catch (Exception e) {
// 回滚事务
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
logger.info("发生异常:{}", e.getMessage());
// 返回其他异常
rsp.setCode(ResponseCode.ERROR.getCode());
rsp.setMessage(e.getMessage());
return JSON.toJSONString(rsp);
}
// 返回成功
rsp.setCode(ResponseCode.OK.getCode());
rsp.setMessage("更新料箱信息成功");
return JSON.toJSONString(rsp);
}
/**
* 删除当前料箱信息
*
* @param vehicle 料箱
* @return 结果
*/
@PostMapping("/deleteVehicle")
@ResponseBody
@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
public String deleteVehicle(@RequestBody Vehicle vehicle) {
logger.info("请求的ip地址{}", HttpUtils.getIpAddr(servletRequest));
logger.info("接收到更新料箱信息请求:{}", JSON.toJSONString(vehicle));
// 创建响应信息
ResponseEntity rsp = new ResponseEntity();
try {
if (StringUtils.isEmpty(vehicle.getVehicleId())) {// 箱号为空不执行
logger.error("请求箱号为空");
rsp.setCode(ResponseCode.ERROR.getCode());
rsp.setMessage("请求箱号为空");
return JSON.toJSONString(rsp);
}
// 判断当前料箱是不是空箱带料不允许删除
Vehicle currentVehicle = vehicleService.selVehicleById(vehicle.getVehicleId());
if (currentVehicle != null && currentVehicle.getIsEmpty() != 1) {// 非空箱
logger.error("非空箱不允许删除");
rsp.setCode(ResponseCode.ERROR.getCode());
rsp.setMessage("非空箱不允许删除");
return JSON.toJSONString(rsp);
}
// 将库中表中是当前载具的信息清空
Location locationQuery = new Location();
locationQuery.setVehicleId(vehicle.getVehicleId());
List<Location> locations = locationService.selLocations(locationQuery);
for (Location location : locations) {
location.setVehicleId(WmsConstants.EMPTY_STRING);
locationService.modifyLocation(location);
}
vehicleService.deleteVehicle(vehicle);
} catch (Exception e) {
// 回滚事务
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
logger.info("发生异常:{}", e.getMessage());
// 返回其他异常
rsp.setCode(ResponseCode.ERROR.getCode());
rsp.setMessage(e.getMessage());
return JSON.toJSONString(rsp);
}
// 返回成功
rsp.setCode(ResponseCode.OK.getCode());
rsp.setMessage("删除料箱成功");
return JSON.toJSONString(rsp);
}
}

View File

@ -0,0 +1,60 @@
package com.wms.controller;
import com.wms.entity.common.WmsApiResponse;
import com.wms.entity.dto.orderCheck.queryOrderCheckRequest;
import com.wms.entity.table.OrderCheck;
import com.wms.service.IOrderCheckService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Slf4j
@RestController
@CrossOrigin
@RequestMapping(value = "/wms/api/orderCheck")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class OrderCheckController {
private final IOrderCheckService orderCheckService;
/**
* 查询订单
*/
@PostMapping(value = "/queryOrderCheck")
public WmsApiResponse<List<OrderCheck>> getOrderCheck(@RequestBody queryOrderCheckRequest request) {
return orderCheckService.queryOrderCheck(request);
}
/**
* 执行订单
*/
@PutMapping(value = "/executeOrderCheck/{recordId}") //更新
public WmsApiResponse<Object> executeOrderCheck(@PathVariable String recordId) {
return orderCheckService.executeOrderCheck(recordId);
}
/**
* 删除订单
*/
@DeleteMapping(value = "/deleteCheck/{recordId}")
public WmsApiResponse<Object> deleteOrderIn(@PathVariable String recordId) {
return orderCheckService.deleteOrderCheck(recordId);
}
@DeleteMapping(value = "/deleteCheckAll/{remarkReturn}")
public WmsApiResponse<Object> deleteOrderInAll(@PathVariable String remarkReturn){
return orderCheckService.deleteOrderCheckAll(remarkReturn);
}
/**
* 下发一个盘点任务
*/
@PostMapping(value = "/downInventoryTask")
public WmsApiResponse<Object> issueOrderCheck() {
return orderCheckService.issueOrderCheck();
}
}

View File

@ -0,0 +1,100 @@
package com.wms.controller;
import com.wms.entity.common.WmsApiResponse;
import com.wms.entity.dto.orderIn.bindingVehicleRequest;
import com.wms.entity.dto.orderIn.downOrderInRequest;
import com.wms.entity.dto.orderIn.queryOrderInRequest;
import com.wms.entity.dto.orderIn.updateNumRequest;
import com.wms.entity.table.AppOrderIn;
import com.wms.service.IOrderInService;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
import java.util.List;
@Slf4j
@RestController
@CrossOrigin
@RequestMapping(value = "/wms/api/orderIn")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class OrderInController {
private final IOrderInService iOrderInService;
/**
* 查询入库单
* @param request 请求参数
* @return 返回结果
*/
@PostMapping(value = "/queryOrderIn")
public WmsApiResponse<List<AppOrderIn>> queryOrderIn(@RequestBody queryOrderInRequest request) {
return iOrderInService.queryOrderIn(request);
}
/**
* 新增入库单
* @param request 请求参数
* @return 返回结果
*/
@PostMapping(value = "/addOrderIn")
public WmsApiResponse<Object> addOrderIn(@RequestBody downOrderInRequest request) {
return iOrderInService.addOrderIn(request);
}
/**
* 绑定载具
* @param request 请求参数
* @return 返回结果
*/
@PostMapping(value = "/bindingVehicle")
public WmsApiResponse<Object> bindingVehicle(@RequestBody bindingVehicleRequest request) {
return iOrderInService.bindingVehicle(request);
}
/**
* 更新数量
* @return 更新结果
*/
@PostMapping(value = "/updateForNum")
public WmsApiResponse<Object> updateForNum(@RequestBody updateNumRequest request) {
return iOrderInService.updateForNum(request);
}
/**
* 根据载具号查询入库单
* @param vehicleNo 载具号
* @return 查询结果
*/
@GetMapping(value = "/getOrderInWithVehicleNo")
public WmsApiResponse<List<AppOrderIn>> getOrderInWithVehicleNo(@RequestParam("vehicleNo") String vehicleNo) {
return iOrderInService.getOrderInWithVehicleNo(vehicleNo);
}
/**
* 解绑载具
* @param rowId 行号
* @return 解绑结果
*/
@PutMapping(value = "/unBindingVehicle/{rowId}")
public WmsApiResponse<Object> unBindingVehicle(@PathVariable String rowId) {
return iOrderInService.unBindingVehicle(rowId);
}
/**
* 删除入库单
* @param rowId 行号
* @return 删除结果
*/
@DeleteMapping(value = "/deleteOrderIn/{rowId}")
public WmsApiResponse<Object> deleteOrderIn(@PathVariable String rowId) {
return iOrderInService.deleteOrderIn(rowId);
}
}

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