1.丰尚wms最新版本

This commit is contained in:
杨学谦 2025-09-25 13:11:33 +08:00
commit b88bf05f1c
590 changed files with 101761 additions and 0 deletions

37
.gitignore vendored Normal file
View File

@ -0,0 +1,37 @@
# ---> Java
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
replay_pid*
# ---> Vue
# gitignore template for Vue.js projects
#
# Recommended template: Node.gitignore
# TODO: where does this rule come from?
docs/_book
# TODO: where does this rule come from?
test/

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

6
.idea/misc.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

8
.idea/modules.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/202501-Wms-Kate-Wuxi.iml" filepath="$PROJECT_DIR$/.idea/202501-Wms-Kate-Wuxi.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

50
.idea/workspace.xml Normal file
View File

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="9dd77fc1-3ab6-4f35-8ba8-ea75480e777f" name="更改" comment="" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="ProjectColorInfo"><![CDATA[{
"associatedIndex": 0
}]]></component>
<component name="ProjectId" id="2uR0X6Tba9IxGACyPvfDy9g6V0v" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"RunOnceActivity.ShowReadmeOnStart": "true",
"git-widget-placeholder": "master",
"last_opened_file_path": "/Users/liangzhou/代码/无锡卡特/202501-Wms-Kate-Wuxi",
"nodejs_package_manager_path": "npm",
"vue.rearranger.settings.migration": "true"
}
}]]></component>
<component name="SharedIndexes">
<attachedChunks>
<set>
<option value="bundled-jdk-9823dce3aa75-a94e463ab2e7-intellij.indexing.shared.core-IU-243.25659.39" />
<option value="bundled-js-predefined-d6986cc7102b-1632447f56bf-JavaScript-IU-243.25659.39" />
</set>
</attachedChunks>
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="应用程序级" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="默认任务">
<changelist id="9dd77fc1-3ab6-4f35-8ba8-ea75480e777f" name="更改" comment="" />
<created>1742196115930</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1742196115930</updated>
<workItem from="1742196117099" duration="2000" />
</task>
<servers />
</component>
</project>

3
README.md Normal file
View File

@ -0,0 +1,3 @@
# 202501-Wms-Kate-Wuxi
无锡卡特Wms

23
dev_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
dev_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/).

View File

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

View File

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

21688
dev_wms_client/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,60 @@
{
"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.9.8",
"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",
"sass": "^1.87.0",
"sass-loader": "^16.0.5"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/vue3-essential",
"eslint:recommended"
],
"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: 12 KiB

View File

@ -0,0 +1,17 @@
<!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 -->
</body>
</html>

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,37 @@
import request from "@/http/request";
export const updateConfig = (params) => {
return request({
url: '/config/updateConfig',
method: 'post',
data: params,
timeout: 10000
})
}
export const queryConfigsByPage = (params) => {
return request({
url: '/config/queryConfigsByPage',
method: 'post',
data: params,
timeout: 10000
})
}
export const restartSystem = (params) => {
return request({
url: '/system/restartSystem',
method: 'post',
data: params,
timeout: 10000
})
}
export const reloadConfig = (params) => {
return request({
url: '/system/reloadConfig',
method: 'post',
data: params,
timeout: 10000
})
}

View File

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

View File

@ -0,0 +1,175 @@
import request from "@/http/request";
// 上传物料基础信息
export const uploadExcelBaseGoods = (data) => {
return request({
url: '/excel/importBaseGoods',
method: 'post',
data: data,
timeout: 600000
})
}
// 上传看板
export const uploadExcelKanban = (data) => {
return request({
url: '/excel/importKanban',
method: 'post',
data: data,
timeout: 600000
})
}
// 上传dbs
export const uploadExcelDbs = (data) => {
return request({
url: '/excel/importDbs',
method: 'post',
data: data,
timeout: 600000
})
}
// 上传非服务件配料单
export const uploadExcelProduct = (data) => {
return request({
url: '/excel/importProduct',
method: 'post',
data: data,
timeout: 600000
})
}
// 上传服务件配料单
export const uploadExcelSingleProduct = (data) => {
return request({
url: '/excel/importServiceProduct',
method: 'post',
data: data,
timeout: 600000
})
}
// 上传配对关系
export const uploadExcelProductExtend = (data) => {
return request({
url: '/excel/importProductExtend',
method: 'post',
data: data,
timeout: 600000
})
}
// 上传盘点请求清单
export const uploadExcelInventoryRequest = (data) => {
return request({
url: '/excel/importInventoryRequest',
method: 'post',
data: data,
timeout: 600000
})
}
// 导出dbs
export const exportDbsWithExcel = (data) => {
return request({
url: '/excel/exportDbsWithExcel',
method: 'post',
responseType: 'blob',
data: data,
timeout: 600000
})
}
// 导出配料单
export const exportKittingBomWithExcel = (data) => {
return request({
url: '/excel/exportKittingBomWithExcel',
method: 'post',
responseType: 'blob',
data: data,
timeout: 600000
})
}
// 导出配对关系
export const exportKittingBomRelationWithExcel = (data) => {
return request({
url: '/excel/exportKittingBomRelationWithExcel',
method: 'post',
responseType: 'blob',
data: data,
timeout: 600000
})
}
// 导出物料
export const exportGoodsExcel = (data) => {
return request({
url: '/excel/exportGoodsExcel',
method: 'post',
responseType: 'blob',
data: data,
timeout: 600000
})
}
// 导出库存
export const exportStockExcel = (data) => {
return request({
url: '/excel/exportStockExcel',
method: 'post',
responseType: 'blob',
data: data,
timeout: 600000
})
}
// 导出库存更新记录
export const exportStockUpdateExcel = (data) => {
return request({
url: '/excel/exportStockUpdateExcel',
method: 'post',
responseType: 'blob',
data: data,
timeout: 600000
})
}
// 导出工作详情
export const exportWorkSummaryExcel = (data) => {
return request({
url: '/excel/exportWorkSummaryExcel',
method: 'post',
responseType: 'blob',
data: data,
timeout: 600000
})
}
// 导出看板需求
export const exportKanbanExcel = (data) => {
return request({
url: '/excel/exportKanbanExcel',
method: 'post',
responseType: 'blob',
data: data,
timeout: 600000
})
}
// 导出入库记录
export const exportInTaskRecordExcel = (data) => {
return request({
url: '/excel/exportInTaskRecordExcel',
method: 'post',
responseType: 'blob',
data: data,
timeout: 600000
})
}
// 导出出库记录
export const exportOutTaskRecordExcel = (data) => {
return request({
url: '/excel/exportOutTaskRecordExcel',
method: 'post',
responseType: 'blob',
data: data,
timeout: 600000
})
}
// 导出库位详情
export const exportLocationDetailExcel = (data) => {
return request({
url: '/excel/exportLocationDetailExcel',
method: 'post',
responseType: 'blob',
data: data,
timeout: 600000
})
}

View File

@ -0,0 +1,22 @@
import request from "@/http/request";
/**
* 分页查找物料
*/
export const getGoodsInfoByPage = (params) => {
return request({
url: '/goods/getGoodsInfoByPage',
method: 'post',
data: params
})
}
/**
* 根据物料id查询物料信息
*/
export const getGoodsInfoByGoodsId = (params) => {
return request({
url: '/goods/getGoodsInfoByGoodsId',
method: 'get',
data: params
})
}

View File

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

View File

@ -0,0 +1,19 @@
import axios from "axios";
axios.defaults.baseURL = 'https://login.microsoftonline.com/caterpillar.onmicrosoft.com'
axios.defaults.timeout = 5000;
// axios.defaults.withCredentials = true
const postToGetToken = (params) => {
return axios({
url: '/oauth2/v2.0/token',
method: 'post',
data: params,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
}
export {
postToGetToken
}

View File

@ -0,0 +1,209 @@
import request from "@/http/request";
// 查询工作
export const queryKateWorks = (params) => {
return request({
url: '/kate/queryKateWorks',
method: 'post',
data: params,
timeout: 5000
})
}
// 下发工作
export const initWorks = (params) => {
return request({
url: '/kate/initWorks',
method: 'post',
data: params,
timeout: 5000
})
}
// 查询当前工作
export const getCurrentWorks = (params) => {
return request({
url: '/kate/getCurrentWorks',
method: 'post',
data: params,
timeout: 5000
})
}
// 确认当前工作
export const confirmCurrentWork = (params) => {
return request({
url: '/kate/confirmCurrentWork',
method: 'post',
data: params,
timeout: 5000
})
}
// 获取图纸---定时显示
export const getImageOfWork = (params) => {
return request({
url: '/kate/getImageOfWork',
method: 'post',
data: params,
timeout: 5000
})
}
// 获取料盒及缺料
export const getBoxesAndLacks = (params) => {
return request({
url: '/kate/getBoxesAndLacks',
method: 'post',
data: params,
timeout: 5000
})
}
// 分页查询看板
export const queryKanbanByPage = (params) => {
return request({
url: '/kate/queryKanbanByPage',
method: 'post',
data: params,
timeout: 5000
})
}
// 生成看板需求
export const genClcKanbanRequirement = (params) => {
return request({
url: '/kate/genClcKanbanRequirement',
method: 'post',
data: params,
timeout: 5000
})
}
// 请求图纸---产线扫码
export const requestImageDetail = (params) => {
return request({
url: '/kate/requestImageDetail',
method: 'post',
data: params,
timeout: 10000
})
}
// 分页查询DBS
export const queryDbsByPage = (params) => {
return request({
url: '/kate/queryDbsByPage',
method: 'post',
data: params,
timeout: 5000
})
}
// 分页查询配料单
export const queryKittingBomByPage = (params) => {
return request({
url: '/kate/queryKittingBomByPage',
method: 'post',
data: params,
timeout: 5000
})
}
// 分页查询图纸列表
export const queryImagesByPage = (params) => {
return request({
url: '/kate/queryImagesByPage',
method: 'post',
data: params,
timeout: 5000
})
}
// 分页查询对应关系
export const queryRelationByPage = (params) => {
return request({
url: '/kate/queryRelationByPage',
method: 'post',
data: params,
timeout: 5000
})
}
export const queryWorkSummaryByPage = (params) => {
return request({
url: '/kate/queryWorkSummaryByPage',
method: 'post',
data: params,
timeout: 5000
})
}
// 查询当前工作正在配的料
export const queryWorkingGoodsByPage = (params) => {
return request({
url: '/kate/queryWorkingGoodsByPage',
method: 'post',
data: params,
timeout: 5000
})
}
// 查询缺料列表
export const getLackGoods = (params) => {
return request({
url: '/kate/getLackGoods',
method: 'post',
data: params,
timeout: 5000
})
}
// 更新工作信息
export const updateKateWorks = (params) => {
return request({
url: '/kate/updateKateWorks',
method: 'post',
data: params,
timeout: 5000
})
}
// 关闭缺料工作
export const closeCurrentWorks = (params) => {
return request({
url: '/kate/closeCurrentWorks',
method: 'post',
data: params,
timeout: 5000
})
}
// 请求料盒标签数据
export const requestPrintBoxTags = (params) => {
return request({
url: '/kate/requestPrintBoxTags',
method: 'post',
data: params,
timeout: 5000
})
}
// 删除一条dbs计划
export const deleteDbsPlan = (params) => {
return request({
url: '/kate/deleteDbsPlan',
method: 'post',
data: params,
timeout: 5000
})
}
// 获取物料需求
export const getGoodsRequirement = (params) => {
return request({
url: '/kate/getGoodsRequirement',
method: 'post',
data: params,
timeout: 5000
})
}
// 删除配料单
export const deleteKittingBom = (params) => {
return request({
url: '/kate/deleteKittingBom',
method: 'post',
data: params,
timeout: 5000
})
}
// 获取筛选条件的所有工单号列表
export const getTargetOrderList = (params) => {
return request({
url: '/kate/getTargetOrderList',
method: 'post',
data: params,
timeout: 5000
})
}

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,13 @@
import request from "@/http/request";
const getTaskRecords = (params) => {
return request({
url: '/record/getTaskRecordByPage',
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,25 @@
import request from "@/http/request";
export const queryStocksByPage = (params) => {
return request({
url: '/stock/queryStocksByPage',
method: 'post',
data: params
})
}
export const queryStocks = (params) => {
return request({
url: '/stock/queryStocks',
method: 'post',
data: params
})
}
export const queryStockUpdateByPage = (params) => {
return request({
url: '/stock/queryStockUpdateByPage',
method: 'post',
data: params
})
}

View File

@ -0,0 +1,109 @@
import request from "@/http/request";
export const requireStockIn = (params) => {
return request({
url: '/task/requireStockIn',
method: 'post',
data: params
})
}
export const requireStockOut = (params) => {
return request({
url: '/task/requireStockOut',
method: 'post',
data: params
})
}
export const getCompareData = (params) => {
return request({
url: '/task/getCompareData',
method: 'post',
data: params
})
}
export const queryStocksCompare = (params) => {
return request({
url: '/task/queryStocksCompare',
method: 'post',
data: params
})
}
export const requireVehiclesForIn = (params) => {
return request({
url: '/task/requireVehiclesForIn',
method: 'post',
data: params
})
}
export const getCurrentTask = (params) => {
return request({
url: '/task/getCurrentTask',
method: 'post',
data: params
})
}
export const getPdaData = (params) => {
return request({
url: '/task/getPdaData',
method: 'post',
data: params
})
}
export const confirmCurrentTask = (params) => {
return request({
url: '/task/confirmCurrentTask',
method: 'post',
data: params
})
}
export const confirmCurrentTaskByPDA = (params) => {
return request({
url: '/task/confirmCurrentTaskByPDA',
method: 'post',
data: params
})
}
// 请求盘点
export const requestInventory = (params) => {
return request({
url: '/task/requestInventory',
method: 'post',
data: params
})
}
// 获取盘点信息
export const getInventoryConfirm = (params) => {
return request({
url: '/task/getInventoryConfirm',
method: 'post',
data: params
})
}
// 确认盘点信息
export const confirmInventory = (params) => {
return request({
url: '/task/confirmInventory',
method: 'post',
data: params
})
}
// 获取缺料数量
export const getGoodsLackQty = (params) => {
return request({
url: '/task/getGoodsLackQty',
method: 'get',
params: {
goodsId: params.goodsId,
workOrder: params.workOrder
}
})
}

View File

@ -0,0 +1,28 @@
import request from "@/http/request";
// 删除wms任务
export const deleteWmsTask = (params) => {
return request({
url: '/taskOperation/deleteWmsTask',
method: 'post',
data: params
})
}
// 更新wms任务
export const updateWmsTask = (params) => {
return request({
url: '/taskOperation/updateWmsTask',
method: 'post',
data: params
})
}
// 更新出库单任务
export const updateOutsTask = (params) => {
return request({
url: '/taskOperation/updateOutsTask',
method: 'post',
data: params
})
}

View File

@ -0,0 +1,50 @@
import request from "@/http/request";
// 分页查询任务列表
export const queryTasksByPage = (params) => {
return request({
url: '/taskQuery/queryTasksByPage',
method: 'post',
data: params
})
}
// 分页查询入库记录
export const queryInTaskRecordByPage = (params) => {
return request({
url: '/taskQuery/queryInTaskRecordByPage',
method: 'post',
data: params
})
}
// 分页查询出库记录
export const queryOutTaskRecordByPage = (params) => {
return request({
url: '/taskQuery/queryOutTaskRecordByPage',
method: 'post',
data: params
})
}
// 分页查询拣选任务
export const queryPickTasksByPage = (params) => {
return request({
url: '/taskQuery/queryPickTasksByPage',
method: 'post',
data: params
})
}
// 分页查询出库单
export const queryOutsByPage = (params) => {
return request({
url: '/taskQuery/queryOutsByPage',
method: 'post',
data: params
})
}
// 分页查询盘点信息
export const queryInventoryRecordByPage = (params) => {
return request({
url: '/taskQuery/queryInventoryRecordByPage',
method: 'post',
data: params
})
}

View File

@ -0,0 +1,149 @@
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
// })
// }
export function getUserList(params) {
return request({
url: '/user/getUserList',
method: 'post',
data: params,
timeout: 5000
})
}
export function getRoleList(params) {
return request({
url: '/user/getRoleList',
method: 'post',
data: params,
timeout: 5000
})
}
export function getPermissionList(params) {
return request({
url: '/user/getPermissionList',
method: 'post',
data: params,
timeout: 5000
})
}
export function updateRoleInfo(params) {
return request({
url: '/user/updateRoleInfo',
method: 'post',
data: params,
timeout: 5000
})
}
export function deleteRoleInfo(params) {
return request({
url: '/user/deleteRoleInfo',
method: 'post',
data: params,
timeout: 5000
})
}
export function addRoleInfo(params) {
return request({
url: '/user/addRoleInfo',
method: 'post',
data: params,
timeout: 5000
})
}
export function getRoleOptions(params) {
return request({
url: '/user/getRoleOptions',
method: 'post',
data: params,
timeout: 5000
})
}
export function updateUserInfo(params) {
return request({
url: '/user/updateUserInfo',
method: 'post',
data: params,
timeout: 5000
})
}
export function addUserInfo(params) {
return request({
url: '/user/addUserInfo',
method: 'post',
data: params,
timeout: 5000
})
}
export function deleteUserInfo(params) {
return request({
url: '/user/deleteUserInfo',
method: 'post',
data: params,
timeout: 5000
})
}

View File

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

View File

@ -0,0 +1,19 @@
import request from "@/http/request";
// 分页查询接收日志
export const queryLogsByPage = (params) => {
return request({
url: '/log/queryLogsByPage',
method: 'post',
data: params
})
}
// 分页查询发送日志
export const queryApisByPage = (params) => {
return request({
url: '/log/queryApisByPage',
method: 'post',
data: params
})
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

@ -0,0 +1,90 @@
<template>
<el-scrollbar ref="scrollbar" :wrap-style="{ 'align-content': 'center' }">
<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, index)">
<el-tooltip effect="light" :content="tag.labelName" placement="top">
{{ tag.labelName.length > 4 ? tag.labelName.substring(0, 4) + '..' : tag.labelName }}
</el-tooltip>
</el-tag>
</div>
</el-scrollbar>
</template>
<script setup>
import store from '@/store'
import {nextTick, ref, watch} from 'vue'
import {onMounted} from 'vue';
import {useRouter} from 'vue-router';
const router = useRouter()
let tags = ref([])
const scrollbar = ref()
//
onMounted(() => {
tags.value = store.getters.getStateTagsList
nextTick(() => {
autoScroll(router.currentRoute.value.path)
})
})
//
watch(() => router.currentRoute.value.path, (newVal, oldVal) => {
if (newVal !== oldVal) {
// pathtag
autoScroll(router.currentRoute.value.path)
}
})
//
const closeTag = (tag) => {
store.commit('mutationCloseTag', tag)
}
//
const handleClose = (tag, index) => {
//
if (router.currentRoute.value.path === tag.path) {
if (tags.value.length === 1) { // ,
router.push('/home')
} else { //
if (index === 0) {
router.push(tags.value[index + 1].path)
} else {
router.push(tags.value[index - 1].path)
}
}
}
closeTag(tag) // tag
}
// tags
const handleClick = (tag) => {
router.push(tag.path)
autoScroll(router.currentRoute.value.path)
}
//
const autoScroll = (path) => {
// pathtag
tags.value.forEach((item, index) => {
if (item.path === path) {
scrollbar.value.setScrollLeft(index * 80)
}
})
}
</script>
<style scoped>
.app-tag {
display: flex;
}
.app-tag .el-tag {
display: flex;
cursor: pointer;
height: 30px;
min-width: 80px;
max-width: 80px;
margin-right: 2px;
}
.app-tag .el-tag:hover {
color: #000;
background-color: #5A9CF8;
}
</style>

View File

@ -0,0 +1,41 @@
<template>
<div class="menu-title">主菜单</div>
<!-- 侧边栏菜单区域 -->
<el-menu :default-active="route.path" 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 {useRoute} from 'vue-router'
const menuList = store.getters.getMenuList
const route = useRoute()
//
const clickMenu = (item) => {
store.commit('mutationSelectTags', item)
}
</script>
<style scoped>
.menu-title {
margin-top: 5px;
}
</style>

View File

@ -0,0 +1,72 @@
export const shortcuts = [
{
text: '今天',
value: new Date(),
},
{
text: '昨天',
value: () => {
const date = new Date()
date.setTime(date.getTime() - 3600 * 1000 * 24)
return date
},
},
]
export const labelPosition = 'top'
export const printObj = {
id: "printArea", // 这里是要打印元素的ID
popTitle: "&nbsp", // 打印的标题
extraCss: "", // 打印可引入外部的一个 css 文件
extraHead: "", // 打印头部文字
preview: false, // 是否启动预览模式默认是false
previewTitle: '打印预览', // 打印预览的标题
previewPrintBtnLabel: '预览结束,开始打印', // 打印预览的标题下方的按钮文本,点击可进入打印
zIndex: 10002, // 预览窗口的z-index默认是20002最好比默认值更高
previewBeforeOpenCallback() {
// console.log('正在加载预览窗口!');
}, // 预览窗口打开之前的callback
previewOpenCallback() { console.log('已经加载完预览窗口,预览打开了!') }, // 预览窗口打开时的callback
beforeOpenCallback() {
// console.log('开始打印之前!')
}, // 开始打印之前的callback
openCallback() {
// console.log('执行打印了!')
}, // 调用打印时的callback
closeCallback() {
// console.log('关闭了打印工具!')
}, // 关闭打印的callback(无法区分确认or取消)
clickMounted() {
// console.log('点击v-print绑定的按钮了')
},
}
// 创建打印Obj
export const getPrintObj = (printId) => {
return {
id: printId, // 这里是要打印元素的ID
popTitle: "&nbsp", // 打印的标题
extraCss: "", // 打印可引入外部的一个 css 文件
extraHead: "", // 打印头部文字
preview: false, // 是否启动预览模式默认是false
previewTitle: '打印预览', // 打印预览的标题
previewPrintBtnLabel: '预览结束,开始打印', // 打印预览的标题下方的按钮文本,点击可进入打印
zIndex: 10002, // 预览窗口的z-index默认是20002最好比默认值更高
previewBeforeOpenCallback() {
// console.log('正在加载预览窗口!');
}, // 预览窗口打开之前的callback
previewOpenCallback() { console.log('已经加载完预览窗口,预览打开了!') }, // 预览窗口打开时的callback
beforeOpenCallback() {
// console.log('开始打印之前!')
}, // 开始打印之前的callback
openCallback() {
// console.log('执行打印了!')
}, // 调用打印时的callback
closeCallback() {
// console.log('关闭了打印工具!')
}, // 关闭打印的callback(无法区分确认or取消)
clickMounted() {
// console.log('点击v-print绑定的按钮了')
},
}
}

View File

@ -0,0 +1,347 @@
// 库存状态枚举
export const stockStatusOptions = [
{
value: 0,
label: '在库中'
},
{
value: 1,
label: '出库中'
},
{
value: 2,
label: '已出库'
},
{
value: 3,
label: '回库中'
},
{
value: 4,
label: '盘点中'
},
{
value: 9,
label: '库存锁定'
}
]
// 物料状态枚举
export const goodsStatusOptions = [
{
value: 0,
label: '正常'
},
{
value: 1,
label: '不合格'
},
{
value: 2,
label: '延期'
},
{
value: 3,
label: '过期'
},
{
value: 5,
label: '长时间未使用'
}
]
// 看板状态枚举
export const kanbanStatusOptions = [
{
value: 0,
label: '空'
},
{
value: 1,
label: '满'
}
]
// dbs状态枚举
export const dbsStatusOptions = [
{
value: 0,
label: '未开始'
},
{
value: 1,
label: '已开始'
},
{
value: 2,
label: '已完成'
}
]
// 配料单枚举
export const kittingBomTypeOptions = [
{
value: 1,
label: '非服务件'
},
{
value: 2,
label: '服务件'
}
]
// 工作总结枚举
export const summaryTypeOptions = [
{
value: 1,
label: '未关闭'
},
{
value: 2,
label: '已关闭'
}
]
// 工作状态枚举
export const workStatusOptions = [
{
value: -1,
label: '已暂停'
},
{
value: 0,
label: '未开始'
},
{
value: 1,
label: '已开始'
},
{
value: 2,
label: '已完成'
}
]
// 缺料状态枚举
export const lackStatusOptions = [
{
value: 0,
label: '不缺料'
},
{
value: 1,
label: '缺料'
}
]
// 任务类型枚举
export const taskTypeOptions = [
{
value: 1,
label: '入库'
},
{
value: 2,
label: '出库'
},
{
value: 3,
label: '盘点'
}
]
// Wms任务状态枚举
export const wmsTaskStatusOptions = [
{
value: -1,
label: '暂存'
},
{
value: 0,
label: '初始化'
},
{
value: 1,
label: '已解析'
},
{
value: 2,
label: '已下发'
},
{
value: 3,
label: '正在执行'
},
{
value: 4,
label: '执行完成'
},
{
value: 98,
label: '已取消'
},
{
value: 99,
label: '执行异常'
},
]
// 拣选任务状态枚举
export const pickingTaskStatusOptions = [
{
value: -2,
label: '入库用'
},
{
value: -1,
label: '暂存中'
},
{
value: 0,
label: '待下发'
},
{
value: 1,
label: '已下发'
},
{
value: 2,
label: '执行中'
},
{
value: 3,
label: '已到达'
},
{
value: 4,
label: '已离开'
},
{
value: 5,
label: '已取消'
},
]
// 是否枚举
export const yesOrNoOptions = [
{
value: 0,
label: '否'
},
{
value: 1,
label: '是'
}
]
// 料箱状态枚举
export const vehicleStatusOptions = [
{
value: 1,
label: '入库中'
},
{
value: 2,
label: '在库中'
},
{
value: 3,
label: '出库中'
},
{
value: 9,
label: '锁定中'
}
]
// 出库单类型枚举
export const outTypeOptions = [
{
value: 1,
label: '空箱出库'
},
{
value: 2,
label: '普通出库'
},
{
value: 4,
label: '完整出库'
},
{
value: 5,
label: '入库使用'
},
{
value: 9,
label: '紧急出库'
}
]
// 是否锁定枚举
export const lockOptions = [
{
value: 0,
label: '未锁定'
},
{
value: 1,
label: '已锁定'
}
]
// 是否空闲枚举
export const occupyOptions = [
{
value: 0,
label: '空闲'
},
{
value: 1,
label: '占用'
}
]
// 盘点结果枚举
export const invResultOptions = [
{
value: -99,
label: '未盘'
},
{
value: -1,
label: '盘亏'
},
{
value: 0,
label: '正常'
},
{
value: 1,
label: '盘盈'
}
]
// 设备类型枚举
export const equipmentTypeOptions = [
{
value: 1,
label: '堆垛机'
}
]
// 设备状态枚举
export const equipmentStatusOptions = [
{
value: 0,
label: '不可用'
},
{
value: 1,
label: '可用'
}
]
// 定时器类型枚举
export const timerTypeOptions = [
{
value: 1,
label: '普通定时器'
},
{
value: 2,
label: 'Cron表达式'
}
]
// 任务状态枚举
export const jobStatusOptions = [
{
value: 0,
label: '不生效'
},
{
value: 1,
label: '生效'
}
]

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>

2
dev_wms_client/src/env.d.ts vendored Normal file
View File

@ -0,0 +1,2 @@
declare module 'element-plus/dist/locale/zh-cn.mjs';
declare module 'vue3-print-nb';

View File

@ -0,0 +1,94 @@
<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: 10px;" type="success" @click="uploadBaseGoods">上传物料基本信息</el-button>
</el-upload>
</template>
<script setup>
import store from '@/store'
import { ref, reactive } from 'vue';
import { uploadExcelBaseGoods } from '@/api/excel.js'
import { ElMessage } from 'element-plus'
import { errorBox } from '@/utils/myMessageBox';
import { sizeFormatter } from '@/utils/formatter.js'
import { loading } from '@/utils/loading.js'
import { getHashString } from '@/utils/hashUtils.js'
var currentHash = ''
const file = ref()
const uploadForm = reactive({
data: {
fileId: '',
name: '',
type: '',
size: null,
hash: '',
userName: store.getters.getUserName
}
})
const changeFile = (uploadFile) => {
file.value = uploadFile
uploadForm.data = {
fileId: file.value.raw.uid,
name: file.value.raw.name,
type: file.value.raw.type,
size: sizeFormatter(file.value.raw.size),
hash: getHashString(uploadFile),
userName: store.getters.getUserName
}
}
const uploadRef = ref()
const uploadBaseGoods = () => {
if (uploadForm == undefined || file.value == undefined) {
errorBox('请选择文件之后再上传')
return
}
if (currentHash != '' && currentHash == uploadForm.data.hash) {
errorBox('请勿重复上传')
return
}
currentHash = uploadForm.data.hash
const jsonStr = JSON.stringify(uploadForm.data);
const blob = new Blob([jsonStr], {
type: 'application/json'
});
let formData = new FormData();
// file.value.rawfilefile.valueProxy
formData.append("fileVo", blob);
formData.append("file", file.value.raw);
loading.open('导入中...')
uploadExcelBaseGoods(formData).then(res => {
if (res.data.code == 0) {
ElMessage.success(res.data.message)
clearFileInfos()
} else {
errorBox(res.data.message)
}
}).catch(err => {
console.log(err)
errorBox('上传错误')
}).finally(() => {
currentHash = ''
loading.close()
})
}
const clearFileInfos = () => {
//
uploadRef.value.clearFiles()
uploadForm.data = {
fileId: '',
name: '',
type: '',
size: null,
hash: '',
userName: store.getters.getUserName
}
file.value = undefined
}
const previewFile = () => {
}
</script>
<style scoped></style>

View File

@ -0,0 +1,98 @@
<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">选取DBS文件</el-button>
</template>
<el-button style="margin-left: 10px;" type="success" @click="uploadDbs">上传DBS数据</el-button>
</el-upload>
</template>
<script setup>
import store from '@/store'
import { ref, reactive } from 'vue';
import { uploadExcelDbs } from '@/api/excel.js'
import { ElMessage } from 'element-plus'
import { errorBox } from '@/utils/myMessageBox';
import { sizeFormatter } from '@/utils/formatter.js'
import { loading } from '@/utils/loading.js'
import { getHashString } from '@/utils/hashUtils.js'
const file = ref()
var currentHash = ''
const uploadForm = reactive({
data: {
fileId: '',
name: '',
type: '',
size: null,
hash: '',
userName: store.getters.getUserName
}
})
const changeFile = (uploadFile) => {
file.value = uploadFile
uploadForm.data = {
fileId: file.value.raw.uid,
name: file.value.raw.name,
type: file.value.raw.type,
size: sizeFormatter(file.value.raw.size),
hash: getHashString(uploadFile),
userName: store.getters.getUserName
}
}
const uploadRef = ref()
const uploadDbs = () => {
if (uploadForm == undefined || file.value == undefined) {
errorBox('请选择文件之后再上传')
return
}
if (currentHash != '' && currentHash == uploadForm.data.hash) {
errorBox('请勿重复上传')
return
}
currentHash = uploadForm.data.hash
const jsonStr = JSON.stringify(uploadForm.data);
const blob = new Blob([jsonStr], {
type: 'application/json'
});
let formData = new FormData();
// file.value.rawfilefile.valueProxy
formData.append("fileVo", blob);
formData.append("file", file.value.raw);
loading.open('导入中...')
uploadExcelDbs(formData).then(res => {
loading.close()
currentHash = ''
if (res.data.code == 0) {
ElMessage({
message: '上传成功',
type: 'success',
})
clearFileInfos()
} else {
errorBox(res.data.message)
}
}).catch(err => {
loading.close()
currentHash = ''
console.log(err)
errorBox('上传错误')
})
}
const clearFileInfos = () => {
//
uploadRef.value.clearFiles()
uploadForm.data = {
fileId: '',
name: '',
type: '',
size: null,
hash: '',
userName: store.getters.getUserName
}
file.value = undefined
}
const previewFile = () => {
}
</script>
<style scoped></style>

View File

@ -0,0 +1,98 @@
<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: 10px;" type="success" @click="uploadBaseGoods">上传盘点请求列表</el-button>
</el-upload>
</template>
<script setup>
import store from '@/store'
import {ref, reactive} from 'vue';
import {uploadExcelInventoryRequest} from '@/api/excel.js'
import {ElMessage} from 'element-plus'
import {errorBox} from '@/utils/myMessageBox';
import {sizeFormatter} from '@/utils/formatter.js'
import {loading} from '@/utils/loading.js'
import {getHashString} from '@/utils/hashUtils.js'
var currentHash = ''
const file = ref()
const uploadForm = reactive({
data: {
fileId: '',
name: '',
type: '',
size: null,
hash: '',
userName: store.getters.getUserName,
standId: store.getters.getStandId
}
})
const changeFile = (uploadFile) => {
file.value = uploadFile
uploadForm.data = {
fileId: file.value.raw.uid,
name: file.value.raw.name,
type: file.value.raw.type,
size: sizeFormatter(file.value.raw.size),
hash: getHashString(uploadFile),
userName: store.getters.getUserName,
standId: store.getters.getStandId
}
}
const uploadRef = ref()
const uploadBaseGoods = () => {
if (uploadForm === undefined || file.value === undefined) {
errorBox('请选择文件之后再上传')
return
}
if (currentHash !== '' && currentHash === uploadForm.data.hash) {
errorBox('请勿重复上传')
return
}
currentHash = uploadForm.data.hash
const jsonStr = JSON.stringify(uploadForm.data);
const blob = new Blob([jsonStr], {
type: 'application/json'
});
let formData = new FormData();
// file.value.rawfilefile.valueProxy
formData.append("fileVo", blob);
formData.append("file", file.value.raw);
loading.open('导入中...')
uploadExcelInventoryRequest(formData).then(res => {
if (res.data.code === 0) {
ElMessage.success(res.data.message)
clearFileInfos()
} else {
errorBox(res.data.message)
}
}).catch(err => {
console.log(err)
errorBox('上传错误')
}).finally(() => {
currentHash = ''
loading.close()
})
}
const clearFileInfos = () => {
//
uploadRef.value.clearFiles()
uploadForm.data = {
fileId: '',
name: '',
type: '',
size: null,
hash: '',
userName: store.getters.getUserName,
standId: store.getters.getStandId
}
file.value = undefined
}
const previewFile = () => {
}
</script>
<style scoped></style>

View File

@ -0,0 +1,98 @@
<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: 10px;" type="success" @click="uploadKanban">上传看板</el-button>
</el-upload>
</template>
<script setup>
import store from '@/store'
import { ref, reactive } from 'vue';
import { uploadExcelKanban } from '@/api/excel.js'
import { ElMessage } from 'element-plus'
import { errorBox } from '@/utils/myMessageBox';
import { sizeFormatter } from '@/utils/formatter.js'
import { loading } from '@/utils/loading.js'
import { getHashString } from '@/utils/hashUtils.js'
var currentHash = ''
const file = ref()
const uploadForm = reactive({
data: {
fileId: '',
name: '',
type: '',
size: null,
hash: '',
userName: store.getters.getUserName
}
})
const changeFile = (uploadFile) => {
file.value = uploadFile
uploadForm.data = {
fileId: file.value.raw.uid,
name: file.value.raw.name,
type: file.value.raw.type,
size: sizeFormatter(file.value.raw.size),
hash: getHashString(uploadFile),
userName: store.getters.getUserName
}
}
const uploadRef = ref()
const uploadKanban = () => {
if (uploadForm == undefined || file.value == undefined) {
errorBox('请选择文件之后再上传')
return
}
if (currentHash != '' && currentHash == uploadForm.data.hash) {
errorBox('请勿重复上传')
return
}
currentHash = uploadForm.data.hash
const jsonStr = JSON.stringify(uploadForm.data);
const blob = new Blob([jsonStr], {
type: 'application/json'
});
let formData = new FormData();
// file.value.rawfilefile.valueProxy
formData.append("fileVo", blob);
formData.append("file", file.value.raw);
loading.open('导入中...')
uploadExcelKanban(formData).then(res => {
loading.close()
currentHash = ''
if (res.data.code == 0) {
ElMessage({
message: '上传成功',
type: 'success',
})
clearFileInfos()
} else {
errorBox(res.data.message)
}
}).catch(err => {
loading.close()
currentHash = ''
console.log(err)
errorBox('上传错误')
})
}
const clearFileInfos = () => {
//
uploadRef.value.clearFiles()
uploadForm.data = {
fileId: '',
name: '',
type: '',
size: null,
hash: '',
userName: store.getters.getUserName
}
file.value = undefined
}
const previewFile = () => {
}
</script>
<style scoped></style>

View File

@ -0,0 +1,95 @@
<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: 10px;" type="success" @click="uploadProduct">上传非服务件配料清单</el-button>
</el-upload>
</template>
<script setup>
import store from '@/store'
import {ref, reactive} from 'vue';
import {uploadExcelProduct} from '@/api/excel.js'
import {errorBox, successBox} from '@/utils/myMessageBox';
import {sizeFormatter} from '@/utils/formatter.js'
import {loading} from '@/utils/loading.js'
import {getHashString} from '@/utils/hashUtils.js'
var currentHash = ''
const file = ref()
const uploadForm = reactive({
data: {
fileId: '',
name: '',
type: '',
size: null,
hash: '',
userName: store.getters.getUserName
}
})
const changeFile = (uploadFile) => {
file.value = uploadFile
uploadForm.data = {
fileId: file.value.raw.uid,
name: file.value.raw.name,
type: file.value.raw.type,
size: sizeFormatter(file.value.raw.size),
hash: getHashString(uploadFile),
userName: store.getters.getUserName
}
}
const uploadRef = ref()
const uploadProduct = () => {
if (uploadForm == undefined || file.value == undefined) {
errorBox('请选择文件之后再上传')
return
}
if (currentHash != '' && currentHash == uploadForm.data.hash) {
errorBox('请勿重复上传')
return
}
currentHash = uploadForm.data.hash
const jsonStr = JSON.stringify(uploadForm.data);
const blob = new Blob([jsonStr], {
type: 'application/json'
});
let formData = new FormData();
// file.value.rawfilefile.valueProxy
formData.append("fileVo", blob);
formData.append("file", file.value.raw);
loading.open('导入中...')
uploadExcelProduct(formData).then(res => {
loading.close()
currentHash = ''
if (res.data.code == 0) {
successBox(res.data.message)
clearFileInfos()
} else {
errorBox(res.data.message)
}
}).catch(err => {
loading.close()
currentHash = ''
console.log(err)
errorBox('上传错误')
})
}
const clearFileInfos = () => {
//
uploadRef.value.clearFiles()
uploadForm.data = {
fileId: '',
name: '',
type: '',
size: null,
hash: '',
userName: store.getters.getUserName
}
file.value = undefined
}
const previewFile = () => {
}
</script>
<style scoped></style>

View File

@ -0,0 +1,98 @@
<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: 10px;" type="success" @click="uploadProductExtend">上传总成-单片数据</el-button>
</el-upload>
</template>
<script setup>
import store from '@/store'
import { ref, reactive } from 'vue';
import { uploadExcelProductExtend } from '@/api/excel.js'
import { ElMessage } from 'element-plus'
import { errorBox } from '@/utils/myMessageBox';
import { sizeFormatter } from '@/utils/formatter.js'
import { loading } from '@/utils/loading.js'
import { getHashString } from '@/utils/hashUtils.js'
var currentHash = ''
const file = ref()
const uploadForm = reactive({
data: {
fileId: '',
name: '',
type: '',
size: null,
hash: '',
userName: store.getters.getUserName
}
})
const changeFile = (uploadFile) => {
file.value = uploadFile
uploadForm.data = {
fileId: file.value.raw.uid,
name: file.value.raw.name,
type: file.value.raw.type,
size: sizeFormatter(file.value.raw.size),
hash: getHashString(uploadFile),
userName: store.getters.getUserName
}
}
const uploadRef = ref()
const uploadProductExtend = () => {
if (uploadForm == undefined || file.value == undefined) {
errorBox('请选择文件之后再上传')
return
}
if (currentHash != '' && currentHash == uploadForm.data.hash) {
errorBox('请勿重复上传')
return
}
currentHash = uploadForm.data.hash
const jsonStr = JSON.stringify(uploadForm.data);
const blob = new Blob([jsonStr], {
type: 'application/json'
});
let formData = new FormData();
// file.value.rawfilefile.valueProxy
formData.append("fileVo", blob);
formData.append("file", file.value.raw);
loading.open('导入中...')
uploadExcelProductExtend(formData).then(res => {
loading.close()
currentHash = ''
if (res.data.code == 0) {
ElMessage({
message: '上传成功',
type: 'success',
})
clearFileInfos()
} else {
errorBox(res.data.message)
}
}).catch(err => {
loading.close()
currentHash = ''
console.log(err)
errorBox('上传错误')
})
}
const clearFileInfos = () => {
//
uploadRef.value.clearFiles()
uploadForm.data = {
fileId: '',
name: '',
type: '',
size: null,
hash: '',
userName: store.getters.getUserName
}
file.value = undefined
}
const previewFile = () => {
}
</script>
<style scoped></style>

View File

@ -0,0 +1,95 @@
<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: 10px;" type="success" @click="uploadSingleProduct">上传服务件配料单</el-button>
</el-upload>
</template>
<script setup>
import store from '@/store'
import {ref, reactive} from 'vue';
import {uploadExcelSingleProduct} from '@/api/excel.js'
import {errorBox, successBox} from '@/utils/myMessageBox';
import {sizeFormatter} from '@/utils/formatter.js'
import {loading} from '@/utils/loading.js'
import {getHashString} from '@/utils/hashUtils.js'
var currentHash = ''
const file = ref()
const uploadForm = reactive({
data: {
fileId: '',
name: '',
type: '',
size: null,
hash: '',
userName: store.getters.getUserName
}
})
const changeFile = (uploadFile) => {
file.value = uploadFile
uploadForm.data = {
fileId: file.value.raw.uid,
name: file.value.raw.name,
type: file.value.raw.type,
size: sizeFormatter(file.value.raw.size),
hash: getHashString(uploadFile),
userName: store.getters.getUserName
}
}
const uploadRef = ref()
const uploadSingleProduct = () => {
if (uploadForm == undefined || file.value == undefined) {
errorBox('请选择文件之后再上传')
return
}
if (currentHash != '' && currentHash == uploadForm.data.hash) {
errorBox('请勿重复上传')
return
}
currentHash = uploadForm.data.hash
const jsonStr = JSON.stringify(uploadForm.data);
const blob = new Blob([jsonStr], {
type: 'application/json'
});
let formData = new FormData();
// file.value.rawfilefile.valueProxy
formData.append("fileVo", blob);
formData.append("file", file.value.raw);
loading.open('导入中...')
uploadExcelSingleProduct(formData).then(res => {
loading.close()
currentHash = ''
if (res.data.code == 0) {
successBox(res.data.message)
clearFileInfos()
} else {
errorBox(res.data.message)
}
}).catch(err => {
loading.close()
currentHash = ''
console.log(err)
errorBox('上传错误')
})
}
const clearFileInfos = () => {
//
uploadRef.value.clearFiles()
uploadForm.data = {
fileId: '',
name: '',
type: '',
size: null,
hash: '',
userName: store.getters.getUserName
}
file.value = undefined
}
const previewFile = () => {
}
</script>
<style scoped></style>

View File

@ -0,0 +1,46 @@
import axios from 'axios'
const request = axios.create({
baseURL: 'http://172.18.222.253:12315/wms',
//baseURL: 'http://localhost:12315/wms',
timeout: 5000
})
// 172.18.222.253
// axios.defaults.baseURL = 'http://localhost:12315/wms'
// axios.defaults.baseURL = 'https://s4wwjasrsp01.ap.cat.com/wmsServer/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,350 @@
<template>
<el-config-provider :locale="zhCn">
<el-container class="content">
<div class="work-area">
<fieldset class="search-area">
<el-form ref="searchQueryFormRef" :model="searchQueryFormEntity"
:label-position="labelPosition" label-width="158px" style="max-width: 100%" status-icon>
<div style="display: flex;justify-content: space-between;">
<el-row>
<el-form-item label="成品类型">
<el-select-v2 style="width: 196px" v-model="searchQueryFormEntity.imageType" placeholder="成品类型"
:options="addAllOptionOfOptions(kittingBomTypeOptions)"
@change="search()" />
</el-form-item>
<el-form-item label="成品号">
<el-input v-model="searchQueryFormEntity.productId" @keyup.enter="search()" clearable/>
</el-form-item>
<el-form-item label="料盒号">
<el-input v-model="searchQueryFormEntity.boxNo" @keyup.enter="search()" clearable/>
</el-form-item>
</el-row>
<div style="align-content: center;">
<el-row>
<el-button type="primary" class="btn-search" @click="search()">查询</el-button>
<el-button type="warning" class="btn-search" @click="clearQuery()">清除输入</el-button>
</el-row>
</div>
</div>
</el-form>
</fieldset>
<div class="table-area">
<el-table :data="displayImageList" stripe border v-loading="tableLoading" class="table-class"
:max-height="maxHeight" highlight-current-row @row-click="getCurrentRow"
:header-cell-style="{ 'text-align': 'center' }" :cell-style="{ 'text-align': 'center' }"
@sort-change="handleSortChange">
<el-table-column width="65px" fixed="left">
<template v-slot="scope">
<el-radio :label="scope.row.imageId" v-model="imageId">&nbsp;</el-radio>
</template>
</el-table-column>
<el-table-column prop="imageId" label="图纸id" fixed="left" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="imageType" label="成品类型" :formatter="imageTypeFormat" min-width="120px"
sortable="custom" show-overflow-tooltip/>
<el-table-column prop="productId" label="成品号" min-width="120px" sortable="custom" show-overflow-tooltip/>
<el-table-column prop="boxNo" label="料盒号" min-width="120px" sortable="custom" show-overflow-tooltip/>
<el-table-column prop="imagePath" label="存放路径" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="imageName" label="图纸名称" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column fixed="right" label="操作" width="120px">
<template v-slot="scope">
<el-button plain type="primary" @click="requestPreview(scope.row)">预览</el-button>
</template>
</el-table-column>
</el-table>
<br/>
<el-pagination v-model:current-page="baseTableQuery.currentPage"
v-model:page-size="baseTableQuery.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="baseTableQuery.total"/>
</div>
<!-- 图片预览 -->
<el-image-viewer v-if="showImagePreview" :zoom-rate="1.2" @close="closePreview" :url-list="imgPreviewList">
<template #toolbar="{ actions, prev, next, reset, activeIndex, setActiveItem }">
<el-icon @click="actions('zoomOut')"><ZoomOut /></el-icon>
<el-icon
@click="actions('zoomIn', { enableTransition: false, zoomRate: 1.2 })"
>
<ZoomIn />
</el-icon>
<el-icon
@click="
actions('clockwise', { rotateDeg: 180, enableTransition: false })
"
>
<RefreshRight />
</el-icon>
<el-icon @click="actions('anticlockwise')"><RefreshLeft /></el-icon>
<el-icon @click="reset"><Refresh /></el-icon>
<el-icon @click="download(activeIndex)"><Download /></el-icon>
</template>
</el-image-viewer>
</div>
</el-container>
</el-config-provider>
</template>
<script setup>
import store from '@/store'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import {queryImagesByPage, requestImageDetail} from '@/api/kateWork.js'
import {ref, reactive, onMounted, nextTick, onBeforeUnmount} from 'vue'
import {ElMessage} from 'element-plus'
import {addAllOptionOfOptions, genTableRequest} from '@/utils/generator.js'
import {labelPosition} from '@/constant/form.js'
import {kittingBomTypeOptions} from '@/constant/options.js'
import {loading} from "@/utils/loading";
import {
Download,
Refresh,
RefreshLeft,
RefreshRight,
ZoomIn,
ZoomOut,
} from '@element-plus/icons-vue'
/**
* 常量定义
*/
const STAND_ID = store.getters.getStandId
const USER_NAME = store.getters.getUserName
/**
* 变量定义
*/
let maxHeight = ref(window.innerHeight * 0.55)
let tableLoading = ref(false)
let displayImageList = ref([])
let baseTableQuery = reactive({
currentPage: 1,
pageSize: 10,
total: 0,
sortBy: new Map([['boxNo', true], ['productId', true]]),// ---
standId: STAND_ID,
userName: USER_NAME
})
let searchQueryFormEntity = reactive({
imageType: -99,
productId: '',
boxNo: ''
})
let searchQueryFormRef = ref()
let imageId = ''
let showImagePreview = ref(false)
let imgPreviewList = ref([])
let selectedImageInfo = reactive({
imageId: '',
productId: '',
boxNo: '',
url: '',
base64: '',
name: ''
})
/**
* 系统方法
*/
onMounted(() => {
nextTick(() => {
window.addEventListener('resize', resizeHeight)
search()
})
})
onBeforeUnmount(() => {
nextTick(() => {
window.removeEventListener('resize', resizeHeight)
})
})
const resizeHeight = () => {
maxHeight.value = window.innerHeight * 0.55
}
/**
* 自定义方法
*/
//
const search = () => {
tableLoading.value = true
let request = genTableRequest(baseTableQuery)
//
request.imageType = searchQueryFormEntity.imageType === -99 ? null : searchQueryFormEntity.imageType
request.productId = searchQueryFormEntity.productId.trim()
request.boxNo = searchQueryFormEntity.boxNo.trim()
queryImagesByPage(request).then((res) => {
const response = res.data
if (response.code === 0) {
const data = response.data
if (data != null) {
displayImageList.value = data.lists
baseTableQuery.total = data.total
} else {
displayImageList.value = []
baseTableQuery.total = 0
}
} else {
ElMessage.error(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('查询数据异常。')
}).finally(() => {
tableLoading.value = false
})
}
const clearQuery = () => {
searchQueryFormEntity.productId = ''
searchQueryFormEntity.boxNo = ''
}
const imageTypeFormat = (row, column, cellValue, index) => {
switch (cellValue) {
case 1:
return '非服务件'
case 2:
return '服务件'
default:
return '未知类型'
}
}
const handleSortChange = (data) => {
if (baseTableQuery.sortBy.has(data.prop)) {
baseTableQuery.sortBy.delete(data.prop)
}
baseTableQuery.sortBy.set(data.prop, data.order === 'ascending')
search()
}
const getCurrentRow = (row) => {
imageId = row.imageId
}
//
const requestPreview = (row) => {
const request = {
imageId: row.imageId,
standId: STAND_ID,
userName: USER_NAME
}
loading.open('打开预览中...')
requestImageDetail(request).then(res => {
const response = res.data
if (response.code === 0) {
const results = response.data
if (results === undefined || results.length !== 1) {
ElMessage.error('无图纸或图纸歧义。')
return
}
const image = results[0]
openPreview(image)
} else {
ElMessage.error(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('查询异常')
}).finally(() => {
loading.close()
})
}
//
const openPreview = (image) => {
selectedImageInfo.imageId = image.imageId
selectedImageInfo.productId = image.productId
selectedImageInfo.boxNo = image.boxNo
selectedImageInfo.url = image.imageIp + image.imagePath + image.imageName
selectedImageInfo.base64 = 'data:image/png;base64,' + image.imageDetail
selectedImageInfo.name = image.imageName
//
showImagePreview.value = true
//
imgPreviewList.value = [selectedImageInfo.base64]
}
//
const closePreview = () => {
selectedImageInfo.imageId = ''
selectedImageInfo.productId = ''
selectedImageInfo.boxNo = ''
selectedImageInfo.url = ''
selectedImageInfo.base64 = ''
selectedImageInfo.name = ''
//
showImagePreview.value = false
//
imgPreviewList.value = []
}
//
const download = (activeIndex) => {
if (imgPreviewList.value.length === 0 || imgPreviewList.value.length < activeIndex - 1) {
ElMessage.error('没有下载数据。')
return
}
// base64,
const imgUrl = imgPreviewList.value[activeIndex]
//
const a = document.createElement('a')
a.href = imgUrl
a.setAttribute('download', selectedImageInfo.name)
a.click()
}
</script>
<style scoped>
.content {
display: flex;
width: 100%;
}
.work-area {
width: 100%;
/* padding: 5px; */
}
.search-area {
margin: auto;
min-height: fit-content;
max-height: 40%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.table-area {
margin: auto;
min-height: fit-content;
max-height: 60%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.el-form-item {
margin: 5px 5px 5px 5px;
}
.el-form-item .el-input {
width: 196px;
}
.el-form-item .el-select-v2 {
width: 196px;
}
.table-class {
margin: 5px 5px 5px 5px;
width: inherit;
}
.el-pagination {
padding-left: 5px;
}
.btn-search {
height: 30px;
width: 80px;
margin: auto 5px 5px auto;
color: black;
}
</style>

View File

@ -0,0 +1,355 @@
<template>
<el-config-provider :locale="zhCn">
<el-container class="content">
<div class="work-area">
<fieldset class="search-area">
<el-form ref="searchQueryFormRef" :model="searchQueryFormEntity" :label-position="labelPosition"
label-width="158px" style="max-width: 100%" status-icon>
<div style="display: flex;justify-content: space-between;">
<el-row>
<el-form-item label="查询类型">
<el-select-v2 style="width: 196px" v-model="searchQueryFormEntity.queryType" placeholder="查询类型"
:options="queryTypeOptions"
@change="search()"></el-select-v2>
</el-form-item>
<el-form-item label="任务类型">
<el-select-v2 style="width: 196px" v-model="searchQueryFormEntity.outType" placeholder="任务类型"
:options="addAllOptionOfOptions(outTypeOptions)"
@change="search()"></el-select-v2>
</el-form-item>
<el-form-item label="箱号">
<el-input v-model="searchQueryFormEntity.vehicleId" @keyup.enter="search()" clearable/>
</el-form-item>
<el-form-item label="料号">
<el-input v-model="searchQueryFormEntity.goodsId" @keyup.enter="search()" clearable/>
</el-form-item>
</el-row>
<div style="align-content: center;">
<el-row>
<el-button type="primary" class="btn-search" @click="search()">查询</el-button>
<el-button type="warning" class="btn-search" @click="clearQuery()">清除输入</el-button>
</el-row>
</div>
</div>
</el-form>
</fieldset>
<div class="table-area">
<el-table :data="tableData" stripe border v-loading="tableLoading" class="table-class"
:max-height="maxHeight" highlight-current-row @row-click="getCurrentRow"
:header-cell-style="{ 'text-align': 'center' }" :cell-style="{ 'text-align': 'center' }"
@sort-change="handleSortChange">
<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="taskId" label="任务号" fixed="left" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="outType" label="任务类型" fixed="left" :formatter="outsTypeFormat" min-width="120px"
sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="vehicleId" label="箱号" fixed="left" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="goodsId" label="料号" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="needNum" label="需求数量"
min-width="120px" sortable="custom" show-overflow-tooltip/>
<el-table-column prop="distributeNum" label="已分配数量" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="pickNum" label="已拣选数量" min-width="120px"
sortable="custom" show-overflow-tooltip/>
<el-table-column prop="destination" label="目标站台" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="userName" label="用户" min-width="120px"
sortable="custom" show-overflow-tooltip/>
<el-table-column prop="reason" label="原因" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="requestTime" label="请求时间" :formatter="timeFormat" min-width="120px"
sortable="custom"
show-overflow-tooltip/>
<el-table-column fixed="right" label="操作" width="170px" v-if="searchQueryFormEntity.queryType === 1">
<template v-slot="scope">
<div style="display: inline-block; align-content: center;">
<el-button type="danger"
@click="cancelOuts(scope.row)">取消</el-button>
<el-button type="success"
@click="finishOuts(scope.row)">完成</el-button>
</div>
</template>
</el-table-column>
</el-table>
<br/>
<el-pagination v-model:current-page="baseTableQuery.currentPage"
v-model:page-size="baseTableQuery.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="baseTableQuery.total"/>
</div>
</div>
</el-container>
</el-config-provider>
</template>
<script setup>
import store from '@/store'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import {queryOutsByPage} from '@/api/taskQuery.js'
import {timeFormatter, outTaskTypeFormatter} from '@/utils/formatter.js'
import {ref, reactive, onMounted, nextTick, onBeforeUnmount} from 'vue'
import {ElMessage} from 'element-plus'
import {genTableRequest} from '@/utils/generator.js'
import {labelPosition} from '@/constant/form.js'
import {outTypeOptions} from '@/constant/options.js'
import {addAllOptionOfOptions} from '@/utils/generator.js'
import {loading} from '@/utils/loading'
import {updateOutsTask} from "@/api/taskOperation";
/**
* 常量定义
*/
const STAND_ID = store.getters.getStandId
const USER_NAME = store.getters.getUserName
/**
* 变量定义
*/
let maxHeight = ref(window.innerHeight * 0.55)
let tableLoading = ref(false)
let tableData = ref([])
let baseTableQuery = reactive({
currentPage: 1,
pageSize: 10,
total: 0,
sortBy: new Map([['requestTime', true]]),//
standId: STAND_ID,
userName: USER_NAME
})
let searchQueryFormEntity = reactive({
vehicleId: '',
goodsId: '',
outType: -99,
queryType: 1
})
let searchQueryFormRef = ref()
let taskId = ''
const queryTypeOptions = [
{
label: '未关闭',
value: 1
},
{
label: '已关闭',
value: 2
}
]
/**
* 系统方法
*/
onMounted(() => {
nextTick(() => {
window.addEventListener('resize', resizeHeight)
search()
})
})
onBeforeUnmount(() => {
nextTick(() => {
window.removeEventListener('resize', resizeHeight)
})
})
const resizeHeight = () => {
maxHeight.value = window.innerHeight * 0.55
}
/**
* 自定义方法
*/
//
const search = () => {
tableLoading.value = true
let request = genTableRequest(baseTableQuery)
//
request.vehicleId = searchQueryFormEntity.vehicleId.trim()
request.goodsId = searchQueryFormEntity.goodsId.trim()
request.outType = searchQueryFormEntity.outType === -99 ? null : searchQueryFormEntity.outType
request.queryType = searchQueryFormEntity.queryType//
queryOutsByPage(request).then((res) => {
const response = res.data
if (response.code === 0) {
const data = response.data
if (data != null) {
tableData.value = data.lists
baseTableQuery.total = data.total
} else {
tableData.value = []
baseTableQuery.total = 0
}
} else {
ElMessage.error(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('查询数据异常。')
}).finally(() => {
tableLoading.value = false
})
}
const clearQuery = () => {
searchQueryFormEntity.vehicleId = ''
searchQueryFormEntity.goodsId = ''
}
const handleSortChange = (data) => {
if (baseTableQuery.sortBy.has(data.prop)) {
baseTableQuery.sortBy.delete(data.prop)
}
baseTableQuery.sortBy.set(data.prop, data.order === 'ascending')
search()
}
const getCurrentRow = (row) => {
taskId = row.taskId
}
const timeFormat = (row, column, cellValue, index) => {
return timeFormatter(cellValue)
}
const outsTypeFormat = (row, column, cellValue, index) => {
return outTaskTypeFormatter(cellValue)
}
//
const cancelOuts = (row) => {
const request = {
taskId: row.taskId,
updateType: 1,
userName: USER_NAME,
standId: STAND_ID
}
loading.open('取消中...')
updateOutsTask(request).then(res => {
const response = res.data
if (response.code === 0) {
ElMessage.success(response.message)
} else {
ElMessage.error(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('取消发生异常。')
}).finally(() => {
loading.close()
search()
})
}
//
const finishOuts = (row) => {
const request = {
taskId: row.taskId,
updateType: 2,
userName: USER_NAME,
standId: STAND_ID
}
loading.open('完成中...')
updateOutsTask(request).then(res => {
const response = res.data
if (response.code === 0) {
ElMessage.success(response.message)
} else {
ElMessage.error(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('完成发生异常。')
}).finally(() => {
loading.close()
search()
})
}
</script>
<style scoped>
.content {
display: flex;
width: 100%;
}
.work-area {
width: 100%;
/* padding: 5px; */
}
.search-area {
margin: auto;
min-height: fit-content;
max-height: 40%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.table-area {
margin: auto;
min-height: fit-content;
max-height: 60%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.el-form-item {
margin: 5px 5px 5px 5px;
}
.el-form-item .el-input {
width: 196px;
}
.el-form-item .el-input-number {
width: 196px;
}
.table-class {
margin: 5px 5px 5px 5px;
width: inherit;
}
.el-pagination {
padding-left: 5px;
}
.my-autocomplete li {
width: 196px;
line-height: normal;
padding: 7px;
}
.my-autocomplete li .name {
text-overflow: ellipsis;
overflow: hidden;
}
.my-autocomplete li .addr {
font-size: 12px;
color: #b4b4b4;
}
.my-autocomplete li .highlighted .addr {
color: #ddd;
}
.my-autocomplete li .goods_id {
color: brown;
}
.my-autocomplete li .goods_name {
color: cornflowerblue;
}
.btn-search {
height: 30px;
width: 80px;
margin: auto 5px 5px auto;
color: black;
}
</style>

View File

@ -0,0 +1,308 @@
<template>
<el-config-provider :locale="zhCn">
<el-container class="content">
<div class="work-area">
<fieldset class="search-area">
<el-form ref="kanbanQueryFormRef" :model="kanbanQuery" :label-position="labelPosition"
label-width="158px" style="max-width: 100%" status-icon>
<div style="display: flex;justify-content: space-between;">
<el-row>
<el-form-item label="料号">
<el-input v-model="kanbanQuery.goodsId" placeholder="料号" @keyup.enter="search()"
clearable/>
</el-form-item>
<el-form-item label="看板Id">
<el-input v-model="kanbanQuery.kanbanId" placeholder="看板Id"
@keyup.enter="search()" clearable/>
</el-form-item>
<el-form-item label="看板状态">
<el-select-v2 style="width: 196px" v-model="kanbanQuery.kanbanStatus" placeholder="看板状态"
:options="addAllOptionOfOptions(kanbanStatusOptions)"
@change="search()"></el-select-v2>
</el-form-item>
</el-row>
<div style="align-content: center;">
<el-row>
<el-button type="primary"
style="height: 30px; width: 80px; margin: auto 5px 5px auto; color: black;"
@click="search()">查询
</el-button>
<el-button type="warning"
style="height: 30px; width: 80px; margin: auto 5px 5px auto; color: black;"
@click="clearQuery()">清空
</el-button>
</el-row>
<el-row>
<el-button
style="height: 30px; width: 80px; margin: auto 5px 5px auto; background-color: #32CD32; color: #000;"
@click="exportExcel()">导出看板
</el-button>
</el-row>
</div>
</div>
</el-form>
</fieldset>
<div class="table-area">
<el-table :data="kanbanList" stripe border v-loading="tableLoading" class="table-class"
:max-height="maxHeight" highlight-current-row @row-click="getCurrentRow"
:header-cell-style="{ 'text-align': 'center' }" :cell-style="{ 'text-align': 'center' }"
@sort-change="handleSortChange">
<el-table-column width="65px" fixed="left">
<template v-slot="scope">
<el-radio :label="scope.row.recordId" v-model="recordId">&nbsp;</el-radio>
</template>
</el-table-column>
<el-table-column prop="recordId" label="id" fixed="left" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="goodsId" label="料号" show-overflow-tooltip sortable="custom"
min-width="120px"/>
<el-table-column prop="kanbanId" label="看板id" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="kanbanStatus" label="看板状态" sortable="custom"
:formatter="kanbanStatusFormat" min-width="120px" show-overflow-tooltip/>
</el-table>
<br/>
<el-pagination v-model:current-page="baseTableQuery.currentPage"
v-model:page-size="baseTableQuery.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="baseTableQuery.total"/>
</div>
</div>
</el-container>
</el-config-provider>
</template>
<script setup>
import store from '@/store'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import {queryKanbanByPage} from '@/api/kateWork.js'
import {ref, reactive, onMounted, nextTick, onBeforeUnmount} from 'vue'
import {ElMessage} from 'element-plus'
import {genTableRequest, addAllOptionOfOptions} from '@/utils/generator.js'
import {labelPosition} from '@/constant/form'
import {kanbanStatusOptions} from '@/constant/options'
import {dateFormatter} from '@/utils/formatter.js'
import {exportKanbanExcel} from '@/api/excel.js'
/**
* 常量定义
*/
const STAND_ID = store.getters.getStandId
const USER_NAME = store.getters.getUserName
/**
* 变量定义
*/
let maxHeight = ref(window.innerHeight * 0.55)
let tableLoading = ref(false)
let kanbanList = ref([])
let baseTableQuery = reactive({
currentPage: 1,
pageSize: 10,
total: 0,
sortBy: new Map([['goodsId', true]]),
standId: STAND_ID,
userName: USER_NAME
})
let kanbanQuery = reactive({
goodsId: '',
kanbanId: '',
kanbanStatus: -99
})
let kanbanQueryFormRef = ref()
let recordId = ''
/**
* 系统方法
*/
onMounted(() => {
nextTick(() => {
window.addEventListener('resize', resizeHeight)
search()
})
})
onBeforeUnmount(() => {
nextTick(() => {
window.removeEventListener('resize', resizeHeight)
})
})
const resizeHeight = () => {
maxHeight.value = window.innerHeight * 0.55
}
/**
* 自定义方法
*/
//
const search = () => {
tableLoading.value = true
let request = genTableRequest(baseTableQuery)
//
request.goodsId = kanbanQuery.goodsId
request.kanbanId = kanbanQuery.kanbanId
request.kanbanStatus = kanbanQuery.kanbanStatus === -99 ? null : kanbanQuery.kanbanStatus
queryKanbanByPage(request).then((res) => {
const response = res.data
if (response.code === 0) {
const data = response.data
if (data != null) {
kanbanList.value = data.lists
baseTableQuery.total = data.total
} else {
kanbanList.value = []
baseTableQuery.total = 0
}
} else {
ElMessage.error(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('查询看板信息异常。')
}).finally(() => {
tableLoading.value = false
})
}
//
const clearQuery = () => {
kanbanQuery.goodsId = ''
kanbanQuery.kanbanId = ''
kanbanQuery.kanbanStatus = -99
}
//
const handleSortChange = (data) => {
if (baseTableQuery.sortBy.has(data.prop)) {
baseTableQuery.sortBy.delete(data.prop)
}
baseTableQuery.sortBy.set(data.prop, data.order.toLowerCase() === 'ascending')
search()
}
const getCurrentRow = (row) => {
recordId = row.recordId
}
//
const kanbanStatusFormat = (row, column, cellValue, index) => {
switch (cellValue) {
case 0:
return '空'
case 1:
return '满'
default:
return '异常'
}
}
//
const exportExcel = () => {
const params = {
goodsId: kanbanQuery.goodsId,
kanbanId: kanbanQuery.kanbanId,
kanbanStatus: kanbanQuery.kanbanStatus == -99 ? null : kanbanQuery.kanbanStatus,
standId: STAND_ID,
userName: USER_NAME
}
exportKanbanExcel(params).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) {
console.log(e)
ElMessage.error('下载文件失败')
}
}).catch(err => {
console.log(err)
ElMessage.error('导出失败')
})
}
</script>
<style scoped>
.content {
display: flex;
width: 100%;
}
.work-area {
width: 100%;
/* padding: 5px; */
}
.search-area {
margin: auto;
min-height: fit-content;
max-height: 40%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.table-area {
margin: auto;
min-height: fit-content;
max-height: 60%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.el-form-item {
margin: 5px 5px 5px 5px;
}
.el-form-item .el-input {
width: 196px;
}
.table-class {
margin: 5px 5px 5px 5px;
width: inherit;
}
.el-pagination {
padding-left: 5px;
}
.my-autocomplete li {
width: 196px;
line-height: normal;
padding: 7px;
}
.my-autocomplete li .name {
text-overflow: ellipsis;
overflow: hidden;
}
.my-autocomplete li .addr {
font-size: 12px;
color: #b4b4b4;
}
.my-autocomplete li .highlighted .addr {
color: #ddd;
}
.my-autocomplete li .goods_id {
color: brown;
}
.my-autocomplete li .goods_name {
color: cornflowerblue;
}
</style>

View File

@ -0,0 +1,673 @@
<template>
<el-config-provider :locale="zhCn">
<el-container class="content">
<div class="work-area">
<fieldset class="search-area">
<el-form ref="dbsQueryFormRef" :model="dbsQueryFormEntity" :label-position="labelPosition"
label-width="158px" style="max-width: 100%" status-icon>
<div style="display: flex;justify-content: space-between;">
<el-row>
<el-form-item label="工单号">
<el-input v-model="dbsQueryFormEntity.workOrder" @keyup.enter="search()" clearable/>
</el-form-item>
<el-form-item label="零件号">
<el-input v-model="dbsQueryFormEntity.productId" @keyup.enter="search()" clearable/>
</el-form-item>
<el-form-item label="状态">
<el-select-v2 style="width: 196px" v-model="dbsQueryFormEntity.dbsStatus" placeholder="工单状态"
:options="addAllOptionOfOptions(dbsStatusOptions)"
@change="search()"></el-select-v2>
</el-form-item>
<el-form-item label="计划开工日期">
<el-date-picker v-model="dbsQueryFormEntity.planStartDate" type="date"
placeholder="计划开工日期" :shortcuts="shortcuts" style="width: 196px;" clearable/>
</el-form-item>
<el-form-item label="需求工单列表">
<el-select
v-model="selectedOrders"
multiple
collapse-tags
collapse-tags-tooltip
placeholder="请选择工单列表"
style="width: 196px"
>
<el-option
v-for="item in orderOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-button style="height: 32px; background-color: #40E0D0;" class="btn-search"
@click="addAllListOfSearch()">全部添加
</el-button>
</el-row>
<div style="align-content: center;">
<el-row>
<el-button type="primary" class="btn-search" @click="search()">查询</el-button>
<el-button type="warning" class="btn-search" @click="clearQuery()">清除输入</el-button>
<el-button style="background-color: #6495ED;" class="btn-search"
@click="openRequirementDialog()">生成需求
</el-button>
</el-row>
<el-row>
<el-button style="background-color: #00CED1;" class="btn-search"
@click="openUploadDialog()">导入DBS
</el-button>
<el-button type="success" class="btn-search"
@click="exportExcel()">导出excel
</el-button>
<el-button style="background-color: #ADD8E6;" class="btn-search"
@click="genKanban()">生成看板
</el-button>
</el-row>
</div>
</div>
</el-form>
</fieldset>
<div class="table-area">
<el-table :data="displayDbs" stripe border v-loading="tableLoading" class="table-class"
:max-height="maxHeight" highlight-current-row @row-click="getCurrentRow" :row-style="rowStyle"
:header-cell-style="{ 'text-align': 'center' }" :cell-style="{ 'text-align': 'center' }"
@sort-change="handleSortChange">
<el-table-column width="65px" fixed="left">
<template v-slot="scope">
<el-radio :label="scope.row.dbsId" v-model="dbsId">&nbsp;</el-radio>
</template>
</el-table-column>
<el-table-column prop="workOrder" label="工单" fixed="left" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="productIdOrigin" label="元零件号" fixed="left" min-width="120px"
sortable="custom" show-overflow-tooltip/>
<el-table-column prop="productId" label="零件号" fixed="left" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="testPlanStartDate" label="Test计划开始时间" :formatter="dateFormat"
fixed="left" min-width="160px" sortable="custom" show-overflow-tooltip/>
<el-table-column prop="testPlanFinishDate" label="Test计划完成时间" :formatter="dateFormat"
min-width="160px" sortable="custom" show-overflow-tooltip/>
<el-table-column prop="pntPlanStartDate" label="PNT计划开始时间" :formatter="dateFormat"
min-width="170px" sortable="custom" show-overflow-tooltip/>
<el-table-column prop="pntPlanFinishDate" label="PNT计划完成时间" :formatter="dateFormat"
min-width="170px" sortable="custom" show-overflow-tooltip/>
<el-table-column prop="planProduction" label="计划产量" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="equipmentName" label="设备名称" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="workShift" label="班次" sortable="custom" min-width="120px"
show-overflow-tooltip/>
<el-table-column prop="family" label="Family" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="testNo" label="Test No#" sortable="custom" min-width="120px"
show-overflow-tooltip/>
<el-table-column prop="dbsStatus" label="状态" :formatter="dbsStatusFormat" fixed="right"
min-width="120px" sortable="custom" show-overflow-tooltip/>
<el-table-column prop="workStand" label="工作站台" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="realWorkDate" label="实际工作日期" sortable="custom" :formatter="dateFormat"
min-width="140px" show-overflow-tooltip/>
<el-table-column prop="finishTime" label="完成时间" min-width="120px" :formatter="timeFormat"
sortable="custom" show-overflow-tooltip/>
<el-table-column prop="kittingRemark" label="K料备注" sortable="custom" min-width="120px"
show-overflow-tooltip/>
<el-table-column prop="remark" label="备注" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column fixed="right" label="操作" width="240px">
<template v-slot="scope">
<el-button plain type="primary" @click="addRequirement(scope.row)">添加需求</el-button>
<el-button plain type="danger" @click="deleteCurrentRow(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<br/>
<el-pagination v-model:current-page="baseTableQuery.currentPage"
v-model:page-size="baseTableQuery.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="baseTableQuery.total"/>
</div>
<el-dialog v-model="showGoodsRequireDialog" title="物料需求" width="50%" center>
<el-button type="success" style="margin-left: 5px" @click="exportRequirements()">导出需求</el-button>
<el-table :data="goodsRequireList" stripe border class="table-class" max-height="450px"
:header-cell-style="{ 'text-align': 'center' }" :cell-style="{ 'text-align': 'center' }">
<el-table-column prop="goodsId" show-overflow-tooltip label="料号" fixed="left"/>
<el-table-column prop="goodsDesc" show-overflow-tooltip label="描述"/>
<el-table-column prop="needQty" show-overflow-tooltip label="需求数量"/>
<el-table-column prop="stockQty" show-overflow-tooltip label="库存数量"/>
<el-table-column prop="lackQty" show-overflow-tooltip label="缺少数量"/>
<el-table-column prop="goodsType" show-overflow-tooltip label="补料类型"/>
<el-table-column prop="stockType" show-overflow-tooltip label="存放类型"/>
</el-table>
</el-dialog>
<el-dialog v-model="showDbsUploadDialog" title="上传DBS" width="40%" draggable :show-close="true">
<fieldset class="search-area">
<legend>导入dbs</legend>
<UploadExcelDbs></UploadExcelDbs>
</fieldset>
</el-dialog>
</div>
</el-container>
</el-config-provider>
</template>
<script setup>
import store from '@/store'
import {
queryDbsByPage,
deleteDbsPlan,
getGoodsRequirement,
genClcKanbanRequirement,
getTargetOrderList
} from '@/api/kateWork.js'
import {dateFormatter, timeFormatter} from '@/utils/formatter.js'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import {ref, reactive, onMounted, nextTick, onBeforeUnmount} from 'vue'
import {ElMessage, ElMessageBox} from 'element-plus'
import {genTableRequest, addAllOptionOfOptions} from '@/utils/generator.js'
import {labelPosition, shortcuts} from '@/constant/form'
import {dbsStatusOptions} from '@/constant/options'
import UploadExcelDbs from '@/excel/UploadExcelDbs.vue'
import {exportDbsWithExcel} from '@/api/excel'
import {loading} from "@/utils/loading";
import {useRouter} from 'vue-router';
import {exportToExcel} from "@/utils/excelUtils";
/**
* 常量定义
*/
const USER_NAME = store.getters.getUserName
const STAND_ID = store.getters.getStandId
const router = useRouter()
/**
* 变量定义
*/
let maxHeight = ref(window.innerHeight * 0.55)
let tableLoading = ref(false)
let displayDbs = ref([])
let baseTableQuery = reactive({
currentPage: 1,
pageSize: 10,
total: 0,
sortBy: new Map([['workOrder', true]]),//
standId: STAND_ID,
userName: USER_NAME
})
let dbsQueryFormEntity = reactive({
workOrder: '',
productId: '',
dbsStatus: -99,
planStartDate: null
})
let dbsQueryFormRef = ref()
let dbsId = ''
let showDbsUploadDialog = ref(false)
let selectedOrders = ref([])
let orderOptions = ref([])
let goodsRequireList = ref([])
let showGoodsRequireDialog = ref(false)
/**
* 系统方法
*/
onMounted(() => {
nextTick(() => {
window.addEventListener('resize', resizeHeight)
search()
})
})
onBeforeUnmount(() => {
nextTick(() => {
window.removeEventListener('resize', resizeHeight)
})
})
const resizeHeight = () => {
maxHeight.value = window.innerHeight * 0.55
}
/**
* 自定义方法
*/
//
const search = () => {
tableLoading.value = true
let request = genTableRequest(baseTableQuery)
//
request.workOrder = dbsQueryFormEntity.workOrder.trim()
request.productId = dbsQueryFormEntity.productId.trim()
request.dbsStatus = dbsQueryFormEntity.dbsStatus === -99 ? null : dbsQueryFormEntity.dbsStatus
request.planStartDate = dateFormatter(dbsQueryFormEntity.planStartDate)
queryDbsByPage(request).then((res) => {
const response = res.data
if (response.code === 0) {
const data = response.data
if (data != null) {
displayDbs.value = data.lists
baseTableQuery.total = data.total
} else {
displayDbs.value = []
baseTableQuery.total = 0
}
} else {
ElMessage.error(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('查询DBS数据异常。')
}).finally(() => {
tableLoading.value = false
})
}
const clearQuery = () => {
dbsQueryFormEntity.workOrder = ''
dbsQueryFormEntity.productId = ''
dbsQueryFormEntity.dbsStatus = -99
dbsQueryFormEntity.planStartDate = null
}
const dbsStatusFormat = (row, column, cellValue, index) => {
switch (cellValue) {
case 0:
return '未开始'
case 1:
return '已开始'
case 2:
return '已完成'
default:
return '未知状态'
}
}
const dateFormat = (row, column, cellValue, index) => {
return dateFormatter(cellValue)
}
const timeFormat = (row, column, cellValue, index) => {
return timeFormatter(cellValue)
}
const rowStyle = ({row, rowIndex}) => {
if (row.dbsStatus === 2) {
return {"color": "green"}
}
}
const handleSortChange = (data) => {
if (baseTableQuery.sortBy.has(data.prop)) {
baseTableQuery.sortBy.delete(data.prop)
}
baseTableQuery.sortBy.set(data.prop, data.order.toLowerCase() === 'ascending')
search()
}
const getCurrentRow = (row) => {
dbsId = row.dbsId
}
const exportExcel = () => {
const params = {
workOrder: dbsQueryFormEntity.workOrder,
productId: dbsQueryFormEntity.productId,
dbsStatus: dbsQueryFormEntity.dbsStatus === -99 ? null : dbsQueryFormEntity.dbsStatus,
planStartDate: dateFormatter(dbsQueryFormEntity.planStartDate)
}
exportDbsWithExcel(params).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 = 'DBS计划' + 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) {
console.log(e)
ElMessage.error('下载文件失败')
}
}).catch(err => {
console.log(err)
ElMessage.error('导出失败')
})
}
// dbs
const deleteCurrentRow = (row) => {
ElMessageBox.confirm(
'当前操作涉及删除工单计划。\n是否确认',
'警告',
{
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
}
).then(() => {
const request = {
dbsId: row.dbsId,
userName: USER_NAME,
standId: STAND_ID
}
loading.open('删除中...')
deleteDbsPlan(request).then(res => {
const response = res.data
if (response.code === 0) {
ElMessage.success(response.message)
} else {
ElMessage.error(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('删除异常')
}).finally(() => {
search()
loading.close()
})
}).catch(() => {
ElMessage.info('操作取消')
})
}
const openUploadDialog = () => {
showDbsUploadDialog.value = true
}
//
const addRequirement = (row) => {
const workOrder = row.workOrder
if (workOrder === undefined || workOrder === '') {
ElMessage.error('请先选择工单')
return
}
//
if (orderOptions.value.length > 0) {
const oldOption = orderOptions.value.find((item) => {
return item.value === workOrder
})
if (oldOption === undefined) {
orderOptions.value.push({
label: workOrder,
value: workOrder
})
}
} else {
orderOptions.value.push({
label: workOrder,
value: workOrder
})
}
addSelectWorkOrders(workOrder)
}
//
const addSelectWorkOrders = (workOrder) => {
if (selectedOrders.value.find((item) => {
return item === workOrder
}) === undefined) {
selectedOrders.value.push(workOrder)
} else {
ElMessage.error('请勿重复添加工单')
}
}
//
const openRequirementDialog = () => {
if (selectedOrders.value.length === 0) {
ElMessage.error('请选择工单。')
return
}
//
const request = {
orderIds: selectedOrders.value,
userName: USER_NAME,
standId: STAND_ID
}
getGoodsRequirement(request).then(res => {
const response = res.data
if (response.code === 0) {
if (response.data != null && response.data.length > 0) {
goodsRequireList.value = response.data
} else {
goodsRequireList.value = []
}
showGoodsRequireDialog.value = true
//
downloadSelectedOrders()
} else {
ElMessage.error(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('获取需求列表异常。')
})
}
//
const exportRequirements = () => {
try {
const header = {
goodsId: '料号',
goodsDesc: '物料描述',
needQty: '需求数量',
stockQty: '库存数量',
lackQty: '缺少数量',
goodsType: '补料类型',
stockType: '存放类型'
}
exportToExcel(header, goodsRequireList.value, '工单需求', '工单需求')
} catch (e) {
console.log(e)
ElMessage.error('导出需求异常。')
}
}
//
const genKanban = () => {
if (selectedOrders.value.length === 0) {
ElMessage.error('请选择工单。')
return
}
const request = {
orderIds: selectedOrders.value,
standId: STAND_ID,
userName: USER_NAME
}
loading.open('生成中...')
genClcKanbanRequirement(request).then(res => {
const response = res.data
if (response.code === 0) {
//
downloadSelectedOrders()
//
if (response.data !== null && response.data.length > 0) {
downloadLackOrders(response.data)
ElMessage.success('生成看板需求成功,但部分物料缺少看板。')
} else {
ElMessage.success('生成看板需求成功。')
}
//
const menuItem = store.getters.getMenuItemByPath('/clcKanban')
if (menuItem !== undefined) {
store.commit('mutationSelectTags', menuItem)
router.push(menuItem.path)
}
} else {
ElMessage.error(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('生成看板需求异常。')
}).finally(() => {
loading.close()
})
}
//
const addAllListOfSearch = () => {
loading.open('添加中...')
const request = {
userName: USER_NAME,
standId: STAND_ID,
workOrder: dbsQueryFormEntity.workOrder.trim(),
productId: dbsQueryFormEntity.productId.trim(),
planStartDate: dateFormatter(dbsQueryFormEntity.planStartDate)
}
getTargetOrderList(request).then(res => {
const response = res.data
if (response.code === 0) {
//
addOrders(response.data)
} else {
ElMessage.error(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('获取工单号列表异常。')
}).finally(() => {
loading.close()
})
}
//
const addOrders = (orderList) => {
if (orderList === undefined || orderList.length === 0) {
//
return
}
for (let i = 0; i < orderList.length; i++) {
const workOrder = orderList[i]
//
if (orderOptions.value.length > 0) {
const oldOption = orderOptions.value.find((item) => {
return item.value === workOrder
})
if (oldOption === undefined) {
orderOptions.value.push({
label: workOrder,
value: workOrder
})
}
} else {
orderOptions.value.push({
label: workOrder,
value: workOrder
})
}
//
if (selectedOrders.value.find((item) => {
return item === workOrder
}) === undefined) {
selectedOrders.value.push(workOrder)
}
}
}
//
const downloadSelectedOrders = () => {
try {
const header = {
workOrder: '工单号'
}
//
const selectedOrdersEntity = selectedOrders.value.map((item) => {
return {
workOrder: item
}
})
exportToExcel(header, selectedOrdersEntity, '已选工单列表', '已选工单列表')
} catch (e) {
console.log(e)
ElMessage.error('导出选择的工单列表异常。')
}
}
//
const downloadLackOrders = (lackKanbanList) => {
try {
const header = {
goodsId: '料号',
needKanbanQty: '需要看板数量',
haveKanbanQty: '已有看板数量',
lackKanbanQty: '缺少看板数量',
}
exportToExcel(header, lackKanbanList, '缺少看板', '缺少看板详情')
} catch (e) {
console.log(e)
ElMessage.error('导出缺少看板详情异常。')
}
}
</script>
<style scoped>
.content {
display: flex;
width: 100%;
}
.work-area {
width: 100%;
/* padding: 5px; */
}
.search-area {
margin: auto;
min-height: fit-content;
max-height: 40%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.table-area {
margin: auto;
min-height: fit-content;
max-height: 60%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.el-form-item {
margin: 5px 5px 5px 5px;
}
.el-form-item .el-input {
width: 196px;
}
.table-class {
margin: 5px 5px 5px 5px;
width: inherit;
}
.el-pagination {
padding-left: 5px;
}
.my-autocomplete li {
width: 196px;
line-height: normal;
padding: 7px;
}
.my-autocomplete li .name {
text-overflow: ellipsis;
overflow: hidden;
}
.my-autocomplete li .addr {
font-size: 12px;
color: #b4b4b4;
}
.my-autocomplete li .highlighted .addr {
color: #ddd;
}
.my-autocomplete li .goods_id {
color: brown;
}
.my-autocomplete li .goods_name {
color: cornflowerblue;
}
.btn-search {
height: 30px;
width: 80px;
margin: auto 5px 5px auto;
color: black;
}
</style>

View File

@ -0,0 +1,263 @@
<template>
<el-config-provider :locale="zhCn">
<el-container class="content">
<div class="work-area">
<fieldset class="search-area">
<el-form ref="searchQueryFormRef" :model="searchQueryFormEntity" :label-position="labelPosition"
label-width="158px" style="max-width: 100%" status-icon>
<div style="display: flex;justify-content: space-between;">
<el-row>
<el-form-item label="设备ID">
<el-input v-model="searchQueryFormEntity.equipmentId" @keyup.enter="search()" clearable/>
</el-form-item>
<el-form-item label="设备类型">
<el-select-v2 style="width: 196px;" v-model="searchQueryFormEntity.equipmentType"
placeholder="设备类型"
:options="addAllOptionOfOptions(equipmentTypeOptions)"
@change="search()"></el-select-v2>
</el-form-item>
<el-form-item label="设备状态">
<el-select-v2 style="width: 196px;" v-model="searchQueryFormEntity.equipmentStatus"
placeholder="设备状态"
:options="addAllOptionOfOptions(equipmentStatusOptions)"
@change="search()"></el-select-v2>
</el-form-item>
<el-form-item label="设备名称">
<el-input v-model="searchQueryFormEntity.equipmentName" @keyup.enter="search()" clearable/>
</el-form-item>
</el-row>
<div style="align-content: center;">
<el-row>
<el-button type="primary" class="btn-search" @click="search()">查询</el-button>
<el-button type="warning" class="btn-search" @click="clearQuery()">清除输入</el-button>
</el-row>
</div>
</div>
</el-form>
</fieldset>
<div class="table-area">
<el-table :data="tableData" stripe border v-loading="tableLoading" class="table-class"
:max-height="maxHeight" highlight-current-row @row-click="getCurrentRow"
:header-cell-style="{ 'text-align': 'center' }" :cell-style="{ 'text-align': 'center' }"
@sort-change="handleSortChange">
<el-table-column width="65px" fixed="left">
<template v-slot="scope">
<el-radio :label="scope.row.equipmentId" v-model="equipmentId">&nbsp;</el-radio>
</template>
</el-table-column>
<el-table-column prop="equipmentId" label="设备ID" fixed="left" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="equipmentName" label="设备名称" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="equipmentType" label="设备类型" min-width="120px" :formatter="equipmentTypeFormat"
sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="equipmentStatus" label="设备状态" :formatter="equipmentStatusFormat"
min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="equipmentDesc" label="设备描述" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="lastUpdateTime" label="最后更新时间" min-width="180px" sortable="custom"
:formatter="timeFormat" show-overflow-tooltip/>
<el-table-column prop="lastUpdateUser" label="最后更新用户" min-width="120px" sortable="custom"
show-overflow-tooltip/>
</el-table>
<br/>
<el-pagination v-model:current-page="baseTableQuery.currentPage"
v-model:page-size="baseTableQuery.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="baseTableQuery.total"/>
</div>
</div>
</el-container>
</el-config-provider>
</template>
<script setup>
import store from '@/store'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import {timeFormatter} from '@/utils/formatter.js'
import {ref, reactive, onMounted, nextTick, onBeforeUnmount} from 'vue'
import {ElMessage} from 'element-plus'
import {genTableRequest, addAllOptionOfOptions} from '@/utils/generator.js'
import {labelPosition} from '@/constant/form.js'
import {getEquipmentsByPage} from "@/api/equipment";
import {equipmentTypeOptions, equipmentStatusOptions} from "@/constant/options";
/**
* 常量定义
*/
const STAND_ID = store.getters.getStandId
const USER_NAME = store.getters.getUserName
/**
* 变量定义
*/
let maxHeight = ref(window.innerHeight * 0.55)
let tableLoading = ref(false)
let tableData = ref([])
let baseTableQuery = reactive({
currentPage: 1,
pageSize: 10,
total: 0,
sortBy: new Map([['equipmentId', true]]),// ID
standId: STAND_ID,
userName: USER_NAME
})
let searchQueryFormEntity = reactive({
equipmentId: '',
equipmentType: -99,
equipmentStatus: -99,
equipmentName: '',
equipmentDesc: ''
})
let searchQueryFormRef = ref()
let equipmentId = ''
/**
* 系统方法
*/
onMounted(() => {
nextTick(() => {
window.addEventListener('resize', resizeHeight)
search()
})
})
onBeforeUnmount(() => {
nextTick(() => {
window.removeEventListener('resize', resizeHeight)
})
})
const resizeHeight = () => {
maxHeight.value = window.innerHeight * 0.55
}
/**
* 自定义方法
*/
//
const search = () => {
tableLoading.value = true
let request = genTableRequest(baseTableQuery)
//
request.equipmentId = searchQueryFormEntity.equipmentId.trim() || null
request.equipmentType = searchQueryFormEntity.equipmentType === -99 ? null : searchQueryFormEntity.equipmentType
request.equipmentStatus = searchQueryFormEntity.equipmentStatus === -99 ? null : searchQueryFormEntity.equipmentStatus
request.equipmentName = searchQueryFormEntity.equipmentName.trim() || null
request.equipmentDesc = searchQueryFormEntity.equipmentDesc.trim() || null
getEquipmentsByPage(request).then((res) => {
const response = res.data
if (response.code === 0) {
const data = response.data
if (data != null) {
tableData.value = data.lists
baseTableQuery.total = data.total
} else {
tableData.value = []
baseTableQuery.total = 0
}
} else {
ElMessage.error(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('查询数据异常。')
}).finally(() => {
tableLoading.value = false
})
}
const clearQuery = () => {
searchQueryFormEntity.equipmentId = ''
searchQueryFormEntity.equipmentType = -99
searchQueryFormEntity.equipmentStatus = -99
searchQueryFormEntity.equipmentName = ''
searchQueryFormEntity.equipmentDesc = ''
}
const handleSortChange = (data) => {
if (baseTableQuery.sortBy.has(data.prop)) {
baseTableQuery.sortBy.delete(data.prop)
}
baseTableQuery.sortBy.set(data.prop, data.order.toLowerCase() === 'ascending')
search()
}
const getCurrentRow = (row) => {
equipmentId = row.equipmentId
}
const timeFormat = (row, column, cellValue, index) => {
return timeFormatter(cellValue)
}
const equipmentTypeFormat = (row, column, cellValue, index) => {
const option = equipmentTypeOptions.find(item => item.value === cellValue)
return option ? option.label : cellValue
}
const equipmentStatusFormat = (row, column, cellValue, index) => {
return cellValue === 1 ? '可用' : '不可用'
}
</script>
<style scoped>
.content {
display: flex;
width: 100%;
}
.work-area {
width: 100%;
/* padding: 5px; */
}
.search-area {
margin: auto;
min-height: fit-content;
max-height: 40%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.table-area {
margin: auto;
min-height: fit-content;
max-height: 60%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.el-form-item {
margin: 5px 5px 5px 5px;
}
.el-form-item .el-input {
width: 196px;
}
.el-form-item .el-input-number {
width: 196px;
}
.el-form-item .el-select-v2 {
width: 196px;
}
.table-class {
margin: 5px 5px 5px 5px;
width: inherit;
}
.el-pagination {
padding-left: 5px;
}
.btn-search {
height: 30px;
width: 80px;
margin: auto 5px 5px auto;
color: black;
}
</style>

View File

@ -0,0 +1,322 @@
<template>
<el-config-provider :locale="zhCn">
<el-container class="content">
<div class="work-area">
<fieldset class="search-area">
<el-form ref="searchQueryFormRef" :model="searchQueryFormEntity" :label-position="labelPosition"
label-width="158px" style="max-width: 100%" status-icon>
<div style="display: flex;justify-content: space-between;">
<el-row>
<el-form-item label="料号">
<el-input v-model="searchQueryFormEntity.goodsId" @keyup.enter="search()"
clearable/>
</el-form-item>
<el-form-item label="描述">
<el-input v-model="searchQueryFormEntity.goodsDesc" @keyup.enter="search()"
clearable/>
</el-form-item>
</el-row>
<div style="align-content: center;">
<el-row>
<el-button type="primary" class="btn-search" @click="search()">查询</el-button>
<el-button type="warning" class="btn-search" @click="clearQuery()">清除输入</el-button>
</el-row>
<el-row>
<el-button style="background-color: #00CED1;" class="btn-search"
@click="openUploadDialog()">导入数据
</el-button>
<el-button type="success" class="btn-search"
@click="exportExcel()">导出excel
</el-button>
</el-row>
</div>
</div>
</el-form>
</fieldset>
<div class="table-area">
<el-table :data="tableData" stripe border v-loading="tableLoading" class="table-class"
:max-height="maxHeight" highlight-current-row @row-click="getCurrentRow"
:header-cell-style="{ 'text-align': 'center' }" :cell-style="{ 'text-align': 'center' }"
@sort-change="handleSortChange">
<el-table-column width="65px" fixed="left">
<template v-slot="scope">
<el-radio :label="scope.row.goodsId" v-model="goodsId">&nbsp;</el-radio>
</template>
</el-table-column>
<el-table-column prop="goodsId" label="料号" fixed="left" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="goodsDescription" label="描述" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="plant" label="工厂" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="vendorName" label="供应商" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="isSled" label="SLED管理" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="sledDays" label="SLED天数" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="feedingType" label="补料类型" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="boxQty" label="每盒数量" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="maxBoxNum" label="最大盒数" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="putArea" label="存放区域" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="hotPoint" label="热点区域" min-width="120px" sortable="custom"
show-overflow-tooltip/>
</el-table>
<br/>
<el-pagination v-model:current-page="baseTableQuery.currentPage"
v-model:page-size="baseTableQuery.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="baseTableQuery.total"/>
</div>
<el-dialog v-model="showUploadDialog" title="上传物料信息" width="40%" draggable :show-close="true">
<fieldset class="search-area">
<legend>导入基础信息</legend>
<UploadExcelBaseGoods></UploadExcelBaseGoods>
</fieldset>
<fieldset class="search-area">
<legend>导入看板信息</legend>
<UploadExcelKanban></UploadExcelKanban>
</fieldset>
</el-dialog>
</div>
</el-container>
</el-config-provider>
</template>
<script setup>
import store from '@/store'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import {getGoodsInfoByPage} from '@/api/goods.js'
import {ref, reactive, onMounted, nextTick, onBeforeUnmount} from 'vue'
import {ElMessage} from 'element-plus'
import {genTableRequest} from '@/utils/generator.js'
import {labelPosition} from '@/constant/form.js'
import UploadExcelBaseGoods from '@/excel/UploadExcelBaseGoods.vue'
import UploadExcelKanban from '@/excel/UploadExcelKanban.vue'
import {exportGoodsExcel} from "@/api/excel";
import {dateFormatter} from "@/utils/formatter";
/**
* 常量定义
*/
const STAND_ID = store.getters.getStandId
const USER_NAME = store.getters.getUserName
/**
* 变量定义
*/
let maxHeight = ref(window.innerHeight * 0.55)
let tableLoading = ref(false)
let tableData = ref([])
let baseTableQuery = reactive({
currentPage: 1,
pageSize: 10,
total: 0,
sortBy: new Map([['goodsId', true]]),//
standId: STAND_ID,
userName: USER_NAME
})
let searchQueryFormEntity = reactive({
goodsId: '',
goodsDesc: ''
})
let searchQueryFormRef = ref()
let rowEditFlag = ref(false)
let goodsId = ''
let rowEditFormRef = ref()
let rowFormEntity = reactive({})
let showUploadDialog = ref(false)
/**
* 系统方法
*/
onMounted(() => {
nextTick(() => {
window.addEventListener('resize', resizeHeight)
search()
})
})
onBeforeUnmount(() => {
nextTick(() => {
window.removeEventListener('resize', resizeHeight)
})
})
const resizeHeight = () => {
maxHeight.value = window.innerHeight * 0.55
}
/**
* 自定义方法
*/
//
const search = () => {
tableLoading.value = true
let request = genTableRequest(baseTableQuery)
//
request.goodsId = searchQueryFormEntity.goodsId.trim()
request.goodsDesc = searchQueryFormEntity.goodsDesc.trim()
getGoodsInfoByPage(request).then((res) => {
const response = res.data
if (response.code === 0) {
const data = response.data
if (data != null) {
tableData.value = data.lists
baseTableQuery.total = data.total
} else {
tableData.value = []
baseTableQuery.total = 0
}
} else {
ElMessage.error(response.message)
}
}).catch(err => {
ElMessage.error('查询数据异常。')
}).finally(() => {
tableLoading.value = false
})
}
const clearQuery = () => {
searchQueryFormEntity.goodsId = ''
searchQueryFormEntity.goodsDesc = ''
}
const handleSortChange = (data) => {
if (baseTableQuery.sortBy.has(data.prop)) {
baseTableQuery.sortBy.delete(data.prop)
}
baseTableQuery.sortBy.set(data.prop, data.order.toLowerCase() === 'ascending')
search()
}
const openUploadDialog = () => {
showUploadDialog.value = true
}
const getCurrentRow = (row) => {
goodsId = row.goodsId
}
const exportExcel = () => {
const params = {
goodsId: searchQueryFormEntity.goodsId,
goodsDesc: searchQueryFormEntity.goodsDesc,
userName: USER_NAME
}
exportGoodsExcel(params).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) {
console.log(e)
ElMessage.error('下载文件失败')
}
}).catch(err => {
console.log(err)
ElMessage.error('导出失败')
})
}
</script>
<style scoped>
.content {
display: flex;
width: 100%;
}
.work-area {
width: 100%;
/* padding: 5px; */
}
.search-area {
margin: auto;
min-height: fit-content;
max-height: 40%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.table-area {
margin: auto;
min-height: fit-content;
max-height: 60%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.el-form-item {
margin: 5px 5px 5px 5px;
}
.el-form-item .el-input {
width: 196px;
}
.el-form-item .el-input-number {
width: 196px;
}
.table-class {
margin: 5px 5px 5px 5px;
width: inherit;
}
.el-pagination {
padding-left: 5px;
}
.my-autocomplete li {
width: 196px;
line-height: normal;
padding: 7px;
}
.my-autocomplete li .name {
text-overflow: ellipsis;
overflow: hidden;
}
.my-autocomplete li .addr {
font-size: 12px;
color: #b4b4b4;
}
.my-autocomplete li .highlighted .addr {
color: #ddd;
}
.my-autocomplete li .goods_id {
color: brown;
}
.my-autocomplete li .goods_name {
color: cornflowerblue;
}
.btn-search {
height: 30px;
width: 80px;
margin: auto 5px 5px auto;
color: black;
}
</style>

View File

@ -0,0 +1,588 @@
<template>
<el-config-provider :locale="zhCn">
<el-container class="content">
<div class="work-area">
<fieldset class="main-area">
<el-form ref="inTaskRef" :model="inTaskEntity" :label-position="labelPosition" label-width="158px"
style="max-width: 100%" :rules="rules" status-icon>
<div style="display: flex;justify-content: space-between;">
<el-row>
<el-form-item label="入库类型" prop="emptyTask">
<el-select-v2 style="width: 196px; height: 80px; font-size: 25px" v-model="inTaskEntity.emptyTask" placeholder="请选择入库类型"
:options="inTypeOptions"
:disabled="taskRequestEntity.vehicleId !== ''"></el-select-v2>
</el-form-item>
<el-form-item label="箱号" prop="vehicleId">
<el-input style="width: 256px; height: 80px; font-size: 35px" v-model="inTaskEntity.vehicleId" ref="vehicleId"
:disabled="taskRequestEntity.vehicleId !== ''" clearable
@keyup.enter="handleEnter()"/>
</el-form-item>
<el-form-item label="料号">
<el-input style="width: 256px; height: 80px; font-size: 35px" v-model="inTaskEntity.goodsId" ref="goodsId"
:disabled="inTaskEntity.emptyTask" clearable @keyup.enter="handleEnter()"/>
</el-form-item>
<el-form-item label="数量">
<el-input-number style="width: 256px; height: 80px; line-height: 80px; font-size: 35px" v-model.number="inTaskEntity.opNum" ref="opNum"
:disabled="inTaskEntity.emptyTask" controls-position="right" :min="1" clearable
@keyup.enter="handleEnter()"/>
</el-form-item>
</el-row>
<el-row>
<el-button type="success"
style="height: 50px; width: 100px; margin: auto 5px auto 5px; font-size: large; color: black;"
@click="confirmBinding()">绑定物料
</el-button>
<el-button type="warning"
style="height: 50px; width: 100px; margin: auto 5px auto 5px; font-size: large; color: black;"
@click="clearInput()">清除输入
</el-button>
<el-button type="primary"
style="height: 50px; width: 100px; margin: auto 5px auto 5px; font-size: large; color: black;"
@click="openOutForInDialog()">入库料扫码
</el-button>
</el-row>
</div>
</el-form>
</fieldset>
<fieldset class="confirm-area" v-if="taskRequestEntity.vehicleId !== ''">
<el-form ref="taskRequestRef" :model="taskRequestEntity" :label-position="labelPosition"
label-width="158px" style="max-width: 100%" :rules="rules" status-icon>
<div style="display: flex;justify-content: space-between;">
<el-row>
<el-form-item label="入库类型">
<el-select-v2 style="width: 196px" v-model="taskRequestEntity.emptyTask" placeholder="请选择入库类型"
:options="inTypeOptions" disabled></el-select-v2>
</el-form-item>
<el-form-item label="箱号">
<el-input v-model="taskRequestEntity.vehicleId" disabled/>
</el-form-item>
</el-row>
<el-row>
<el-button type="success" ref="sendTaskRef"
style="height: 50px; width: 100px; margin: auto 5px auto 5px; font-size: large; color: black;"
@click="confirmTasks()">下发任务
</el-button>
<el-button type="danger"
style="height: 50px; width: 100px; margin: auto 5px auto 5px; font-size: large; color: black;"
@click="cancelBinding()">取消绑定
</el-button>
</el-row>
</div>
</el-form>
<el-table :data="taskRequestEntity.goodsInfo" stripe border class="table-class" max-height="450px"
:header-cell-style="{ 'text-align': 'center' }" :cell-style="{ 'text-align': 'center' }"
:row-style="{ 'height': '80px', 'font-size': '30px' }"
v-if="taskRequestEntity.goodsInfo.length != 0">
<el-table-column prop="goodsId" label="零件号" fixed="left"/>
<el-table-column prop="opNum" label="数量"/>
<el-table-column fixed="right" label="操作">
<template v-slot="scope">
<el-button plain type="warning" @click="removeThisRow(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</fieldset>
<el-dialog v-model="showInOutDialog" title="入库清单扫码" width="70%" draggable>
<fieldset class="main-area">
<el-form ref="outForInRef" :model="outForInEntity" :label-position="labelPosition"
label-width="158px" style="max-width: 100%" :rules="outForInRules" status-icon
@submit.native.prevent>
<div style="display: flex; justify-content: space-between;">
<el-row>
<el-form-item label="料号">
<el-input style="width: 256px; height: 80px; font-size: 35px" v-model="outForInEntity.goodsId" ref="forInGoodsId" clearable
@keyup.enter="addForInGoods()"/>
</el-form-item>
</el-row>
<el-row>
<el-button type="success"
style="height: 50px; width: 100px; margin: auto 5px auto 5px; font-size: large; color: black;"
@click="addForInGoods()">添加物料
</el-button>
</el-row>
</div>
</el-form>
</fieldset>
<fieldset class="confirm-area" v-if="outForInRequestEntity.goodsIds.length != 0">
<div style="display: flex; justify-content: space-between;">
<el-button type="success"
style="height: 50px; width: 100px; margin: auto 5px auto auto; font-size: large; color: black;"
@click="confirmCallVehicles()">确认需求
</el-button>
</div>
<el-table ref="outForInTableRef" :data="outForInRequestEntity.goodsIds" stripe border
class="table-class" max-height="200px" :header-cell-style="{ 'text-align': 'center' }"
:cell-style="{ 'text-align': 'center' }" :row-style="{ 'height': '80px', 'font-size': '30px' }">
<el-table-column prop="goodsId" label="料号" fixed="left"/>
<el-table-column fixed="right" label="操作">
<template v-slot="scope">
<el-button plain type="warning" @click="popThisGoodsId(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</fieldset>
</el-dialog>
</div>
</el-container>
</el-config-provider>
</template>
<script setup>
import store from '@/store'
import {requireStockIn, requireVehiclesForIn} from '@/api/task.js'
import {errorBox, successBox} from '@/utils/myMessageBox.js'
import {ElMessage, ElMessageBox} from 'element-plus'
import {nextTick, onMounted, reactive, ref} from 'vue'
import {loading} from '@/utils/loading.js'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import {labelPosition} from '@/constant/form'
import {getGoodsInfoByGoodsId} from "@/api/goods";
const inTypeOptions = [
{
label: '空箱入库',
value: true
},
{
label: '非空箱入库',
value: false
}
]
const rules = reactive({
emptyTask: [
{required: true, message: '请选择入库类型。'}
],
vehicleId: [
{required: true, message: '请输入箱号。'}
]
})
const vehicleId = ref()
const goodsId = ref()
const opNum = ref()
const sendTaskRef = ref()
let inTaskRef = ref()
let inTaskEntity = reactive({
emptyTask: false,
vehicleId: '',
goodsId: '',
opNum: null
})
let taskRequestRef = ref()
let taskRequestEntity = reactive({
emptyTask: false,
vehicleId: '',
origin: store.getters.getStandId,
goodsInfo: [],
standId: store.getters.getStandId,
userName: store.getters.getUserName
})
let showInOutDialog = ref(false)
let outForInRef = ref()
let outForInEntity = reactive({
goodsId: '',
})
const outForInRules = reactive({
goodsId: [
{required: true, message: '请输入料号。'}
]
})
const forInGoodsId = ref()
let outForInRequestEntity = reactive({
goodsIds: [],
origin: store.getters.getStandId,
standId: store.getters.getStandId,
userName: store.getters.getUserName
})
const outForInTableRef = ref()
onMounted(() => {
nextTick(() => {
vehicleId.value.focus()
})
})
//
const handleEnter = () => {
changeFocus()
}
//
const changeFocus = () => {
//
inTaskEntity.vehicleId = inTaskEntity.vehicleId.toUpperCase().trim()
inTaskEntity.goodsId = inTaskEntity.goodsId.toUpperCase().trim()
if (inTaskEntity.vehicleId === '') {
vehicleId.value.focus()
return
}
//
if (inTaskEntity.vehicleId !== '') {
const vehicleArray = inTaskEntity.vehicleId.split('-')
if (vehicleArray.length !== 2) {
errorBox('箱号格式不正确正确格式为“ASRS-XXXX”。')
vehicleId.value.focus()
return
} else {
if (vehicleArray[0] !== 'ASRS' || !numberCheck(vehicleArray[1]) || vehicleArray[1].length !== 4) {
errorBox('箱号格式不正确正确格式为“ASRS-XXXX”。')
vehicleId.value.focus()
return
} else if (parseInt(vehicleArray[1]) < 1 || parseInt(vehicleArray[1]) > 2200) {
errorBox('箱号范围是00012200。')
vehicleId.value.focus()
return
}
}
}
if (inTaskEntity.opNum != null) {
if (inTaskEntity.opNum < 0 || inTaskEntity.opNum > 99999) {
errorBox('数量不正确应该为1-99999之间的整数值。')
opNum.value.focus()
return
}
}
//
if (!inTaskEntity.emptyTask) {
if (inTaskEntity.goodsId === '') {
goodsId.value.focus()
return
} else {
//
inTaskEntity.goodsId = inTaskEntity.goodsId.toUpperCase().trim()
if (inTaskEntity.goodsId.substring(0, 1) === 'P') {
//
loading.open('请求中,请稍等...')
getGoodsInfoByGoodsId(inTaskEntity.goodsId).then(res => {
const goodsResponse = res.data
if (goodsResponse.code !== 0) {
// P
inTaskEntity.goodsId = inTaskEntity.goodsId.substring(1)
}
}).catch(err => {
console.log(err)
}).finally(() => {
loading.close()
})
}
}
if (inTaskEntity.opNum == null || inTaskEntity.opNum === '') {
opNum.value.focus()
return
}
}
if (inTaskEntity.goodsId === inTaskEntity.vehicleId || inTaskEntity.goodsId === inTaskEntity.opNum || inTaskEntity.vehicleId === inTaskEntity.opNum) {
errorBox('箱号、料号、数量必须为互不相同。')
goodsId.value.focus()
return
}
addBinding()
}
//
const numberCheck = (numberStr) => {
if (numberStr == null || numberStr === '') {
return false
}
try {
return !isNaN(parseInt(numberStr))
} catch (e) {
return false
}
}
//
const clearInput = () => {
if (taskRequestEntity.vehicleId !== '') {
if (!taskRequestEntity.emptyTask) {
inTaskEntity.goodsId = ''
inTaskEntity.opNum = null
}
} else {
inTaskEntity.vehicleId = ''
if (!inTaskEntity.emptyTask) {
inTaskEntity.goodsId = ''
inTaskEntity.opNum = null
}
}
}
//
const confirmBinding = () => {
//
inTaskEntity.vehicleId = inTaskEntity.vehicleId.toUpperCase().trim()
inTaskEntity.goodsId = inTaskEntity.goodsId.toUpperCase().trim()
//
if (!inTaskEntity.emptyTask && inTaskEntity.goodsId === '' && inTaskEntity.vehicleId !== '') {
if (inTaskEntity.vehicleId === '') {
ElMessage.error("请输入箱号。")
vehicleId.value.focus()
return
}
//
if (inTaskEntity.vehicleId !== '') {
const vehicleArray = inTaskEntity.vehicleId.split('-')
if (vehicleArray.length !== 2) {
errorBox('箱号格式不正确正确格式为“ASRS-XXXX”。')
vehicleId.value.focus()
return
} else {
if (vehicleArray[0] !== 'ASRS' || !numberCheck(vehicleArray[1]) || vehicleArray[1].length !== 4) {
errorBox('箱号格式不正确正确格式为“ASRS-XXXX”。')
vehicleId.value.focus()
return
} else if (parseInt(vehicleArray[1]) < 1 || parseInt(vehicleArray[1]) > 2200) {
errorBox('箱号范围是00012200。')
vehicleId.value.focus()
return
}
}
}
ElMessageBox.confirm(
'非空箱入库未输入料号。\n是否继续绑定',
'警告',
{
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
}
).then(() => {
addBinding()
}).catch(() => {
ElMessage.info('操作取消')
})
} else {
handleEnter()
}
}
//
const addBinding = () => {
if (taskRequestEntity.vehicleId !== '' && taskRequestEntity.vehicleId !== inTaskEntity.vehicleId) {
errorBox('请下发已绑定的任务或取消绑定后重试。')
return
}
if (taskRequestEntity.vehicleId === '') {
if (inTaskEntity.vehicleId === '') {
errorBox('请输入箱号。')
vehicleId.value.focus()
return
}
if (!inTaskEntity.emptyTask) {
if (inTaskEntity.goodsId !== '' && inTaskEntity.opNum != null && inTaskEntity.opNum > 0) {
//
taskRequestEntity.goodsInfo.push({
goodsId: inTaskEntity.goodsId.trim().toUpperCase(),
opNum: inTaskEntity.opNum
})
inTaskEntity.goodsId = ''
inTaskEntity.opNum = null
}
}
//
taskRequestEntity.emptyTask = inTaskEntity.emptyTask
taskRequestEntity.vehicleId = inTaskEntity.vehicleId.trim().toUpperCase()
} else {
if (!taskRequestEntity.emptyTask) {
if (inTaskEntity.goodsId === '') {
errorBox('请输入料号。')
goodsId.value.focus()
return
}
if (inTaskEntity.opNum == null || inTaskEntity.opNum === 0) {
errorBox('请输入正确的数量。')
opNum.value.focus()
return
}
//
taskRequestEntity.goodsInfo.push({
goodsId: inTaskEntity.goodsId.trim().toUpperCase(),
opNum: inTaskEntity.opNum
})
inTaskEntity.goodsId = ''
inTaskEntity.opNum = null
} else {
//
errorBox('空入库不允许多次下发。')
return
}
}
goodsId.value.focus()
}
//
const confirmTasks = () => {
//
if (!taskRequestEntity.emptyTask && taskRequestEntity.goodsInfo.length === 0) {
ElMessageBox.confirm(
'非空箱入库未绑定物料,默认生成回库任务。\n是否继续',
'警告',
{
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
}
).then(() => {
confirmSend()
}).catch(() => {
ElMessage.info('操作取消')
})
} else {
confirmSend()
}
}
//
const confirmSend = () => {
let request = taskRequestEntity
loading.open()
requireStockIn(request).then(res => {
const response = res.data
if (response.code === 0) {
ElMessage.success(response.message)
cancelBinding()
} else {
errorBox(response.message)
}
}).catch(err => {
console.log(err)
errorBox('请求错误。')
}).finally(() => {
loading.close()
})
}
//
const cancelBinding = () => {
resetTaskEntity()
inTaskEntity.vehicleId = ''
vehicleId.value.focus()
}
//
const removeThisRow = (row) => {
taskRequestEntity.goodsInfo.splice(taskRequestEntity.goodsInfo.indexOf(row), 1)
if (taskRequestEntity.goodsInfo.length === 0 && taskRequestEntity.vehicleId !== '' && !taskRequestEntity.emptyTask) {
//
resetTaskEntity()
}
goodsId.value.focus()
}
//
const resetTaskEntity = () => {
taskRequestEntity.emptyTask = false
taskRequestEntity.vehicleId = ''
taskRequestEntity.goodsInfo = []
}
//
const openOutForInDialog = () => {
//
showInOutDialog.value = true
nextTick(() => {
//
forInGoodsId.value.focus()
})
}
//
const addForInGoods = () => {
outForInEntity.goodsId = outForInEntity.goodsId.trim()
if (outForInEntity.goodsId === '') {
errorBox('请输入料号。')
} else {
outForInEntity.goodsId = outForInEntity.goodsId.toUpperCase()
outForInRequestEntity.goodsIds.push({
goodsId: outForInEntity.goodsId
})
outForInEntity.goodsId = ''
}
//
forInGoodsId.value.focus()
}
const popThisGoodsId = (row) => {
outForInRequestEntity.goodsIds.splice(outForInRequestEntity.goodsIds.indexOf(row), 1)
forInGoodsId.value.focus()
}
//
const confirmCallVehicles = () => {
const goodsIds = outForInRequestEntity.goodsIds.flatMap(item => {
return item.goodsId
})
if (goodsIds.length === 0) {
errorBox('请输入料号。')
return
}
const request = {
goodsIds: goodsIds,
userName: outForInRequestEntity.userName,
standId: outForInRequestEntity.standId
}
loading.open()
requireVehiclesForIn(request).then(res => {
const response = res.data
if (response.code === 0) {
successBox(response.message)
} else {
errorBox(response.message)
}
outForInRequestEntity.goodsIds = []
}).catch(err => {
console.log(err)
errorBox('请求错误。')
}).finally(() => {
loading.close()
})
}
</script>
<style scoped>
.content {
display: flex;
width: 100%;
}
.work-area {
width: 100%;
/* padding: 5px; */
}
.main-area {
min-height: fit-content;
max-height: 90%;
margin: auto auto 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.confirm-area {
min-height: fit-content;
max-height: 90%;
margin: auto auto 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.title-area {
display: flex;
/* min-height: 10%; */
max-height: max-content;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0 15px 10px -15px #000;
overflow: auto;
}
.el-form-item {
margin: 10px 5px 10px 5px;
}
.el-form-item .el-input {
width: 196px;
}
.el-form-item .el-input-number {
width: 185px;
}
.table-class {
margin: 5px 5px 5px 5px;
width: inherit;
}
</style>

View File

@ -0,0 +1,585 @@
<template>
<el-config-provider :locale="zhCn">
<el-container class="content">
<div class="work-area">
<fieldset class="search-area">
<el-form ref="outTaskRef" :model="outTaskEntity" :label-position="labelPosition" label-width="158px"
style="max-width: 100%" :rules="requestRules" status-icon>
<div style="display: flex; justify-content: space-between;">
<el-row>
<!-- <el-form-item label="出库类型" prop="outType">
<el-select-v2 style="width: 196px" v-model="outTaskEntity.outType" placeholder="请选择入库类型"
:options="outTypeOptions"></el-select-v2>
</el-form-item> -->
<el-form-item label="料号" prop="goodsId">
<el-input v-model="outTaskEntity.goodsId" @blur="getLackQty()" clearable/>
</el-form-item>
<el-form-item label="箱号" prop="vehicleId" v-if="outTaskEntity.outType !== 9">
<el-input v-model="outTaskEntity.vehicleId" clearable/>
</el-form-item>
<el-form-item label="数量" prop="needNum">
<el-input-number style="width: 196px" v-model.number="outTaskEntity.needNum"
controls-position="right" :min="1" clearable/>
</el-form-item>
<!-- <el-form-item label="原因" prop="reason" v-if="outTaskEntity.outType === 9">
<el-select-v2 style="width: 196px" v-model="outTaskEntity.reason" placeholder="请选择紧急出库原因"
:options="reasonOptions"></el-select-v2>
</el-form-item> -->
<el-form-item label="工单" prop="workOrder" v-if="outTaskEntity.reason === '缺料'">
<el-input v-model="outTaskEntity.workOrder" @blur="getLackQty()" clearable/>
</el-form-item>
</el-row>
<el-row>
<el-button type="primary"
style="height: 50px; width: 100px; margin: auto 5px auto 5px; font-size: large; color: black;"
@click="confirmOut()">确认出库
</el-button>
<el-button type="warning"
style="height: 50px; width: 100px; margin: auto 5px auto 5px; font-size: large; color: black;"
@click="clearInput()">清除输入
</el-button>
</el-row>
</div>
</el-form>
</fieldset>
<!-- 修改confirm-area为竖直布局表单项两两一排 -->
<!-- 修改confirm-area为竖直布局表单项两两一排 -->
<div style="display: flex; margin-top: 10px;">
<div v-for="(entity, index) in confirmEntities" :key="index" style="width: 32%; margin: 0 10px;">
<fieldset class="confirm-area">
<!-- 在这里添加站台ID显示 -->
<div style="text-align: center; font-size: 18px; font-weight: bold; margin-bottom: 0; color: #333;">
{{ getChildStandIdByIndex(index) }}
</div>
<el-form ref="confirmRef" :model="entity" :label-position="labelPosition" label-width="158px" style="max-width: 100%" :rules="confirmRules" status-icon>
<div style="display: flex; flex-wrap: wrap;">
<div style="width: 50%; display: flex; flex-direction: column;">
<el-form-item label="出库类型" prop="outType">
<el-select-v2 style="width: 196px" v-model="entity.outType" placeholder=" "
:options="outTypeOptions" disabled></el-select-v2>
</el-form-item>
<el-form-item label="特殊库存" prop="totalNeed" class="special-inventory-item">
<el-input v-model="entity.specialStock" disabled/>
</el-form-item>
<el-form-item label="特殊库存号" prop="totalNeed" class="special-inventory-item">
<el-input v-model="entity.specialStockNo" disabled/>
</el-form-item>
<el-form-item label="总需求" prop="totalNeed">
<el-input v-model="entity.totalNeed" disabled/>
</el-form-item>
<el-form-item label="本次计划拣选" prop="planPickQty">
<el-input v-model="entity.planPickQty" disabled/>
</el-form-item>
<el-form-item label="计划剩余数量" prop="planRemainQty">
<el-input v-model="entity.planRemainQty" disabled/>
</el-form-item>
<el-form-item label="箱号" prop="vehicleId">
<el-input v-model="entity.vehicleId" disabled/>
</el-form-item>
</div>
<div style="width: 50%; display: flex; flex-direction: column;">
<el-form-item label="物料号" prop="goodsId" class="special-inventory-item">
<el-input v-model="entity.goodsId" disabled/>
</el-form-item>
<el-form-item label="批次号" prop="remainNeed" class="special-inventory-item">
<el-input v-model="entity.batchNo" disabled/>
</el-form-item>
<el-form-item label="特殊库存item号" prop="remainNeed" class="special-inventory-item">
<el-input v-model="entity.specialStockItemNo" disabled/>
</el-form-item>
<el-form-item label="剩余需求" prop="remainNeed">
<el-input v-model="entity.remainNeed" disabled/>
</el-form-item>
<el-form-item label="本次实际拣选" prop="realPickQty">
<el-input-number style="width: 196px" v-model.number="entity.realPickQty"
controls-position="right" :min="0" clearable @change="() => changePlanQty(index)"/>
</el-form-item>
<el-form-item label="实际剩余数量" prop="realRemainQty">
<el-input-number style="width: 196px" v-model.number="entity.realRemainQty"
controls-position="right" :min="0" clearable/>
</el-form-item>
<el-form-item label="目标箱号" prop="vehicleId">
<el-input v-model="entity.containerNo"/>
</el-form-item>
</div>
<br>
</div>
<div style="display: flex; justify-content: center; gap: 80px; margin-top: 20px;">
<el-button type="success" style="height: 50px; width: 100px; margin: auto 5px auto 5px; font-size: large; color: black;"
@click="confirmOrRelease(index)">确认/放行
</el-button>
<!-- <el-button type="warning" style="height: 50px; width: 100px; margin: auto 5px auto 5px; font-size: large; color: black;"-->
<!-- @click="clearBox(index)">箱子置空-->
<!-- </el-button>-->
</div>
</el-form>
</fieldset>
</div>
</div>
</div>
</el-container>
</el-config-provider>
</template>
<script setup>
import store from '@/store'
import {requireStockOut, getCurrentTask, confirmCurrentTask, getGoodsLackQty} from '@/api/task.js'
import {errorBox, warningBox} from '@/utils/myMessageBox.js'
import {ElMessage} from 'element-plus'
import {nextTick, onBeforeUnmount, onMounted, reactive, ref, watch} from 'vue'
import {loading} from '@/utils/loading'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import {useRoute} from "vue-router";
import {labelPosition} from '@/constant/form'
const STAND_ID = store.getters.getStandId
const USER_NAME = store.getters.getUserName
let timer = ref()
let outTaskRef = ref()
let outTaskEntity = reactive({
outType: 9,
goodsId: '',
vehicleId: '',
reason: '',
workOrder: '',
needNum: null
})
const requestRules = reactive({
outType: [
{required: true, message: '请选择入库类型'}
],
needNum: [
{required: true, message: '请输入数量'},
{type: 'number', message: '请输入数字值'}
],
})
const outTypeOptions = [
{
label: '空箱出库',
value: 1
},
{
label: '紧急出库',
value: 9
}
]
let confirmRef = ref()
let confirmEntities = reactive([
{
taskId: '',
outType: null,
goodsId: '',
totalNeed: null,
remainNeed: null,
planPickQty: null,
realPickQty: null,
stockId: '',
vehicleId: '',
planRemainQty: null,
realRemainQty: null,
isOut: null,
putArea: '',
warningQty: null,
containerNo: '',
specialStock: '',
specialStockNo: '',
batchNo: '',
specialStockItemNo: ''
},
{
taskId: '',
outType: null,
goodsId: '',
totalNeed: null,
remainNeed: null,
planPickQty: null,
realPickQty: null,
stockId: '',
vehicleId: '',
planRemainQty: null,
realRemainQty: null,
isOut: null,
putArea: '',
warningQty: null,
containerNo: '',
specialStock: '',
specialStockNo: '',
batchNo: '',
specialStockItemNo: ''
},
{
taskId: '',
outType: null,
goodsId: '',
totalNeed: null,
remainNeed: null,
planPickQty: null,
realPickQty: null,
stockId: '',
vehicleId: '',
planRemainQty: null,
realRemainQty: null,
isOut: null,
putArea: '',
warningQty: null,
containerNo: '',
specialStock: '',
specialStockNo: '',
batchNo: '',
specialStockItemNo: ''
}
])
const confirmRules = reactive({})
let pauseGetPickFlag = ref(false)
const route = useRoute()//
//
onMounted(() => {
nextTick(() => {
timer.value = setInterval(() => {
timerTask_1()
}, 1000)
})
})
onBeforeUnmount(() => {
clearInterval(timer.value)
})
//
watch(() => route.path, (newVal, oldVal) => {
if (newVal === '/goodsOut') {
timer.value = setInterval(() => {
timerTask_1()
}, 1000)
} else {
clearInterval(timer.value)
}
})
// 1
const timerTask_1 = () => {
getTask()
}
//
const getTask = () => {
if (pauseGetPickFlag.value) {
return
}
const request = {
standId: STAND_ID,
userName: USER_NAME
}
//
getCurrentTask(request).then(res => {
const response = res.data
console.log(response)
if (response.code === 0) {
const confirmVos = response.data
// ID
let childStandOrder = []
if (STAND_ID === 'P1') {
childStandOrder = ['P13', 'P12', 'P11']
} else if (STAND_ID === 'P2') {
childStandOrder = ['P16', 'P15', 'P14']
} else if (STAND_ID === 'P3') {
childStandOrder = ['P19', 'P18', 'P17']
}
//
confirmEntities.forEach(entity => {
clearEntityData(entity)
})
//
childStandOrder.forEach((standId, index) => {
const found = confirmVos.find(item => item.childStandId === standId)
console.log("found=" + found)
//
if (!found || index >= 3) { // 3
return // continue
}
// taskConfirmstockConfirm
if (!found.taskConfirm || !found.stockConfirm) {
return // taskConfirmstockConfirmnull
}
const entity = confirmEntities[index]
entity.taskId = found.taskConfirm.taskId || ''
entity.outType = found.taskConfirm.outType
entity.goodsId = found.taskConfirm.goodsId || ''
entity.totalNeed = found.taskConfirm.totalNeed
entity.remainNeed = found.taskConfirm.remainNeed
entity.planPickQty = found.taskConfirm.planPickQty
entity.realPickQty = found.taskConfirm.realPickQty
entity.stockId = found.stockConfirm.stockId || ''
entity.vehicleId = found.stockConfirm.vehicleId || ''
entity.planRemainQty = found.stockConfirm.planRemainQty
entity.realRemainQty = found.stockConfirm.realRemainQty
entity.isOut = found.stockConfirm.isOut
entity.putArea = found.stockConfirm.putArea || ''
entity.warningQty = found.stockConfirm.warningQty
entity.specialStock = found.stockConfirm.specialStock || ''
entity.specialStockNo = found.stockConfirm.specialStockNo || ''
entity.batchNo = found.stockConfirm.batchNo || ''
entity.specialStockItemNo = found.stockConfirm.specialStockItemNo || ''
//
if (entity.isOut === 0 && entity.planRemainQty <= entity.warningQty) {
warningBox(`请注意!${found.childStandId}站台,剩余数量小于预警值,请检查并核对数量。`)
}
})
pauseGetPickFlag.value = true
} else if (response.code === 400) {
//
pauseGetPickFlag.value = true
warningBox(response.message)
}
}).catch(err => {
console.log(err)
pauseGetPickFlag.value = true
errorBox('请求错误,请检查完原因后刷新界面。')
})
}
//
const clearEntityData = (entity) => {
entity.taskId = ''
entity.outType = null
entity.goodsId = ''
entity.totalNeed = null
entity.remainNeed = null
entity.planPickQty = null
entity.realPickQty = null
entity.stockId = ''
entity.vehicleId = ''
entity.planRemainQty = null
entity.realRemainQty = null
entity.isOut = null
entity.putArea = ''
entity.warningQty = null
entity.containerNo = ''
}
//
const clearInput = () => {
outTaskEntity.outType = 9
outTaskEntity.goodsId = ''
outTaskEntity.vehicleId = ''
outTaskEntity.needNum = null
}
//
//
const confirmOut = () => {
if (outTaskEntity.needNum == null) {
errorBox('请输入正确的数量。')
return
}
if (outTaskEntity.goodsId === '') {
errorBox('请输入料号。')
return
}
const request = {
// outType: outTaskEntity.outType,
goodsId: outTaskEntity.goodsId ? outTaskEntity.goodsId.toUpperCase().trim() : '',
// vehicleId: outTaskEntity.vehicleId ? outTaskEntity.vehicleId.toUpperCase().trim() : '',
needNum: outTaskEntity.needNum,
// reason: outTaskEntity.reason,
workOrder: outTaskEntity.workOrder ? outTaskEntity.workOrder.trim() : '',
destination: STAND_ID,
userName: USER_NAME,
standId: STAND_ID
}
loading.open('处理中...')
requireStockOut(request).then(res => {
const response = res.data
if (response.code === 0) {
//
ElMessage.success(response.message)
clearInput()
} else {
errorBox(response.message)
}
}).catch(err => {
console.log(err)
errorBox('请求错误。')
}).finally(() => {
loading.close()
})
}
// /
// confirmOrRelease
const confirmOrRelease = (index) => {
const entity = confirmEntities[index]
if (entity.containerNo === ""){
warningBox('目标箱号必填!')
return
}
// ---
const request = {
taskConfirm: {
taskId: entity.taskId,
outType: entity.outType,
goodsId: entity.goodsId,
totalNeed: entity.totalNeed,
remainNeed: entity.remainNeed,
planPickQty: entity.planPickQty,
realPickQty: entity.realPickQty,
containerNo: entity.containerNo,
},
stockConfirm: {
stockId: entity.stockId,
vehicleId: entity.vehicleId,
goodsId: entity.goodsId,
planRemainQty: entity.planRemainQty,
realRemainQty: entity.realRemainQty,
isOut: entity.isOut,
putArea: entity.putArea,
},
standId: getChildStandIdByIndex(index),
userName: USER_NAME
}
loading.open('确认中...')
confirmCurrentTask(request, { timeout: 5000 }).then(res => {
const response = res.data
if (response.code === 0) {
clearConfirmEntity(index) //
//
pauseGetPickFlag.value = false
ElMessage.success(response.message)
} else if (response.code === 400) {
pauseGetPickFlag.value = false
warningBox(response.message)
} else {
//
errorBox(response.message)
}
}).catch(err => {
console.log(err)
errorBox('请求错误,请检查完原因后刷新界面。')
}).finally(() => {
loading.close()
})
}
// clearConfirmEntity
const clearConfirmEntity = (index) => {
if (index >= 0 && index < confirmEntities.length) {
clearEntityData(confirmEntities[index]); // 使 clearEntityData
}
}
//
// changePlanQty
const changePlanQty = (index) => {
const entity = confirmEntities[index]
if (entity.isOut === 0 && entity.realPickQty !== entity.planPickQty) {
//
entity.realRemainQty = entity.planRemainQty - entity.realPickQty + entity.planPickQty
}
}
//
const getLackQty = () => {
if (outTaskEntity.outType !== 9 || outTaskEntity.reason !== '缺料') {
//
return;
}
if (outTaskEntity.workOrder === '' || outTaskEntity.goodsId === '') {
//
return
}
//
const request = {
workOrder: outTaskEntity.workOrder ? outTaskEntity.workOrder.trim() : '',
goodsId: outTaskEntity.goodsId ? outTaskEntity.goodsId.toUpperCase().trim() : ''
}
loading.open('查询缺料缺料数量中...')
getGoodsLackQty(request).then(res => {
outTaskEntity.needNum = res.data
}).catch(err => {
//
outTaskEntity.needNum = null
console.log('获取缺料数量异常:' + err)
}).finally(() => {
loading.close()
})
}
// ID
const getChildStandIdByIndex = (index) => {
// ID
let childStandOrder = []
if (STAND_ID === 'P1') {
childStandOrder = ['P13', 'P12', 'P11']
} else if (STAND_ID === 'P2') {
childStandOrder = ['P16', 'P15', 'P14']
} else if (STAND_ID === 'P3') {
childStandOrder = ['P19', 'P18', 'P17']
}
return childStandOrder[index] || ''
}
//
const clearBox = (index) => {
//
clearConfirmEntity(index)
}
</script>
<style scoped>
.content {
display: flex;
width: 100%;
}
.work-area {
width: 100%;
/* padding: 5px; */
}
.special-inventory-item :deep(.el-form-item__label) {
color: #ff8888;
font-weight: bold;
}
.search-area {
margin: auto;
min-height: fit-content;
max-height: 90%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.confirm-area {
margin: auto;
min-height: fit-content;
max-height: 100%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.el-form-item {
margin: 10px 5px 10px 5px;
}
.el-form-item .el-input {
width: 196px;
}
.table-class {
margin: 5px 5px 5px 5px;
width: inherit;
}
</style>

View File

@ -0,0 +1,90 @@
<template>
<!-- 图纸展示 -->
<div class="content">
<el-image class="image-full" :src="imageData.base64" :fit="fit">
<template #error>
<div class="error-slot">
{{ imageData.errMsg }}
</div>
</template>
</el-image>
</div>
</template>
<script setup>
//
import store from '@/store'
import { getImageOfWork } from '@/api/kateWork.js'
import { onBeforeUnmount, onMounted, reactive, ref } from 'vue';
//
let timer = ref()
const standId = store.getters.getStandId
const userName = store.getters.getUserName
const fit = 'contain'
let imageData = reactive({
url: '',
base64: '',
name: '',
errMsg: ''
})
//
onMounted(() => {
// findImage()
timer.value = setInterval(() => {
findImage()
}, 1000)
})
onBeforeUnmount(() => {
clearInterval(timer.value)
})
//
//
const findImage = () => {
const request = {
standId: standId,
userName: userName
}
getImageOfWork(request).then(res => {
const response = res.data
if (response.code === 0) {
const image = response.data
openPreview(image)
} else {
closePreview(response.message)
}
}).catch(err => {
console.log(err)
closePreview("发生异常,请刷新界面并重试。")
})
}
//
const openPreview = (image) => {
imageData.url = image.imageIp + image.imagePath + image.imageName
imageData.base64 = 'data:image/png;base64,' + image.imageDetail
imageData.name = image.imageName
imageData.errMsg = ''
}
//
const closePreview = (errMsg) => {
imageData.url = ''
imageData.base64 = ''
imageData.name = ''
imageData.errMsg = errMsg
}
</script>
<style scoped>
.content {
width: 100%;
height: 100%;
}
.image-full {
width: 100%;
height: 100%;
}
.image-full .error-slot {
color: red;
font-size: 50px;
font-weight: bold;
}
</style>

View File

@ -0,0 +1,314 @@
<template>
<el-config-provider :locale="zhCn">
<el-container class="content">
<div class="work-area">
<fieldset class="search-area">
<el-form ref="searchQueryFormRef" :model="searchQueryFormEntity" :label-position="labelPosition"
label-width="158px" style="max-width: 100%" status-icon>
<div style="display: flex;justify-content: space-between;">
<el-row>
<el-form-item label="箱号">
<el-input v-model="searchQueryFormEntity.vehicleId" @keyup.enter="search()" clearable/>
</el-form-item>
<el-form-item label="料号">
<el-input v-model="searchQueryFormEntity.goodsId" @keyup.enter="search()" clearable/>
</el-form-item>
<el-form-item label="创建时间from">
<el-date-picker v-model="searchQueryFormEntity.fromTime" type="datetime"
placeholder="请选择from时间" :shortcuts="shortcuts"
style="width: 196px;" clearable/>
</el-form-item>
<el-form-item label="创建时间to">
<el-date-picker v-model="searchQueryFormEntity.toTime" type="datetime"
placeholder="请选择to时间" :shortcuts="shortcuts"
style="width: 196px;" clearable/>
</el-form-item>
</el-row>
<div style="align-content: center;">
<el-row>
<el-button type="primary" class="btn-search" @click="search()">查询</el-button>
<el-button type="warning" class="btn-search" @click="clearQuery()">清除输入</el-button>
</el-row>
<el-row>
<el-button type="success" class="btn-search"
@click="exportExcel()">导出excel
</el-button>
</el-row>
</div>
</div>
</el-form>
</fieldset>
<div class="table-area">
<el-table :data="tableData" stripe border v-loading="tableLoading" class="table-class"
:max-height="maxHeight" highlight-current-row @row-click="getCurrentRow"
:header-cell-style="{ 'text-align': 'center' }" :cell-style="{ 'text-align': 'center' }"
@sort-change="handleSortChange">
<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="taskId" label="任务号" fixed="left" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="taskType" label="任务类型" :formatter="taskTypeFormat" min-width="120px"
sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="taskStatus" label="任务状态" :formatter="taskStatusFormat" min-width="120px"
sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="taskPriority" label="优先级" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="vehicleId" label="箱号" fixed="left" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="goodsId" label="料号" min-width="120px" fixed="left" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="goodsDesc" label="物料描述"
min-width="120px" sortable="custom" show-overflow-tooltip/>
<el-table-column prop="opNum" label="操作数量" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="stockNum" label="库存数量" min-width="120px"
sortable="custom" show-overflow-tooltip/>
<el-table-column prop="origin" label="起点" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="destination" label="终点" min-width="120px"
sortable="custom" show-overflow-tooltip/>
<el-table-column prop="wcsTaskId" label="wcs任务号" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="createTime" label="创建时间" :formatter="timeFormat" fixed="right" min-width="120px"
sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="finishTime" label="完成时间" :formatter="timeFormat" fixed="right" min-width="120px"
sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="opUser" label="操作用户" min-width="120px"
sortable="custom" show-overflow-tooltip/>
<el-table-column prop="remark" label="备注" min-width="120px"
sortable="custom" show-overflow-tooltip/>
<el-table-column prop="callStand" label="呼叫站台" min-width="120px"
sortable="custom" show-overflow-tooltip/>
</el-table>
<br/>
<el-pagination v-model:current-page="baseTableQuery.currentPage"
v-model:page-size="baseTableQuery.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="baseTableQuery.total"/>
</div>
</div>
</el-container>
</el-config-provider>
</template>
<script setup>
import store from '@/store'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import {queryInTaskRecordByPage} from '@/api/taskQuery.js'
import {timeFormatter, wmsTaskTypeFormatter, wmsTaskStatusFormatter, dateFormatter} from '@/utils/formatter.js'
import {ref, reactive, onMounted, nextTick, onBeforeUnmount} from 'vue'
import {ElMessage} from 'element-plus'
import {genTableRequest} from '@/utils/generator.js'
import {labelPosition, shortcuts} from '@/constant/form.js'
import {exportInTaskRecordExcel} from '@/api/excel.js'
/**
* 常量定义
*/
const STAND_ID = store.getters.getStandId
const USER_NAME = store.getters.getUserName
/**
* 变量定义
*/
let maxHeight = ref(window.innerHeight * 0.55)
let tableLoading = ref(false)
let tableData = ref([])
let baseTableQuery = reactive({
currentPage: 1,
pageSize: 10,
total: 0,
sortBy: new Map([['createTime', false]]),//
standId: STAND_ID,
userName: USER_NAME
})
let searchQueryFormEntity = reactive({
vehicleId: '',
goodsId: '',
fromTime: null,
toTime: null
})
let searchQueryFormRef = ref()
let taskId = ''
/**
* 系统方法
*/
onMounted(() => {
nextTick(() => {
window.addEventListener('resize', resizeHeight)
search()
})
})
onBeforeUnmount(() => {
nextTick(() => {
window.removeEventListener('resize', resizeHeight)
})
})
const resizeHeight = () => {
maxHeight.value = window.innerHeight * 0.55
}
/**
* 自定义方法
*/
//
const search = () => {
tableLoading.value = true
let request = genTableRequest(baseTableQuery)
//
request.vehicleId = searchQueryFormEntity.vehicleId.trim()
request.goodsId = searchQueryFormEntity.goodsId.trim()
request.fromTime = searchQueryFormEntity.fromTime == null ? null : timeFormatter(searchQueryFormEntity.fromTime)
request.toTime = searchQueryFormEntity.toTime == null ? null : timeFormatter(searchQueryFormEntity.toTime)
queryInTaskRecordByPage(request).then((res) => {
const response = res.data
if (response.code === 0) {
const data = response.data
if (data != null) {
tableData.value = data.lists
baseTableQuery.total = data.total
} else {
tableData.value = []
baseTableQuery.total = 0
}
} else {
ElMessage.error(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('查询数据异常。')
}).finally(() => {
tableLoading.value = false
})
}
const clearQuery = () => {
searchQueryFormEntity.vehicleId = ''
searchQueryFormEntity.goodsId = ''
searchQueryFormEntity.fromTime = null
searchQueryFormEntity.toTime = null
}
const handleSortChange = (data) => {
if (baseTableQuery.sortBy.has(data.prop)) {
baseTableQuery.sortBy.delete(data.prop)
}
baseTableQuery.sortBy.set(data.prop, data.order == 'ascending')
search()
}
const getCurrentRow = (row) => {
taskId = row.taskId
}
const timeFormat = (row, column, cellValue, index) => {
return timeFormatter(cellValue)
}
const taskTypeFormat = (row, column, cellValue, index) => {
return wmsTaskTypeFormatter(cellValue)
}
const taskStatusFormat = (row, column, cellValue, index) => {
return wmsTaskStatusFormatter(cellValue)
}
const exportExcel = () => {
const params = {
goodsId: searchQueryFormEntity.goodsId,
vehicleId: searchQueryFormEntity.vehicleId,
fromTime: searchQueryFormEntity.fromTime == null ? null : timeFormatter(searchQueryFormEntity.fromTime),
toTime: searchQueryFormEntity.toTime == null ? null : timeFormatter(searchQueryFormEntity.toTime),
userName: USER_NAME
}
exportInTaskRecordExcel(params).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) {
console.log(e)
ElMessage.error('下载文件失败')
}
}).catch(err => {
console.log(err)
ElMessage.error('导出失败')
})
}
</script>
<style scoped>
.content {
display: flex;
width: 100%;
}
.work-area {
width: 100%;
/* padding: 5px; */
}
.search-area {
margin: auto;
min-height: fit-content;
max-height: 40%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.table-area {
margin: auto;
min-height: fit-content;
max-height: 60%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.el-form-item {
margin: 5px 5px 5px 5px;
}
.el-form-item .el-input {
width: 196px;
}
.el-form-item .el-input-number {
width: 196px;
}
.table-class {
margin: 5px 5px 5px 5px;
width: inherit;
}
.el-pagination {
padding-left: 5px;
}
.btn-search {
height: 30px;
width: 80px;
margin: auto 5px 5px auto;
color: black;
}
</style>

View File

@ -0,0 +1,437 @@
<template>
<el-config-provider :locale="zhCn">
<el-container class="content">
<div class="work-area">
<fieldset class="search-area">
<el-form ref="inventoryRequestFormRef" :model="inventoryRequestFormEntity" :label-position="labelPosition"
label-width="158px"
style="max-width: 100%" :rules="requestRules" status-icon>
<div style="display: flex; justify-content: space-between;">
<el-row>
<el-form-item label="箱号" prop="vehicleId">
<el-input v-model="inventoryRequestFormEntity.vehicleId" ref="vehicleId" clearable/>
</el-form-item>
<el-form-item label="料号" prop="goodsId">
<el-input v-model="inventoryRequestFormEntity.goodsId" ref="goodsId" clearable/>
</el-form-item>
<el-form-item label="特殊库存" prop="specialStock">
<el-input v-model="inventoryRequestFormEntity.specialStock" ref="specialStock" clearable/>
</el-form-item>
<el-form-item label="特殊库存号" prop="specialStockNo">
<el-input v-model="inventoryRequestFormEntity.specialStockNo" ref="specialStockNo" clearable/>
</el-form-item>
<el-form-item label="特殊库存item号" prop="specialStockItemNo">
<el-input v-model="inventoryRequestFormEntity.specialStockItemNo" ref="specialStockItemNo" clearable/>
</el-form-item>
<el-form-item label="批次号" prop="batchNo">
<el-input v-model="inventoryRequestFormEntity.batchNo" ref="batchNo" clearable/>
</el-form-item>
</el-row>
<el-row>
<el-button type="primary"
style="height: 50px; width: 100px; margin: auto 5px auto 5px; font-size: large; color: black;"
@click="sendInventoryRequest()">下发盘点
</el-button>
<el-button type="warning"
style="height: 50px; width: 100px; margin: auto 5px auto 5px; font-size: large; color: black;"
@click="clearInput()">清除输入
</el-button>
</el-row>
</div>
</el-form>
</fieldset>
<!-- 参考goodsOut.vue改为三个并排框 -->
<div style="display: flex; margin-top: 10px;">
<div v-for="(entity, index) in confirmEntities" :key="index" style="width: 32%; margin: 0 10px;">
<fieldset class="confirm-area">
<div style="text-align: center; font-size: 18px; font-weight: bold; margin-bottom: 0; color: #333;">
{{ getChildStandIdByIndex(index) }}
</div>
<el-form ref="confirmRef" :model="entity" :label-position="labelPosition" label-width="158px"
style="max-width: 100%" :rules="confirmRules" status-icon>
<div style="display: flex; flex-wrap: wrap;">
<div style="width: 50%; display: flex; flex-direction: column;">
<el-form-item label="盘点任务号" prop="inventoryId">
<el-input v-model="entity.inventoryId" disabled/>
</el-form-item>
<el-form-item label="特殊库存" prop="specialStock" class="special-inventory-item">
<el-input v-model="entity.specialStock" disabled/>
</el-form-item>
<el-form-item label="特殊库存号" prop="specialStockNo" class="special-inventory-item">
<el-input v-model="entity.specialStockNo" disabled/>
</el-form-item>
<el-form-item label="系统数量" prop="stockNum">
<el-input v-model="entity.stockNum" disabled/>
</el-form-item>
<el-form-item label="箱号" prop="vehicleId">
<el-input v-model="entity.vehicleId" disabled/>
</el-form-item>
</div>
<div style="width: 50%; display: flex; flex-direction: column;">
<el-form-item label="物料号" prop="goodsId" class="special-inventory-item">
<el-input v-model="entity.goodsId" disabled/>
</el-form-item>
<el-form-item label="特殊库存item号" prop="specialStockItemNo" class="special-inventory-item">
<el-input v-model="entity.specialStockItemNo" disabled/>
</el-form-item>
<el-form-item label="批次号" prop="batchNo" class="special-inventory-item">
<el-input v-model="entity.batchNo" disabled/>
</el-form-item>
<el-form-item label="确认数量" prop="confirmNum">
<el-input-number style="width: 196px" v-model.number="entity.confirmNum"
controls-position="right" :min="0" clearable/>
</el-form-item>
</div>
</div>
<div style="display: flex; justify-content: center; gap: 80px; margin-top: 20px;">
<el-button type="success"
style="height: 50px; width: 100px; margin: auto 5px auto 5px; font-size: large; color: black;"
@click="confirmOrRelease(index)">确认/放行
</el-button>
</div>
</el-form>
</fieldset>
</div>
</div>
<el-dialog v-model="showUploadDialog" title="上传盘点清单" width="40%" draggable :show-close="true">
<fieldset class="search-area">
<legend>上传盘点清单</legend>
<UploadExcelInventory></UploadExcelInventory>
</fieldset>
</el-dialog>
</div>
</el-container>
</el-config-provider>
</template>
<script setup>
import store from '@/store'
import {nextTick, onBeforeUnmount, onMounted, reactive, ref, watch} from 'vue'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import {useRoute} from "vue-router";
import {errorBox, warningBox} from "@/utils/myMessageBox";
import {ElMessage} from "element-plus";
import {confirmInventory, getInventoryConfirm, requestInventory} from "@/api/task";
import {labelPosition} from "@/constant/form";
import UploadExcelInventory from "@/excel/UploadExcelInventory.vue";
import {loading} from "@/utils/loading";
const STAND_ID = store.getters.getStandId
const USER_NAME = store.getters.getUserName
let timer = ref()
const route = useRoute()//
let inventoryRequestFormRef = ref()
let inventoryRequestFormEntity = reactive({
goodsId: '',
vehicleId: '',
specialStock: '',
specialStockNo: '',
specialStockItemNo: '',
batchNo: ''
})
const requestRules = reactive({})
let confirmRef = ref()
//
let confirmEntities = reactive([
{
inventoryId: '',
vehicleId: '',
goodsId: '',
stockNum: null,
confirmNum: null,
specialStock: '',
specialStockNo: '',
specialStockItemNo: '',
batchNo: ''
},
{
inventoryId: '',
vehicleId: '',
goodsId: '',
stockNum: null,
confirmNum: null,
specialStock: '',
specialStockNo: '',
specialStockItemNo: '',
batchNo: ''
},
{
inventoryId: '',
vehicleId: '',
goodsId: '',
stockNum: null,
confirmNum: null,
specialStock: '',
specialStockNo: '',
specialStockItemNo: '',
batchNo: ''
}
])
const confirmRules = reactive({})
let pauseGetPickFlag = ref(false)
let showUploadDialog = ref(false)
//
onMounted(() => {
nextTick(() => {
timer.value = setInterval(() => {
timerTask_1()
}, 1000)
})
})
onBeforeUnmount(() => {
clearInterval(timer.value)
})
//
watch(() => route.path, (newVal, oldVal) => {
if (newVal === '/inventory') {
timer.value = setInterval(() => {
timerTask_1()
}, 1000)
} else {
clearInterval(timer.value)
}
})
// 1
const timerTask_1 = () => {
//
getInventory()
}
//
const getInventory = () => {
if (pauseGetPickFlag.value) {
return
}
// ID
let childStandOrder = []
if (STAND_ID === 'P1') {
childStandOrder = ['P13', 'P12', 'P11']
} else if (STAND_ID === 'P2') {
childStandOrder = ['P16', 'P15', 'P14']
} else if (STAND_ID === 'P3') {
childStandOrder = ['P19', 'P18', 'P17']
}
//
const promises = childStandOrder.map(STAND_ID => {
const request = {
standId: STAND_ID,
userName: USER_NAME
}
return getInventoryConfirm(request)
})
Promise.all(promises).then(responses => {
responses.forEach((res, index) => {
const response = res.data
if (response.code === 0) {
const confirmVo = response.data
// form
const entity = confirmEntities[index]
entity.inventoryId = confirmVo.inventoryId
entity.goodsId = confirmVo.goodsId
entity.vehicleId = confirmVo.vehicleId
entity.stockNum = confirmVo.stockNum
entity.confirmNum = confirmVo.confirmNum
entity.specialStock = confirmVo.specialStock || ''
entity.specialStockNo = confirmVo.specialStockNo || ''
entity.specialStockItemNo = confirmVo.specialStockItemNo || ''
entity.batchNo = confirmVo.batchNo || ''
} else if (response.code === 400) {
//
clearConfirmEntity(index)
warningBox(response.message)
}
})
pauseGetPickFlag.value = true
}).catch(err => {
console.log(err)
pauseGetPickFlag.value = true
errorBox('请求错误,请检查完原因后刷新界面。')
})
}
// ID
const getChildStandIdByIndex = (index) => {
// ID
let childStandOrder = []
if (STAND_ID === 'P1') {
childStandOrder = ['P13', 'P12', 'P11']
} else if (STAND_ID === 'P2') {
childStandOrder = ['P16', 'P15', 'P14']
} else if (STAND_ID === 'P3') {
childStandOrder = ['P19', 'P18', 'P17']
}
return childStandOrder[index] || ''
}
//
const clearConfirmEntity = (index) => {
if (index >= 0 && index < confirmEntities.length) {
const entity = confirmEntities[index]
entity.inventoryId = ''
entity.goodsId = ''
entity.vehicleId = ''
entity.stockNum = null
entity.confirmNum = null
entity.specialStock = ''
entity.specialStockNo = ''
entity.specialStockItemNo = ''
entity.batchNo = ''
}
}
//
const sendInventoryRequest = () => {
inventoryRequestFormEntity.goodsId = inventoryRequestFormEntity.goodsId.trim().toUpperCase()
inventoryRequestFormEntity.vehicleId = inventoryRequestFormEntity.vehicleId.trim().toUpperCase()
inventoryRequestFormEntity.specialStock = inventoryRequestFormEntity.specialStock.trim().toUpperCase()
inventoryRequestFormEntity.specialStockNo = inventoryRequestFormEntity.specialStockNo.trim().toUpperCase()
inventoryRequestFormEntity.specialStockItemNo = inventoryRequestFormEntity.specialStockItemNo.trim().toUpperCase()
inventoryRequestFormEntity.batchNo = inventoryRequestFormEntity.batchNo.trim().toUpperCase()
if (inventoryRequestFormEntity.goodsId === '') {
ElMessage.error("料号为必须项。")
return
}
const request = {
goodsId: inventoryRequestFormEntity.goodsId,
vehicleId: inventoryRequestFormEntity.vehicleId,
specialStock: inventoryRequestFormEntity.specialStock,
specialStockNo: inventoryRequestFormEntity.specialStockNo,
specialStockItemNo: inventoryRequestFormEntity.specialStockItemNo,
batchNo: inventoryRequestFormEntity.batchNo,
standId: STAND_ID,
userName: USER_NAME
}
loading.open('处理中...')
requestInventory(request).then(res => {
const response = res.data
if (response.code === 0) {
ElMessage.success(response.message)
pauseGetPickFlag.value = false
} else {
errorBox(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error("发生异常。")
}).finally(() => {
loading.close()
})
}
// / ()
const confirmOrRelease = (index) => {
const entity = confirmEntities[index]
// ---
const request = {
inventoryId: entity.inventoryId,
goodsId: entity.goodsId,
vehicleId: entity.vehicleId,
confirmNum: entity.confirmNum,
standId: getChildStandIdByIndex(index),
userName: USER_NAME
}
loading.open('处理中...')
confirmInventory(request).then(res => {
const response = res.data
if (response.code === 0) {
// form
clearConfirmEntity(index)
ElMessage.success(response.message)
pauseGetPickFlag.value = false
} else if (response.code === 400) {
// form
clearConfirmEntity(index)
warningBox(response.message)
pauseGetPickFlag.value = false
} else {
//
errorBox(response.message)
}
}).catch(err => {
console.log(err)
errorBox('请求错误,请检查完原因后刷新界面。')
}).finally(() => {
loading.close()
})
}
//
const clearInput = () => {
inventoryRequestFormEntity.goodsId = ''
inventoryRequestFormEntity.vehicleId = ''
inventoryRequestFormEntity.specialStock = ''
inventoryRequestFormEntity.specialStockNo = ''
inventoryRequestFormEntity.specialStockItemNo = ''
inventoryRequestFormEntity.batchNo = ''
}
//
const openUploadDialog = () => {
showUploadDialog.value = true
}
</script>
<style scoped>
.content {
display: flex;
width: 100%;
}
.work-area {
width: 100%;
}
.search-area {
margin: auto;
min-height: fit-content;
max-height: 90%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.confirm-area {
margin: auto;
min-height: fit-content;
max-height: 100%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.el-form-item {
margin: 10px 5px 10px 5px;
}
.el-form-item .el-input {
width: 196px;
}
.table-class {
margin: 5px 5px 5px 5px;
width: inherit;
}
/* 特殊库存字段标红醒目显示 */
.special-inventory-item :deep(.el-form-item__label) {
color: #ff8888;
font-weight: bold;
}
</style>

View File

@ -0,0 +1,337 @@
<template>
<el-config-provider :locale="zhCn">
<el-container class="content">
<div class="work-area">
<fieldset class="search-area">
<el-form ref="searchQueryFormRef" :model="searchQueryFormEntity" :label-position="labelPosition"
label-width="158px" style="max-width: 100%" status-icon>
<div style="display: flex;justify-content: space-between;">
<el-row>
<el-form-item label="查询类型">
<el-select-v2 style="width: 196px" v-model="searchQueryFormEntity.queryType" placeholder="查询类型"
:options="queryTypeOptions"
@change="search()"></el-select-v2>
</el-form-item>
<el-form-item label="盘点结果">
<el-select-v2 style="width: 196px" v-model="searchQueryFormEntity.invResult" placeholder="盘点结果"
:options="addAllOptionOfOptions(invResultOptions, DEFAULT_TOTAL_OPTIONS)"
@change="search()"></el-select-v2>
</el-form-item>
<el-form-item label="箱号">
<el-input v-model="searchQueryFormEntity.vehicleId" @keyup.enter="search()" clearable/>
</el-form-item>
<el-form-item label="料号">
<el-input v-model="searchQueryFormEntity.goodsId" @keyup.enter="search()" clearable/>
</el-form-item>
</el-row>
<div style="align-content: center;">
<el-row>
<el-button type="primary" class="btn-search" @click="search()">查询</el-button>
<el-button type="warning" class="btn-search" @click="clearQuery()">清除输入</el-button>
</el-row>
</div>
</div>
</el-form>
</fieldset>
<div class="table-area">
<el-table :data="tableData" stripe border v-loading="tableLoading" class="table-class"
:max-height="maxHeight" highlight-current-row @row-click="getCurrentRow"
:header-cell-style="{ 'text-align': 'center' }" :cell-style="{ 'text-align': 'center' }"
@sort-change="handleSortChange">
<el-table-column width="65px" fixed="left">
<template v-slot="scope">
<el-radio :label="scope.row.inventoryId" v-model="inventoryId">&nbsp;</el-radio>
</template>
</el-table-column>
<el-table-column prop="inventoryId" label="任务号" fixed="left" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="goodsId" label="料号" min-width="120px"
sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="vehicleId" label="箱号" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="stockNum" label="库存数量" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="confirmNum" label="确认数量"
min-width="120px" sortable="custom" show-overflow-tooltip/>
<el-table-column prop="invStand" label="盘点站台" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="invUser" label="盘点人" min-width="120px"
sortable="custom" show-overflow-tooltip/>
<el-table-column prop="invType" label="盘点类型" :formatter="invTypeFormat" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="invStatus" label="任务状态" :formatter="invStatusFormat" min-width="120px"
sortable="custom" show-overflow-tooltip/>
<el-table-column prop="invResult" label="盘点结果" :formatter="invResultFormat" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="invCreateTime" label="创建时间" :formatter="timeFormat" min-width="120px"
sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="invConfirmTime" label="确认时间" :formatter="timeFormat" min-width="120px"
sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="invOrderId" label="任务组" min-width="120px"
sortable="custom"
show-overflow-tooltip/>
</el-table>
<br/>
<el-pagination v-model:current-page="baseTableQuery.currentPage"
v-model:page-size="baseTableQuery.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="baseTableQuery.total"/>
</div>
</div>
</el-container>
</el-config-provider>
</template>
<script setup>
import store from '@/store'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import {queryInventoryRecordByPage} from '@/api/taskQuery.js'
import {timeFormatter} from '@/utils/formatter.js'
import {ref, reactive, onMounted, nextTick, onBeforeUnmount} from 'vue'
import {ElMessage} from 'element-plus'
import {genTableRequest} from '@/utils/generator.js'
import {labelPosition} from '@/constant/form.js'
import {invResultOptions} from '@/constant/options.js'
import {addAllOptionOfOptions} from '@/utils/generator.js'
/**
* 常量定义
*/
const STAND_ID = store.getters.getStandId
const USER_NAME = store.getters.getUserName
const DEFAULT_TOTAL_OPTIONS = 99
/**
* 变量定义
*/
let maxHeight = ref(window.innerHeight * 0.55)
let tableLoading = ref(false)
let tableData = ref([])
let baseTableQuery = reactive({
currentPage: 1,
pageSize: 10,
total: 0,
sortBy: new Map([['invCreateTime', true]]),//
standId: STAND_ID,
userName: USER_NAME
})
let searchQueryFormEntity = reactive({
vehicleId: '',
goodsId: '',
invResult: DEFAULT_TOTAL_OPTIONS,
queryType: 1
})
let searchQueryFormRef = ref()
let inventoryId = ''
const queryTypeOptions = [
{
label: '未关闭',
value: 1
},
{
label: '已关闭',
value: 2
}
]
/**
* 系统方法
*/
onMounted(() => {
nextTick(() => {
window.addEventListener('resize', resizeHeight)
search()
})
})
onBeforeUnmount(() => {
nextTick(() => {
window.removeEventListener('resize', resizeHeight)
})
})
const resizeHeight = () => {
maxHeight.value = window.innerHeight * 0.55
}
/**
* 自定义方法
*/
//
const search = () => {
tableLoading.value = true
let request = genTableRequest(baseTableQuery)
//
request.vehicleId = searchQueryFormEntity.vehicleId.trim()
request.goodsId = searchQueryFormEntity.goodsId.trim()
request.invResult = searchQueryFormEntity.invResult === DEFAULT_TOTAL_OPTIONS ? null : searchQueryFormEntity.invResult
request.queryType = searchQueryFormEntity.queryType//
queryInventoryRecordByPage(request).then((res) => {
const response = res.data
if (response.code === 0) {
const data = response.data
if (data != null) {
tableData.value = data.lists
baseTableQuery.total = data.total
} else {
tableData.value = []
baseTableQuery.total = 0
}
} else {
ElMessage.error(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('查询数据异常。')
}).finally(() => {
tableLoading.value = false
})
}
const clearQuery = () => {
searchQueryFormEntity.vehicleId = ''
searchQueryFormEntity.goodsId = ''
}
const handleSortChange = (data) => {
if (baseTableQuery.sortBy.has(data.prop)) {
baseTableQuery.sortBy.delete(data.prop)
}
baseTableQuery.sortBy.set(data.prop, data.order.toLowerCase() === 'ascending')
search()
}
const getCurrentRow = (row) => {
inventoryId = row.inventoryId
}
const timeFormat = (row, column, cellValue, index) => {
return timeFormatter(cellValue)
}
// format
const invStatusFormat = (row, column, cellValue, index) => {
switch (cellValue) {
case 0:
return '初始化'
case 1:
return '已解析'
case 2:
return '已确认'
default:
return '未知状态'
}
}
// format
const invTypeFormat = (row, column, cellValue, index) => {
if (cellValue === 1) {
return '明盘'
} else if (cellValue === 2) {
return '盲盘'
} else {
return '未知类型'
}
}
// format
const invResultFormat = (row, column, cellValue, index) => {
switch (cellValue) {
case -99:
return '未盘'
case -1:
return '盘亏'
case 0:
return '正常'
case 1:
return '盘盈'
default:
return '未知结果'
}
}
</script>
<style scoped>
.content {
display: flex;
width: 100%;
}
.work-area {
width: 100%;
/* padding: 5px; */
}
.search-area {
margin: auto;
min-height: fit-content;
max-height: 40%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.table-area {
margin: auto;
min-height: fit-content;
max-height: 60%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.el-form-item {
margin: 5px 5px 5px 5px;
}
.el-form-item .el-input {
width: 196px;
}
.el-form-item .el-input-number {
width: 196px;
}
.table-class {
margin: 5px 5px 5px 5px;
width: inherit;
}
.el-pagination {
padding-left: 5px;
}
.my-autocomplete li {
width: 196px;
line-height: normal;
padding: 7px;
}
.my-autocomplete li .name {
text-overflow: ellipsis;
overflow: hidden;
}
.my-autocomplete li .addr {
font-size: 12px;
color: #b4b4b4;
}
.my-autocomplete li .highlighted .addr {
color: #ddd;
}
.my-autocomplete li .goods_id {
color: brown;
}
.my-autocomplete li .goods_name {
color: cornflowerblue;
}
.btn-search {
height: 30px;
width: 80px;
margin: auto 5px 5px auto;
color: black;
}
</style>

View File

@ -0,0 +1,274 @@
<template>
<el-config-provider :locale="zhCn">
<el-container class="content">
<div class="work-area">
<fieldset class="search-area">
<el-form ref="searchQueryFormRef" :model="searchQueryFormEntity" :label-position="labelPosition"
label-width="158px" style="max-width: 100%" status-icon>
<div style="display: flex;justify-content: space-between;">
<el-row>
<el-form-item label="任务名">
<el-input v-model="searchQueryFormEntity.jobName" @keyup.enter="search()" clearable/>
</el-form-item>
<el-form-item label="定时器类型">
<el-select-v2 style="width: 196px;" v-model="searchQueryFormEntity.timerType" placeholder="定时器类型"
:options="addAllOptionOfOptions(timerTypeOptions)"
@change="search()"></el-select-v2>
</el-form-item>
<el-form-item label="任务状态">
<el-select-v2 style="width: 196px;" v-model="searchQueryFormEntity.jobStatus" placeholder="任务状态"
:options="addAllOptionOfOptions(jobStatusOptions)"
@change="search()"></el-select-v2>
</el-form-item>
<el-form-item label="任务类">
<el-input v-model="searchQueryFormEntity.jobClass" @keyup.enter="search()" clearable/>
</el-form-item>
</el-row>
<div style="align-content: center;">
<el-row>
<el-button type="primary" class="btn-search" @click="search()">查询</el-button>
<el-button type="warning" class="btn-search" @click="clearQuery()">清除输入</el-button>
</el-row>
</div>
</div>
</el-form>
</fieldset>
<div class="table-area">
<el-table :data="tableData" stripe border v-loading="tableLoading" class="table-class"
:max-height="maxHeight" highlight-current-row @row-click="getCurrentRow"
:header-cell-style="{ 'text-align': 'center' }" :cell-style="{ 'text-align': 'center' }"
@sort-change="handleSortChange">
<el-table-column width="65px" fixed="left">
<template v-slot="scope">
<el-radio :label="scope.row.jobName" v-model="jobName">&nbsp;</el-radio>
</template>
</el-table-column>
<el-table-column prop="jobName" label="任务名" fixed="left" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="jobClass" label="任务类" min-width="200px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="timerType" label="定时器类型" min-width="120px" :formatter="timerTypeFormat"
sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="jobStatus" label="任务状态" :formatter="jobStatusFormat"
min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column label="定时规则" min-width="150px" sortable="custom"
show-overflow-tooltip>
<template v-slot="scope">
{{ getTimerRule(scope.row) }}
</template>
</el-table-column>
</el-table>
<br/>
<el-pagination v-model:current-page="baseTableQuery.currentPage"
v-model:page-size="baseTableQuery.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="baseTableQuery.total"/>
</div>
</div>
</el-container>
</el-config-provider>
</template>
<script setup>
import store from '@/store'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import {timeFormatter} from '@/utils/formatter.js'
import {ref, reactive, onMounted, nextTick, onBeforeUnmount} from 'vue'
import {ElMessage} from 'element-plus'
import {genTableRequest, addAllOptionOfOptions} from '@/utils/generator.js'
import {labelPosition} from '@/constant/form.js'
import {getJobsByPage} from "@/api/job";
import {timerTypeOptions, jobStatusOptions} from "@/constant/options";
/**
* 常量定义
*/
const STAND_ID = store.getters.getStandId
const USER_NAME = store.getters.getUserName
/**
* 变量定义
*/
let maxHeight = ref(window.innerHeight * 0.55)
let tableLoading = ref(false)
let tableData = ref([])
let baseTableQuery = reactive({
currentPage: 1,
pageSize: 10,
total: 0,
sortBy: new Map([['jobName', true]]),//
standId: STAND_ID,
userName: USER_NAME
})
let searchQueryFormEntity = reactive({
jobName: '',
jobClass: '',
cronExpression: '',
timer: null,
timerType: -99,
jobStatus: -99
})
let searchQueryFormRef = ref()
let jobName = ''
/**
* 系统方法
*/
onMounted(() => {
nextTick(() => {
window.addEventListener('resize', resizeHeight)
search()
})
})
onBeforeUnmount(() => {
nextTick(() => {
window.removeEventListener('resize', resizeHeight)
})
})
const resizeHeight = () => {
maxHeight.value = window.innerHeight * 0.55
}
/**
* 自定义方法
*/
//
const search = () => {
tableLoading.value = true
let request = genTableRequest(baseTableQuery)
//
request.jobName = searchQueryFormEntity.jobName.trim() || null
request.jobClass = searchQueryFormEntity.jobClass.trim() || null
request.cronExpression = searchQueryFormEntity.cronExpression.trim() || null
request.timer = searchQueryFormEntity.timer
request.timerType = searchQueryFormEntity.timerType === -99 ? null : searchQueryFormEntity.timerType
request.jobStatus = searchQueryFormEntity.jobStatus === -99 ? null : searchQueryFormEntity.jobStatus
getJobsByPage(request).then((res) => {
const response = res.data
if (response.code === 0) {
const data = response.data
if (data != null) {
tableData.value = data.lists
baseTableQuery.total = data.total
} else {
tableData.value = []
baseTableQuery.total = 0
}
} else {
ElMessage.error(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('查询数据异常。')
}).finally(() => {
tableLoading.value = false
})
}
const clearQuery = () => {
searchQueryFormEntity.jobName = ''
searchQueryFormEntity.jobClass = ''
searchQueryFormEntity.cronExpression = ''
searchQueryFormEntity.timer = null
searchQueryFormEntity.timerType = -99
searchQueryFormEntity.jobStatus = -99
}
const handleSortChange = (data) => {
if (baseTableQuery.sortBy.has(data.prop)) {
baseTableQuery.sortBy.delete(data.prop)
}
baseTableQuery.sortBy.set(data.prop, data.order.toLowerCase() === 'ascending')
search()
}
const getCurrentRow = (row) => {
jobName = row.jobName
}
const timeFormat = (row, column, cellValue, index) => {
return timeFormatter(cellValue)
}
const timerTypeFormat = (row, column, cellValue, index) => {
const option = timerTypeOptions.find(item => item.value === cellValue)
return option ? option.label : cellValue
}
const jobStatusFormat = (row, column, cellValue, index) => {
return cellValue === 1 ? '生效' : '不生效'
}
const getTimerRule = (row) => {
if (row.timerType === 2) {
// Cron
return row.cronExpression || '-'
} else if (row.timerType === 1) {
//
return row.timer ? `${row.timer}ms` : '-'
}
return '-'
}
</script>
<style scoped>
.content {
display: flex;
width: 100%;
}
.work-area {
width: 100%;
/* padding: 5px; */
}
.search-area {
margin: auto;
min-height: fit-content;
max-height: 40%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.table-area {
margin: auto;
min-height: fit-content;
max-height: 60%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.el-form-item {
margin: 5px 5px 5px 5px;
}
.el-form-item .el-input {
width: 196px;
}
.el-form-item .el-input-number {
width: 196px;
}
.el-form-item .el-select-v2 {
width: 196px;
}
.table-class {
margin: 5px 5px 5px 5px;
width: inherit;
}
.el-pagination {
padding-left: 5px;
}
.btn-search {
height: 30px;
width: 80px;
margin: auto 5px 5px auto;
color: black;
}
</style>

View File

@ -0,0 +1,880 @@
<template>
<el-config-provider :locale="zhCn">
<el-container class="content">
<div class="work-area">
<fieldset class="main-area">
<el-form ref="workFormRef" :model="workFormEntity" :label-position="labelPosition"
label-width="158px" style="max-width: 100%" :rules="rules" status-icon>
<div style="display: flex; justify-content: space-between;">
<el-row>
<el-form-item label="计划开工日期" prop="planStartDate">
<el-date-picker v-model="workFormEntity.planStartDate" type="date"
placeholder="选择开工日期" :shortcuts="shortcuts" style="width: 196px;" clearable/>
</el-form-item>
<el-form-item label="工单号" prop="workOrder">
<el-select v-model="workFormEntity.workOrder" filterable default-first-option
placeholder="请选择工单号" style="width: 196px" :loading="optionLoading" remote
:remote-method="(query) => {
workFormQuery.workOrder = query
initWorkOptions()
}" remote-show-suffix reserve-keyword clearable>
<el-option v-for="item in workOptions.workOrder" :key="item" :label="item"
:value="item"/>
</el-select>
</el-form-item>
<el-form-item label="K料备注" prop="kittingRemark"
v-if="workFormEntity.kittingRemark !== '' && workFormEntity.kittingRemark !== null && workFormEntity.kittingRemark !== undefined">
<el-input v-model="workFormEntity.kittingRemark" placeholder="K料备注"
:input-style="{'color':'red'}" readonly/>
</el-form-item>
<el-form-item label="原始成品号" prop="productIdOrigin">
<el-input v-model="workFormEntity.productIdOrigin" placeholder="原始成品号" disabled/>
</el-form-item>
<el-form-item label="过滤成品号" prop="productId">
<el-input v-model="workFormEntity.productId" placeholder="过滤成品号" disabled/>
</el-form-item>
<el-form-item label="单片号" prop="singleProductId">
<el-select v-model="workFormEntity.singleProductId" filterable default-first-option
placeholder="请选择单片号" style="width: 196px" :loading="optionLoading" remote
:remote-method="(query) => {
workFormQuery.singleProductId = query
initWorkOptions()
}" remote-show-suffix reserve-keyword clearable>
<el-option v-for="item in workOptions.singleProductId" :key="item" :label="item"
:value="item"/>
</el-select>
</el-form-item>
<el-form-item label="料盒号" prop="boxNo">
<el-select v-model="workFormEntity.boxNo" filterable default-first-option
placeholder="请选择料盒号" style="width: 196px" :loading="optionLoading" remote
:remote-method="(query) => {
workFormQuery.boxNo = query
initWorkOptions()
}" remote-show-suffix reserve-keyword clearable>
<el-option v-for="item in workOptions.boxNo" :key="item" :label="item"
:value="item"/>
</el-select>
</el-form-item>
<el-form-item label="原材料号" prop="goodsId">
<el-select v-model="workFormEntity.goodsId" filterable default-first-option
placeholder="请选择原材料号" style="width: 196px" :loading="optionLoading" remote
:remote-method="(query) => {
workFormQuery.goodsId = query
initWorkOptions()
}" remote-show-suffix reserve-keyword clearable>
<el-option v-for="item in workOptions.goodsId" :key="item" :label="item"
:value="item"/>
</el-select>
</el-form-item>
</el-row>
<el-row>
<el-button type="success"
style="height: 50px; width: 100px; margin: auto 5px auto 5px; font-size: large; color: black;"
@click="confirmStart()">确认配料
</el-button>
<el-button type="warning"
style="height: 50px; width: 100px; margin: auto 5px auto 5px; font-size: large; color: black;"
@click="resetWorkFormQuery()">清除选择
</el-button>
</el-row>
</div>
</el-form>
</fieldset>
<fieldset class="confirm-area">
<el-form ref="confirmRef" :model="confirmEntity" :label-position="labelPosition" label-width="158px"
style="max-width: 100%" :rules="confirmRules" status-icon>
<div style="display: flex; justify-content: space-between;">
<el-row>
<el-row style="border-bottom: dashed 1px black;">
<el-form-item label="工单号" prop="workOrder">
<el-input v-model="confirmEntity.workOrder" disabled/>
</el-form-item>
<el-form-item label="成品号" prop="productId">
<el-input v-model="confirmEntity.productId" disabled/>
</el-form-item>
<el-form-item label="单片号" prop="singleProductId">
<el-input v-model="confirmEntity.singleProductId" disabled/>
</el-form-item>
<el-form-item label="物料号" prop="goodsId">
<el-input v-model="confirmEntity.goodsId" disabled/>
</el-form-item>
<el-form-item label="料盒号" prop="boxNo">
<el-input v-model="confirmEntity.boxNo" disabled/>
</el-form-item>
<el-form-item label="K料备注" prop="kittingRemark">
<el-input v-model="confirmEntity.kittingRemark"
:input-style="{'color': 'red'}" readonly/>
</el-form-item>
<el-form-item label="计划拣选数量" prop="planPickQty">
<el-input v-model="confirmEntity.planPickQty" disabled/>
</el-form-item>
<el-form-item label="实际拣选数量" prop="realPickQty">
<el-input-number style="width: 196px" v-model.number="confirmEntity.realPickQty"
controls-position="right" :min="0" clearable @change="changePlanQty()"/>
</el-form-item>
</el-row>
<el-row>
<el-form-item label="箱号" prop="vehicleId">
<el-input v-model="confirmEntity.vehicleId" disabled/>
</el-form-item>
<el-form-item label="存放区域" prop="putArea">
<el-input v-model="confirmEntity.putArea" disabled/>
</el-form-item>
<el-form-item label="计划剩余数量" prop="planRemainQty" v-if="confirmEntity.isOut !== 1">
<el-input v-model="confirmEntity.planRemainQty" disabled/>
</el-form-item>
<el-form-item label="实际剩余数量" prop="realRemainQty" v-if="confirmEntity.isOut !== 1">
<el-input-number style="width: 196px" v-model.number="confirmEntity.realRemainQty"
controls-position="right" :min="0" clearable/>
</el-form-item>
</el-row>
</el-row>
<el-row>
<el-button type="primary"
style="height: 50px; width: 100px; margin: auto 5px auto 5px; font-size: large; color: black;"
@click="showBoxSummary()">显示料盒
</el-button>
<el-button type="success" ref="confirmReleaseBtn"
style="height: 50px; width: 100px; margin: auto 5px auto 5px; font-size: large; color: black;"
@click="confirmOrRelease()">确认/放行
</el-button>
<el-button type="warning"
style="height: 50px; width: 100px; margin: auto 5px auto 5px; font-size: large; color: black;"
@click="requestPrint()">打印标签
</el-button>
</el-row>
</div>
</el-form>
</fieldset>
<div class="table-area">
<el-table :data="currentBoxGoodsList" stripe border class="table-class" max-height="350px"
highlight-current-row :header-cell-style="{ 'text-align': 'center' }"
:cell-style="{ 'text-align': 'center' }" @sort-change="handleSortChange">
<el-table-column prop="goodsId" label="料号" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="needNum" label="需求数量" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="finishNum" label="已完成数量" min-width="120px" sortable="custom"
show-overflow-tooltip/>
</el-table>
<br/>
<el-pagination v-model:current-page="baseTableQuery.currentPage"
v-model:page-size="baseTableQuery.pageSize" :page-sizes="[5, 10, 15]" :small="false"
:disabled="false" :background="false" :default-page-size="5" @size-change="searchKittingGoods"
@current-change="searchKittingGoods" layout="total, sizes, prev, pager, next, jumper"
:total="baseTableQuery.total"/>
</div>
<el-dialog v-model="boxShowFlag" title="料盒总览" width="50%" center :close="closeBoxSummary">
<span>料盒信息</span>
<el-table :data="boxSummary" stripe border class="table-class" max-height="200px"
:header-cell-style="{ 'text-align': 'center' }" :cell-style="{ 'text-align': 'center' }">
<el-table-column prop="workOrder" label="工单号" fixed="left"/>
<el-table-column prop="taoQty" label="套数"/>
<el-table-column prop="productId" label="总成号"/>
<el-table-column prop="singleProductId" label="成品/单片"/>
<el-table-column prop="boxNo" label="料盒号"/>
<el-table-column prop="boxQty" label="料盒数量"/>
</el-table>
<span>缺料信息</span>
<el-table :data="goodsLackSummary" stripe border class="table-class" max-height="450px"
:header-cell-style="{ 'text-align': 'center' }" :cell-style="{ 'text-align': 'center' }">
<el-table-column prop="goodsId" label="料号" fixed="left"/>
<el-table-column prop="needNum" label="需求数量"/>
<el-table-column prop="stockNum" label="库存数量"/>
<el-table-column prop="lackNum" label="缺料数量"/>
<el-table-column prop="remark" label="备注"/>
</el-table>
</el-dialog>
<div style="width: 0;height: 0;overflow: hidden">
<button ref="printBtn" style="display: none;" v-print="printObj"></button>
<div id="printArea" class="objectDialogFlowPrint">
<div class="pageWarp" v-for="item in printTabs">
<div class="print-tab-text">
<div class="print-row-normal">工单{{ item.workOrder }}</div>
<div class="print-row-normal">总成{{ item.productId }}</div>
<div class="print-row-normal">单片{{ item.singleProductId }}</div>
<div class="print-row-normal">配料{{ item.kittingDate }}</div>
</div>
<div class="print-tab-text">
<div class="print-row-normal">测试台{{ item.testNo }}</div>
<div class="print-row-normal">产量{{ item.productionQty }}</div>
<div class="print-row-normal">料盒号{{ item.boxNo }}</div>
<div class="print-row-normal">生产{{ item.produceDate }}</div>
</div>
<div class="print-tab-image">
<qrcode-vue
:value="item.imageId"
:size="size" :foreground="color" level="H"/>
</div>
</div>
</div>
</div>
<div style="width: 0;height: 0;overflow: hidden">
<button ref="printLackGoodsBtn" style="display: none;"
v-print="getPrintObj('printLackGoodsArea')"></button>
<div id="printLackGoodsArea" class="objectDialogFlowPrint">
<div class="pageWarp" v-for="item in lackGoodsForPrint">
<div class="print-tab-full" style="margin-left: 30px">
<div class="print-row-big">料盒{{ item.boxNo }}</div>
<div class="print-row-big">料号{{ item.goodsId }}</div>
<div class="print-row-big">需求{{ item.needNum }}</div>
<div class="print-row-big">缺料{{ item.needNum - item.finishNum }}</div>
</div>
</div>
</div>
</div>
</div>
</el-container>
</el-config-provider>
</template>
<script setup>
import store from '@/store'
import QrcodeVue from 'qrcode.vue'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import {
queryKateWorks,
initWorks,
getCurrentWorks,
confirmCurrentWork,
getBoxesAndLacks,
queryWorkingGoodsByPage,
getLackGoods
} from '@/api/kateWork.js'
import {errorBox, successBox, warningBox} from '@/utils/myMessageBox.js'
import {ElMessage} from 'element-plus'
import {dateFormatter} from '@/utils/formatter.js'
import {nextTick, onBeforeUnmount, onMounted, reactive, ref, watch} from 'vue'
import {printObj, labelPosition, shortcuts, getPrintObj} from '@/constant/form'
import {loading} from '@/utils/loading'
import {genTableRequest} from '@/utils/generator.js'
import {useRoute} from 'vue-router'
const standId = store.getters.getStandId
const userName = store.getters.getUserName
let storeKittingWork = store.getters.getKittingWork
let timer = ref()
let optionLoading = ref(false)
let workOptions = reactive({
workOrder: [],
singleProductId: [],
boxNo: [],
goodsId: []
})
let workFormRef = ref()
let workFormEntity = reactive({
workOrder: '',
productIdOrigin: '',
productId: '',
singleProductId: '',
boxNo: '',
goodsId: '',
planStartDate: null,
kittingRemark: ''
})
let workFormQuery = reactive({
workOrder: '',
singleProductId: '',
boxNo: '',
goodsId: '',
})
const rules = reactive({
workOrder: [
{required: true, message: '请选择工单号。'}
]
})
let confirmRef = ref()
let confirmEntity = reactive({
workOrder: storeKittingWork.workOrder,
productId: storeKittingWork.productId,
singleProductId: storeKittingWork.singleProductId,
boxNo: storeKittingWork.boxNo
})
let confirmRules = reactive({})
let boxShowFlag = ref(false)
let boxSummary = ref([])
let goodsLackSummary = ref([])
let pauseGetWorkFlag = ref(false)
let printTabs = ref([])
let currentBoxGoodsList = ref([])
let baseTableQuery = reactive({
currentPage: 1,
pageSize: 5,
total: 0,
sortBy: new Map([['goodsId', true]]),//
standId: store.getters.getStandId,
userName: store.getters.getUserName
})
let lackGoodsForPrint = ref([])
const printBtn = ref()
const printLackGoodsBtn = ref()
const confirmReleaseBtn = ref()
const size = ref(35)
const color = ref('#000000')
const route = useRoute()//
//
onMounted(() => {
nextTick(() => {
initWorkOptions()
timer.value = setInterval(() => {
timerTask_1()
}, 1000)
// enter
window.addEventListener('keydown', solveEnterKey)
})
})
onBeforeUnmount(() => {
clearInterval(timer.value)
window.removeEventListener('keydown', solveEnterKey)
})
//
watch(() => route.path, (newVal, oldVal) => {
if (newVal === '/kitting') {
timer.value = setInterval(() => {
timerTask_1()
}, 1000)
// enter
window.addEventListener('keydown', solveEnterKey)
} else {
clearInterval(timer.value)
window.removeEventListener('keydown', solveEnterKey)
}
})
watch(() => workFormEntity.workOrder, (newVal, oldVal) => {
if (newVal === '') {
workFormEntity.productIdOrigin = ''
workFormEntity.productId = ''
workFormEntity.singleProductId = ''
workFormEntity.boxNo = ''
workFormEntity.goodsId = ''
workFormEntity.kittingRemark = ''
}
})
watch(() => workFormEntity.productId, (newVal, oldVal) => {
if (newVal !== oldVal) {
workFormEntity.singleProductId = ''
workFormEntity.boxNo = ''
workFormEntity.goodsId = ''
}
})
watch(() => workFormEntity.singleProductId, (newVal, oldVal) => {
if (newVal !== oldVal) {
workFormEntity.boxNo = ''
workFormEntity.goodsId = ''
}
})
watch(() => workFormEntity.boxNo, (newVal, oldVal) => {
if (newVal !== oldVal) {
workFormEntity.goodsId = ''
}
})
// 1
const timerTask_1 = () => {
//
getWork()
//
ifNeedShowBoxSummary()
//
searchKittingGoods()
}
//
const solveEnterKey = (e) => {
if (e.key.toLowerCase() === 'enter') {
confirmReleaseBtn.value.$el.click()
}
}
// options
const initWorkOptions = () => {
const request = {
workOrder: workFormQuery.workOrder !== '' ? workFormQuery.workOrder : workFormEntity.workOrder,
singleProductId: workFormQuery.singleProductId !== '' ? workFormQuery.singleProductId : workFormEntity.singleProductId,
boxNo: workFormQuery.boxNo !== '' ? workFormQuery.boxNo : workFormEntity.boxNo,
goodsId: workFormQuery.goodsId !== '' ? workFormQuery.goodsId : workFormEntity.goodsId,
planStartDate: dateFormatter(workFormEntity.planStartDate)
}
optionLoading.value = true
queryKateWorks(request).then(res => {
const response = res.data
if (response.code === 0) {
workOptions.workOrder = response.data.workOrder
//
workFormEntity.productIdOrigin = response.data.productIdOrigin
workFormEntity.productId = response.data.productId
workFormEntity.kittingRemark = response.data.kittingRemark
workOptions.singleProductId = response.data.singleProductId
workOptions.boxNo = response.data.boxNo
workOptions.goodsId = response.data.goodsId
} else {
workOptions.workOrder = []
//
workFormEntity.productIdOrigin = ''
workFormEntity.productId = ''
workFormEntity.kittingRemark = ''
workOptions.singleProductId = []
workOptions.boxNo = []
workOptions.goodsId = []
}
}).catch(err => {
console.log(err)
errorBox('查询选项错误。')
}).finally(() => {
optionLoading.value = false
})
}
//
const resetWorkFormQuery = () => {
workFormQuery.workOrder = ''
workFormQuery.singleProductId = ''
workFormQuery.boxNo = ''
workFormQuery.goodsId = ''
workFormEntity.workOrder = ''
workFormEntity.productIdOrigin = ''
workFormEntity.productId = ''
workFormEntity.singleProductId = ''
workFormEntity.boxNo = ''
workFormEntity.goodsId = ''
workFormEntity.kittingRemark = ''
}
//
const confirmStart = () => {
const request = {
workOrder: workFormEntity.workOrder,
singleProductId: workFormEntity.singleProductId,
boxNo: workFormEntity.boxNo,
goodsId: workFormEntity.goodsId,
standId: standId,
userName: userName
}
loading.open('处理中...')
initWorks(request).then(res => {
const response = res.data
if (response.code === 0) {
ElMessage.success(response.message)
setTimeout(() => {
showBoxSummary()
}, 2000)
} else {
errorBox(response.message)
}
}).catch(err => {
console.log(err)
errorBox('请求错误。')
}).finally(() => {
loading.close()
})
}
//
const showBoxSummary = () => {
if (boxShowFlag.value) {
return
}
boxSummary.value = []
goodsLackSummary.value = []
//
const request = {
standId: standId,
userName: userName
}
getBoxesAndLacks(request).then(res => {
const response = res.data
if (response.code === 0) {
const boxDetailVo = response.data
//
getPrintTabs(boxDetailVo.boxSummary)
//
boxSummary.value = [boxDetailVo.boxSummary]
goodsLackSummary.value = boxDetailVo.goodsLackSummary
boxShowFlag.value = true
} else {
errorBox(response.message)
}
}).catch(error => {
console.log(error)
errorBox('发生异常:' + error)
})
}
//
const closeBoxSummary = () => {
boxSummary.value = []
goodsLackSummary.value = []
boxShowFlag.value = false
}
//
const getWork = () => {
if (pauseGetWorkFlag.value) {
return
}
const request = {
standId: standId,
userName: userName
}
getCurrentWorks(request).then(res => {
const response = res.data
if (response.code === 0) {
// form
confirmEntity.workIndex = response.data.orderConfirm.workIndex
confirmEntity.workOrder = response.data.orderConfirm.workOrder
confirmEntity.productId = response.data.orderConfirm.productId
confirmEntity.singleProductId = response.data.orderConfirm.singleProductId
confirmEntity.boxNo = response.data.orderConfirm.boxNo
confirmEntity.goodsId = response.data.orderConfirm.goodsId
confirmEntity.planPickQty = response.data.orderConfirm.planPickQty
confirmEntity.realPickQty = response.data.orderConfirm.realPickQty
confirmEntity.kittingRemark = response.data.orderConfirm.kittingRemark
confirmEntity.stockId = response.data.stockConfirm.stockId
confirmEntity.vehicleId = response.data.stockConfirm.vehicleId
confirmEntity.planRemainQty = response.data.stockConfirm.planRemainQty
confirmEntity.realRemainQty = response.data.stockConfirm.realRemainQty
confirmEntity.isOut = response.data.stockConfirm.isOut
confirmEntity.putArea = response.data.stockConfirm.putArea
confirmEntity.warningQty = response.data.stockConfirm.warningQty
pauseGetWorkFlag.value = true
//
if (confirmEntity.isOut === 0 && confirmEntity.planRemainQty <= confirmEntity.warningQty) {
warningBox('剩余数量低于预警值,请清点库存数量。')
}
} else if (response.code === 400) {
//
pauseGetWorkFlag.value = true
warningBox(response.message)
} else {
if (response.data != null && response.data.orderConfirm != null) {
confirmEntity.workOrder = response.data.orderConfirm.workOrder
confirmEntity.boxNo = response.data.orderConfirm.boxNo
confirmEntity.productId = response.data.orderConfirm.productId
confirmEntity.singleProductId = response.data.orderConfirm.singleProductId
confirmEntity.kittingRemark = response.data.orderConfirm.kittingRemark
} else {
confirmEntity.workOrder = ''
confirmEntity.boxNo = ''
confirmEntity.productId = ''
confirmEntity.singleProductId = ''
confirmEntity.kittingRemark = ''
}
}
}).catch(err => {
console.log(err)
pauseGetWorkFlag.value = true
errorBox('请求错误,请检查完原因后刷新界面。')
})
}
//
const ifNeedShowBoxSummary = () => {
if (storeKittingWork.workOrder !== '') {
//
if (confirmEntity.workOrder !== storeKittingWork.workOrder
|| confirmEntity.productId !== storeKittingWork.productId
|| confirmEntity.singleProductId !== storeKittingWork.singleProductId
|| confirmEntity.boxNo !== storeKittingWork.boxNo) {
if (confirmEntity.workOrder === '') {
// ---
printLacks(storeKittingWork.workOrder, storeKittingWork.productId, storeKittingWork.singleProductId, storeKittingWork.boxNo, '2')
//
successBox('当前工单已完成。')
} else if (confirmEntity.boxNo !== storeKittingWork.boxNo) {
printLacks(storeKittingWork.workOrder, storeKittingWork.productId, storeKittingWork.singleProductId, storeKittingWork.boxNo, '1')
//
showBoxSummary()
}
// store
storeKittingWork.workOrder = confirmEntity.workOrder
storeKittingWork.productId = confirmEntity.productId
storeKittingWork.singleProductId = confirmEntity.singleProductId
storeKittingWork.boxNo = confirmEntity.boxNo
}
} else {
// store
storeKittingWork.workOrder = confirmEntity.workOrder
storeKittingWork.productId = confirmEntity.productId
storeKittingWork.singleProductId = confirmEntity.singleProductId
storeKittingWork.boxNo = confirmEntity.boxNo
}
store.commit('mutationKittingWork', storeKittingWork)
}
//
const confirmOrRelease = () => {
const request = {
orderConfirm: {
workIndex: confirmEntity.workIndex,
workOrder: confirmEntity.workOrder,
productId: confirmEntity.productId,
singleProductId: confirmEntity.singleProductId,
boxNo: confirmEntity.boxNo,
goodsId: confirmEntity.goodsId,
planPickQty: confirmEntity.planPickQty,
realPickQty: confirmEntity.realPickQty
},
stockConfirm: {
stockId: confirmEntity.stockId,
vehicleId: confirmEntity.vehicleId,
goodsId: confirmEntity.goodsId,
planRemainQty: confirmEntity.planRemainQty,
realRemainQty: confirmEntity.realRemainQty,
isOut: confirmEntity.isOut,
putArea: confirmEntity.putArea
},
standId: standId,
userName: userName
}
loading.open('确认中...')
confirmCurrentWork(request).then(res => {
const response = res.data
if (response.code === 0) {
// form
resetConfirmEntity()
ElMessage.success(response.message)
} else if (response.code === 400) {
// form
resetConfirmEntity()
//
warningBox(response.message)
} else {
//
errorBox(response.message)
}
pauseGetWorkFlag.value = false
}).catch(err => {
console.log(err)
errorBox('请求错误,请检查完原因后刷新界面。')
}).finally(() => {
loading.close()
})
}
const resetConfirmEntity = () => {
confirmEntity.workIndex = ''
confirmEntity.goodsId = ''
confirmEntity.planPickQty = null
confirmEntity.realPickQty = null
confirmEntity.stockId = ''
confirmEntity.kittingRemark = ''
confirmEntity.vehicleId = ''
confirmEntity.planRemainQty = null
confirmEntity.realRemainQty = null
confirmEntity.isOut = null
confirmEntity.putArea = ''
confirmEntity.warningQty = null
}
//
const changePlanQty = () => {
if (confirmEntity.isOut === 0 && confirmEntity.realPickQty !== confirmEntity.planPickQty) {
//
const changeQty = confirmEntity.realPickQty - confirmEntity.planPickQty
//
confirmEntity.realRemainQty = confirmEntity.planRemainQty - changeQty
}
}
const requestPrint = () => {
nextTick(() => {
printBtn.value.click()
});
}
//
const getPrintTabs = (boxSummary) => {
printTabs.value = []
if (boxSummary !== undefined) {
for (let i = 1; i <= boxSummary.boxQty; i++) {
printTabs.value.push(
{
workOrder: boxSummary.workOrder,
productId: boxSummary.productIdOrigin,
singleProductId: boxSummary.singleProductId,
boxNo: boxSummary.boxNo,
kittingDate: boxSummary.kittingDate,
produceDate: boxSummary.produceDate,
testNo: boxSummary.testNo,
productionQty: boxSummary.productionQty,
imageId: boxSummary.imageId,
}
)
}
}
}
//
const searchKittingGoods = () => {
let request = genTableRequest(baseTableQuery)
request.workOrder = confirmEntity.workOrder
request.productId = confirmEntity.productId
request.singleProductId = confirmEntity.singleProductId
request.boxNo = confirmEntity.boxNo
queryWorkingGoodsByPage(request).then(res => {
const response = res.data
if (response.code === 0) {
const data = response.data
if (data != null) {
currentBoxGoodsList.value = data.lists
baseTableQuery.total = data.total
} else {
currentBoxGoodsList.value = []
baseTableQuery.total = 0
}
}
}).catch(err => {
console.log(err)
})
}
//
const handleSortChange = (data) => {
if (baseTableQuery.sortBy.has(data.prop)) {
baseTableQuery.sortBy.delete(data.prop)
}
baseTableQuery.sortBy.set(data.prop, data.order.toLowerCase() === 'ascending')
searchKittingGoods()
}
//
// printLackType;1:2:
const printLacks = (workOrder, productId, singleProductId, boxNo, printLackType) => {
const request = {
workOrder: workOrder,
productId: productId,
singleProductId: singleProductId,
boxNo: boxNo,
bk1: printLackType,
standId: standId,
userName: userName
}
getLackGoods(request).then(res => {
const response = res.data
if (response.code === 0) {
lackGoodsForPrint.value = response.data
nextTick(() => {
printLackGoodsBtn.value.click()
});
}
}).catch(err => {
console.log(err)
})
}
</script>
<style scoped>
.content {
display: flex;
width: 100%;
}
.work-area {
width: 100%;
/* padding: 5px; */
}
.main-area {
margin: auto;
min-height: fit-content;
max-height: 90%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.confirm-area {
margin: auto;
min-height: fit-content;
max-height: 90%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.title-area {
display: flex;
/* min-height: 10%; */
max-height: max-content;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
}
.table-area {
margin: auto;
min-height: fit-content;
max-height: 60%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.el-form-item {
margin: 10px 5px 10px 5px;
}
.el-form-item .el-input {
width: 196px;
}
.table-class {
margin: 5px 5px 5px 5px;
width: inherit;
}
@media print {
@page {
size: auto;
margin: 0;
}
body,
html {
height: auto !important;
}
}
.objectDialogFlowPrint {
width: 100% !important;
height: 100% !important;
}
.objectDialogFlowPrint .pageWarp {
/*这句话很重要,控制时候强制分页 https://www.w3school.com.cn/cssref/pr_page-break-after.asp*/
page-break-after: always;
width: 100%;
height: 100%;
text-align: center;
padding: 0;
display: flex;
print-color-adjust: exact;
}
.print-tab-text {
width: 40%;
align-content: center;
}
.print-tab-image {
width: 20%;
align-content: center;
}
.print-row-normal {
margin: 8px 3px 8px 3px;
font-size: 13px;
font-weight: bold;
text-align: left;
}
.print-tab-full {
width: 90%;
align-content: center;
}
.print-row-big {
margin: 8px 3px 8px 3px;
font-size: 20px;
font-weight: bold;
text-align: left;
}
</style>

View File

@ -0,0 +1,386 @@
<template>
<el-config-provider :locale="zhCn">
<el-container class="content">
<div class="work-area">
<fieldset class="search-area">
<el-form ref="kittingBomQueryFormRef" :model="kittingBomQueryFormEntity"
:label-position="labelPosition" label-width="158px" style="max-width: 100%" status-icon>
<div style="display: flex;justify-content: space-between;">
<el-row>
<el-form-item label="配料单类型">
<el-select-v2 style="width: 196px" v-model="kittingBomQueryFormEntity.bomType"
placeholder="配料单类型"
:options="kittingBomTypeOptions" @change="search()"></el-select-v2>
</el-form-item>
<el-form-item label="机型">
<el-input v-model="kittingBomQueryFormEntity.model" @keyup.enter="search()" clearable/>
</el-form-item>
<el-form-item label="成品号">
<el-input v-model="kittingBomQueryFormEntity.productId" @keyup.enter="search()" clearable/>
</el-form-item>
<el-form-item label="原材料号">
<el-input v-model="kittingBomQueryFormEntity.goodsId" @keyup.enter="search()" clearable/>
</el-form-item>
<el-form-item label="料盒号">
<el-input v-model="kittingBomQueryFormEntity.boxNo" @keyup.enter="search()" clearable/>
</el-form-item>
</el-row>
<div style="align-content: center;">
<el-row>
<el-button type="primary" class="btn-search" @click="search()">查询</el-button>
<el-button type="warning" class="btn-search" @click="clearQuery()">清除输入</el-button>
</el-row>
<el-row>
<el-button style="background-color: #00CED1;" class="btn-search"
@click="openUploadDialog()">导入配料单
</el-button>
<el-button type="success" class="btn-search"
@click="exportExcel()">导出excel
</el-button>
</el-row>
</div>
</div>
</el-form>
</fieldset>
<div class="table-area">
<el-table :data="displayKittingList" stripe border v-loading="tableLoading" class="table-class"
:max-height="maxHeight" highlight-current-row @row-click="getCurrentRow"
:header-cell-style="{ 'text-align': 'center' }" :cell-style="{ 'text-align': 'center' }"
@sort-change="handleSortChange">
<el-table-column width="65px" fixed="left">
<template v-slot="scope">
<el-radio :label="scope.row.templateId" v-model="templateId">&nbsp;</el-radio>
</template>
</el-table-column>
<el-table-column prop="bomType" label="配料单类型" fixed="left" min-width="120px" sortable="custom"
:formatter="bomTypeFormat" show-overflow-tooltip/>
<el-table-column prop="model" label="机型" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="productId"
:label="kittingBomQueryFormEntity.bomType === 1 ? '成品号' : '服务件成品号'" fixed="left"
min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="goodsId" label="原材料号" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="goodsDescription" label="物料描述" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="quantity1Pair" label="单套数量" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="boxNo" label="料盒号" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="quantityOfPair" label="套数" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column fixed="right" label="操作" width="120px">
<template v-slot="scope">
<el-button plain type="danger" @click="deleteThisProduct(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<br/>
<el-pagination v-model:current-page="baseTableQuery.currentPage"
v-model:page-size="baseTableQuery.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="baseTableQuery.total"/>
</div>
<el-dialog v-model="showKittingBomUploadDialog" title="上传配料单" width="40%" draggable :show-close="true">
<fieldset class="search-area" v-if="kittingBomQueryFormEntity.bomType === 1">
<legend>导入非服务件配料单</legend>
<UploadExcelProduct></UploadExcelProduct>
</fieldset>
<fieldset class="search-area" v-if="kittingBomQueryFormEntity.bomType === 2">
<legend>导入服务件配料单</legend>
<UploadExcelSingleProduct></UploadExcelSingleProduct>
</fieldset>
</el-dialog>
</div>
</el-container>
</el-config-provider>
</template>
<script setup>
import store from '@/store'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import UploadExcelProduct from '@/excel/UploadExcelProduct.vue'
import UploadExcelSingleProduct from '@/excel/UploadExcelSingleProduct.vue'
import {deleteKittingBom, queryKittingBomByPage} from '@/api/kateWork.js'
import {dateFormatter} from '@/utils/formatter.js'
import {ref, reactive, onMounted, nextTick, onBeforeUnmount} from 'vue'
import {ElMessage, ElMessageBox} from 'element-plus'
import {genTableRequest} from '@/utils/generator.js'
import {labelPosition} from '@/constant/form.js'
import {kittingBomTypeOptions} from '@/constant/options.js'
import {exportKittingBomWithExcel} from '@/api/excel.js'
import {loading} from "@/utils/loading";
/**
* 常量定义
*/
const USER_NAME = store.getters.getUserName
const STAND_ID = store.getters.getStandId
/**
* 变量定义
*/
let maxHeight = ref(window.innerHeight * 0.55)
let tableLoading = ref(false)
let displayKittingList = ref([])
let baseTableQuery = reactive({
currentPage: 1,
pageSize: 10,
total: 0,
sortBy: new Map([['productId', true]]),//
standId: STAND_ID,
userName: USER_NAME
})
let kittingBomQueryFormEntity = reactive({
bomType: 1,
model: '',
productId: '',
goodsId: '',
boxNo: ''
})
let kittingBomQueryFormRef = ref()
let templateId = ''
let showKittingBomUploadDialog = ref(false)
/**
* 系统方法
*/
onMounted(() => {
nextTick(() => {
window.addEventListener('resize', resizeHeight)
search()
})
})
onBeforeUnmount(() => {
nextTick(() => {
window.removeEventListener('resize', resizeHeight)
})
})
const resizeHeight = () => {
maxHeight.value = window.innerHeight * 0.55
}
/**
* 自定义方法
*/
//
const search = () => {
tableLoading.value = true
let request = genTableRequest(baseTableQuery)
//
request.bomType = kittingBomQueryFormEntity.bomType
request.model = kittingBomQueryFormEntity.model.trim()
request.productId = kittingBomQueryFormEntity.productId.trim()
request.goodsId = kittingBomQueryFormEntity.goodsId.trim()
request.boxNo = kittingBomQueryFormEntity.boxNo.trim()
queryKittingBomByPage(request).then((res) => {
const response = res.data
if (response.code === 0) {
const data = response.data
if (data != null) {
displayKittingList.value = data.lists
baseTableQuery.total = data.total
} else {
displayKittingList.value = []
baseTableQuery.total = 0
}
} else {
ElMessage.error(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('查询配料单异常。')
}).finally(() => {
tableLoading.value = false
})
}
const clearQuery = () => {
kittingBomQueryFormEntity.model = ''
kittingBomQueryFormEntity.productId = ''
kittingBomQueryFormEntity.goodsId = ''
kittingBomQueryFormEntity.boxNo = ''
}
const bomTypeFormat = (row, column, cellValue, index) => {
switch (cellValue) {
case 1:
return '非服务件'
case 2:
return '服务件'
default:
return '未知类型'
}
}
const handleSortChange = (data) => {
if (baseTableQuery.sortBy.has(data.prop)) {
baseTableQuery.sortBy.delete(data.prop)
}
baseTableQuery.sortBy.set(data.prop, data.order.toLowerCase() === 'ascending')
search()
}
const getCurrentRow = (row) => {
templateId = row.templateId
}
const exportExcel = () => {
const params = {
bomType: kittingBomQueryFormEntity.bomType,
model: kittingBomQueryFormEntity.model,
productId: kittingBomQueryFormEntity.productId,
goodsId: kittingBomQueryFormEntity.goodsId,
boxNo: kittingBomQueryFormEntity.boxNo
}
exportKittingBomWithExcel(params).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]; //
const preName = kittingBomQueryFormEntity.bomType === 1 ? '非服务件' : '服务件'
let _fileName = preName + '配料单' + 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) {
console.log(e)
ElMessage.error('下载文件失败')
}
}).catch(err => {
console.log(err)
ElMessage.error('导出失败')
})
}
//
const deleteThisProduct = (row) => {
const toDeleteProductId = row.productId
ElMessageBox.confirm(
'当前操作会删除' + toDeleteProductId + '的整个配料单' + '。\n是否确认',
'警告',
{
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
}
).then(() => {
const request = {
bomType: row.bomType,
productId: row.productId,
userName: USER_NAME,
standId: STAND_ID
}
loading.open('删除中...')
deleteKittingBom(request).then(res => {
const response = res.data
if (response.code === 0) {
ElMessage.success(response.message)
} else {
ElMessage.error(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('删除异常')
}).finally(() => {
search()
loading.close()
})
}).catch((err) => {
console.log(err)
ElMessage.info('操作取消')
})
}
const openUploadDialog = () => {
showKittingBomUploadDialog.value = true
}
</script>
<style scoped>
.content {
display: flex;
width: 100%;
}
.work-area {
width: 100%;
/* padding: 5px; */
}
.search-area {
margin: auto;
min-height: fit-content;
max-height: 40%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.table-area {
margin: auto;
min-height: fit-content;
max-height: 60%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.el-form-item {
margin: 5px 5px 5px 5px;
}
.el-form-item .el-input {
width: 196px;
}
.table-class {
margin: 5px 5px 5px 5px;
width: inherit;
}
.el-pagination {
padding-left: 5px;
}
.my-autocomplete li {
width: 196px;
line-height: normal;
padding: 7px;
}
.my-autocomplete li .name {
text-overflow: ellipsis;
overflow: hidden;
}
.my-autocomplete li .addr {
font-size: 12px;
color: #b4b4b4;
}
.my-autocomplete li .highlighted .addr {
color: #ddd;
}
.my-autocomplete li .goods_id {
color: brown;
}
.my-autocomplete li .goods_name {
color: cornflowerblue;
}
.btn-search {
height: 30px;
width: 80px;
margin: auto 5px 5px auto;
color: black;
}
</style>

View File

@ -0,0 +1,455 @@
<template>
<el-config-provider :locale="zhCn">
<el-container class="content">
<div class="work-area">
<fieldset class="search-area">
<el-form ref="relationQueryFormRef" :model="relationQueryFormEntity" :label-position="labelPosition"
label-width="158px" style="max-width: 100%" status-icon>
<div style="display: flex;justify-content: space-between;">
<el-row>
<el-form-item label="机型">
<el-input v-model="relationQueryFormEntity.model" @keyup.enter="search()" clearable />
</el-form-item>
<el-form-item label="总成号">
<el-input v-model="relationQueryFormEntity.productId" @keyup.enter="search()" clearable />
</el-form-item>
<el-form-item label="单片号">
<el-input v-model="relationQueryFormEntity.singleProductId" @keyup.enter="search()" clearable />
</el-form-item>
</el-row>
<div style="align-content: center;">
<el-row>
<el-button type="primary" class="btn-search" @click="search()">查询</el-button>
<el-button type="warning" class="btn-search" @click="clearQuery()">清除输入</el-button>
</el-row>
<el-row>
<el-button style="background-color: #00CED1;" class="btn-search"
@click="openUploadDialog()">导入数据</el-button>
<el-button type="success" class="btn-search"
@click="exportExcel()">导出excel</el-button>
</el-row>
</div>
</div>
</el-form>
</fieldset>
<div class="table-area">
<el-table :data="displayRelationList" stripe border v-loading="tableLoading" class="table-class"
:max-height="maxHeight" highlight-current-row @row-click="getCurrentRow"
:header-cell-style="{ 'text-align': 'center' }" :cell-style="{ 'text-align': 'center' }"
@sort-change="handleSortChange">
<el-table-column width="65px" fixed="left">
<template v-slot="scope">
<el-radio :label="scope.row.recordId" v-model="recordId">&nbsp;</el-radio>
</template>
</el-table-column>
<el-table-column prop="model" label="机型" min-width="120px" sortable="custom"
show-overflow-tooltip />
<el-table-column prop="productId" label="总成号" min-width="120px" sortable="custom"
show-overflow-tooltip />
<el-table-column prop="singleProductId" label="单片号" min-width="120px" sortable="custom"
show-overflow-tooltip />
<!-- <el-table-column fixed="right" label="操作" width="120px">
<template v-slot="scope">
<el-button plain type="primary" @click="editCurrentRowStock(scope.row)">编辑</el-button>
</template>
</el-table-column> -->
</el-table>
<br />
<el-pagination v-model:current-page="baseTableQuery.currentPage"
v-model:page-size="baseTableQuery.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="baseTableQuery.total" />
</div>
<!-- <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="stockId">
<el-input v-model="stockFormEntity.stockId" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="箱号" prop="vehicleId">
<el-input v-model="stockFormEntity.vehicleId" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="料号" prop="goodsId">
<el-input v-model="stockFormEntity.goodsId" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="料名" prop="goodsName">
<el-input v-model="stockFormEntity.goodsName" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="入库数量" prop="totalNum">
<el-input-number v-model.number="stockFormEntity.totalNum" controls-position="right"
:min="0" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="剩余数量为0时删除库存" prop="remainNum">
<el-input-number v-model.number="stockFormEntity.remainNum"
controls-position="right" :min="0" :max="stockFormEntity.totalNum" clearable />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="库位" prop="locationId">
<el-input v-model="stockFormEntity.locationId" clearable />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="未使用天数" prop="noUseDays">
<el-input-number v-model.number="stockFormEntity.noUseDays"
controls-position="right" :min="0" disabled />
</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-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="盘点任务号" prop="inventoryTaskId">
<el-input v-model="stockFormEntity.inventoryTaskId" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="是否盘点" prop="isInventory">
<el-input v-model="stockFormEntity.isInventory" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="创建时间" prop="createTime">
<el-input v-model="stockFormEntity.createTime" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="最近更新时间" prop="lastUpdateTime">
<el-input v-model="stockFormEntity.lastUpdateTime" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="最近更新用户" prop="lastUpdateUser">
<el-input v-model="stockFormEntity.lastUpdateUser" disabled />
</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-dialog v-model="showRelationUploadDialog" title="上传配对关系" width="40%" draggable :show-close="true">
<fieldset class="search-area">
<legend>导入总成-单片对应</legend>
<UploadExcelProductExtend></UploadExcelProductExtend>
</fieldset>
</el-dialog>
</div>
</el-container>
</el-config-provider>
</template>
<script setup>
import store from '@/store'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import UploadExcelProductExtend from '@/excel/UploadExcelProductExtend.vue'
import { queryRelationByPage } from '@/api/kateWork.js'
import { dateFormatter, timeFormatter } from '@/utils/formatter.js'
import { ref, reactive, onMounted, nextTick, onBeforeUnmount } from 'vue'
import { ElMessage } from 'element-plus'
import { genTableRequest } from '@/utils/generator.js'
import { labelPosition } from '@/constant/form'
import { exportKittingBomRelationWithExcel } from '@/api/excel.js'
/**
* 常量定义
*/
/**
* 变量定义
*/
let maxHeight = ref(window.innerHeight * 0.55)
let tableLoading = ref(false)
let displayRelationList = ref([])
let baseTableQuery = reactive({
currentPage: 1,
pageSize: 10,
total: 0,
sortBy: new Map([['productId', true]]),//
standId: store.getters.getStandId,
userName: store.getters.getUserName
})
let relationQueryFormEntity = reactive({
model: '',
productId: '',
singleProductId: ''
})
let relationQueryFormRef = ref()
let showRelationAddFlag = ref(false)
let recordId = ''
let relationAddFormRef = ref()
let relationAddFormEntity = reactive({})
let showRelationUploadDialog = ref(false)
/**
* 系统方法
*/
onMounted(() => {
nextTick(() => {
window.addEventListener('resize', resizeHeight)
search()
})
})
onBeforeUnmount(() => {
nextTick(() => {
window.removeEventListener('resize', resizeHeight)
})
})
const resizeHeight = () => {
maxHeight.value = window.innerHeight * 0.55
}
/**
* 自定义方法
*/
//
const search = () => {
tableLoading.value = true
let request = genTableRequest(baseTableQuery)
//
request.model = relationQueryFormEntity.model.trim()
request.productId = relationQueryFormEntity.productId.trim()
request.singleProductId = relationQueryFormEntity.singleProductId.trim()
queryRelationByPage(request).then((res) => {
const response = res.data
if (response.code == 0) {
const data = response.data
if (data != null) {
displayRelationList.value = data.lists
baseTableQuery.total = data.total
} else {
displayRelationList.value = []
baseTableQuery.total = 0
}
} else {
ElMessage.error(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('查询对应关系异常。')
}).finally(() => {
tableLoading.value = false
})
}
const clearQuery = () => {
relationQueryFormEntity.model = ''
relationQueryFormEntity.productId = ''
relationQueryFormEntity.singleProductId = ''
}
const handleSortChange = (data) => {
if (baseTableQuery.sortBy.has(data.prop)) {
baseTableQuery.sortBy.delete(data.prop)
}
baseTableQuery.sortBy.set(data.prop, data.order == 'ascending')
search()
}
const getCurrentRow = (row) => {
recordId = row.recordId
}
const exportExcel = () => {
const params = {
model: relationQueryFormEntity.model,
productId: relationQueryFormEntity.productId,
singleProductId: relationQueryFormEntity.singleProductId
}
exportKittingBomRelationWithExcel(params).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) {
console.log(e)
ElMessage.error('下载文件失败')
}
}).catch(err => {
console.log(err)
ElMessage.error('导出失败')
})
}
const editCurrentRowStock = (row) => {
this.stockFormEntity = {
stockId: row.stockId,
locationId: row.locationId,
vehicleId: row.vehicleId,
stockStatus: row.stockStatus,
createTime: row.createTime,
lastUpdateTime: row.lastUpdateTime,
lastUpdateUser: row.lastUpdateUser,
isInventory: row.isInventory,
inventoryTaskId: row.inventoryTaskId,
noUseDays: row.noUseDays,
goodsId: row.goodsId,
goodsName: row.goodsName,
goodsStatus: row.goodsStatus,
remainNum: row.remainNum,
totalNum: row.totalNum
}
this.dialogVisible = true
}
const submitStockInfo = () => {
const request = {
stockId: this.stockFormEntity.stockId,
locationId: this.stockFormEntity.locationId,
vehicleId: this.stockFormEntity.vehicleId,
stockStatus: this.stockFormEntity.stockStatus,
goodsId: this.stockFormEntity.goodsId,
goodsStatus: this.stockFormEntity.goodsStatus,
remainNum: this.stockFormEntity.remainNum,
userName: store.getters.getUserName
}
updateStockInfo(request).then(res => {
if (res.data.code == 0) {
this.dialogVisible = false
ElMessage.success('更新库存成功')
this.search()
} else {
errorBox(res.data.message)
}
}).catch(err => {
console.log(err)
errorBox('更新库存失败')
})
}
const openUploadDialog = () => {
showRelationUploadDialog.value = true
}
</script>
<style scoped>
.content {
display: flex;
width: 100%;
}
.work-area {
width: 100%;
/* padding: 5px; */
}
.search-area {
margin: auto;
min-height: fit-content;
max-height: 40%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.table-area {
margin: auto;
min-height: fit-content;
max-height: 60%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.el-form-item {
margin: 5px 5px 5px 5px;
}
.el-form-item .el-input {
width: 196px;
}
.table-class {
margin: 5px 5px 5px 5px;
width: inherit;
}
.el-pagination {
padding-left: 5px;
}
.my-autocomplete li {
width: 196px;
line-height: normal;
padding: 7px;
}
.my-autocomplete li .name {
text-overflow: ellipsis;
overflow: hidden;
}
.my-autocomplete li .addr {
font-size: 12px;
color: #b4b4b4;
}
.my-autocomplete li .highlighted .addr {
color: #ddd;
}
.my-autocomplete li .goods_id {
color: brown;
}
.my-autocomplete li .goods_name {
color: cornflowerblue;
}
.btn-search {
height: 30px;
width: 80px;
margin: auto 5px 5px auto;
color: black;
}
</style>

View File

@ -0,0 +1,492 @@
<template>
<el-config-provider :locale="zhCn">
<el-container class="content">
<div class="work-area">
<fieldset class="search-area">
<el-form ref="searchQueryFormRef" :model="searchQueryFormEntity" :label-position="labelPosition"
label-width="158px" style="max-width: 100%" status-icon>
<div style="display: flex;justify-content: space-between;">
<el-row>
<el-form-item label="锁定状态">
<el-select-v2 style="width: 196px;" v-model="searchQueryFormEntity.isLock" placeholder="锁定状态"
:options="addAllOptionOfOptions(lockOptions)"
@change="search()"></el-select-v2>
</el-form-item>
<el-form-item label="占用状态">
<el-select-v2 style="width: 196px;" v-model="searchQueryFormEntity.isOccupy" placeholder="占用状态"
:options="addAllOptionOfOptions(occupyOptions)"
@change="search()"></el-select-v2>
</el-form-item>
<el-form-item label="库位号">
<el-input v-model="searchQueryFormEntity.locationId" @keyup.enter="search()" clearable/>
</el-form-item>
<el-form-item label="箱号">
<el-input v-model="searchQueryFormEntity.vehicleId" @keyup.enter="search()" clearable/>
</el-form-item>
</el-row>
<div style="align-content: center;">
<el-row>
<el-button type="primary" class="btn-search" @click="search()">查询</el-button>
<el-button type="warning" class="btn-search" @click="clearQuery()">清除输入</el-button>
</el-row>
<el-row>
<el-button type="success"
style="height: 30px; width: 80px; margin: auto 5px 5px auto; color: black;"
@click="exportExcel()">导出excel</el-button>
</el-row>
</div>
</div>
</el-form>
</fieldset>
<div class="table-area">
<el-table :data="tableData" stripe border v-loading="tableLoading" class="table-class"
:max-height="maxHeight" highlight-current-row @row-click="getCurrentRow"
:header-cell-style="{ 'text-align': 'center' }" :cell-style="{ 'text-align': 'center' }"
@sort-change="handleSortChange">
<el-table-column width="65px" fixed="left">
<template v-slot="scope">
<el-radio :label="scope.row.locationId" v-model="locationId">&nbsp;</el-radio>
</template>
</el-table-column>
<el-table-column prop="locationId" label="库位号" fixed="left" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="vehicleId" label="箱号" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="isLock" label="锁定状态" min-width="120px" :formatter="isLockFormat"
sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="isOccupy" label="占用状态" :formatter="isOccupyFormat"
min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="equipmentId" label="设备号" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="tunnelId" label="巷道号" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="lRow" label="排" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="lCol" label="列"
min-width="120px" sortable="custom" show-overflow-tooltip/>
<el-table-column prop="lLayer" label="层" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="lDepth" label="深度" min-width="120px"
sortable="custom" show-overflow-tooltip/>
<el-table-column prop="subArea" label="子区域" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<!-- <el-table-column fixed="right" label="操作" width="170px">
<template v-slot="scope">
<div style="display: inline-block; align-content: center;">
<el-button type="primary"
@click="editCurrentRowFormEntity(scope.row)">编辑</el-button>
</div>
</template>
</el-table-column> -->
</el-table>
<br/>
<el-pagination v-model:current-page="baseTableQuery.currentPage"
v-model:page-size="baseTableQuery.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="baseTableQuery.total"/>
</div>
<el-dialog v-model="rowEditFlag" title="工作信息" width="40%" draggable :show-close="false">
<el-form ref="rowEditFormRef" :model="rowFormEntity" :label-position="labelPosition"
label-width="100px" style="max-width: 100%" status-icon>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="工作编号">
<el-input v-model="rowFormEntity.workIndex" disabled/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="工单号">
<el-input v-model="rowFormEntity.workOrder" disabled/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="总成号">
<el-input v-model="rowFormEntity.productId" disabled/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="成品号">
<el-input v-model="rowFormEntity.singleProductId" disabled/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="料盒号">
<el-input v-model="rowFormEntity.boxNo" disabled/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="料号">
<el-input v-model="rowFormEntity.goodsId" disabled/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="需求数量">
<el-input-number v-model.number="rowFormEntity.needNum" controls-position="right"
:min="0" disabled/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="已完成数量">
<el-input-number v-model.number="rowFormEntity.finishNum" controls-position="right"
:min="0" :max="rowFormEntity.needNum" clearable/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="已分配数量">
<el-input-number v-model.number="rowFormEntity.distributeNum"
controls-position="right" :min="0" :max="rowFormEntity.needNum" clearable/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="工作状态">
<el-select-v2 v-model="rowFormEntity.workStatus" placeholder="请选择工作状态"
:options="workStatusOptions"></el-select-v2>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="缺料状态">
<el-select-v2 v-model="rowFormEntity.lackStatus" placeholder="请选择缺料状态"
:options="lackStatusOptions"></el-select-v2>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="rowEditFlag = false">取消</el-button>
<el-button type="success" @click="submitUpdateRow(rowFormEntity)">
确定
</el-button>
</span>
</template>
</el-dialog>
</div>
</el-container>
</el-config-provider>
</template>
<script setup>
import store from '@/store'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import {dateFormatter, timeFormatter} from '@/utils/formatter.js'
import {ref, reactive, onMounted, nextTick, onBeforeUnmount} from 'vue'
import {ElMessage} from 'element-plus'
import {genTableRequest, addAllOptionOfOptions} from '@/utils/generator.js'
import {labelPosition} from '@/constant/form.js'
import {loading} from '@/utils/loading'
import {queryLocationsByPage} from "@/api/location";
import {lockOptions, occupyOptions} from "@/constant/options";
import {exportLocationDetailExcel} from "@/api/excel";
/**
* 常量定义
*/
const STAND_ID = store.getters.getStandId
const USER_NAME = store.getters.getUserName
/**
* 变量定义
*/
let maxHeight = ref(window.innerHeight * 0.55)
let tableLoading = ref(false)
let tableData = ref([])
let baseTableQuery = reactive({
currentPage: 1,
pageSize: 10,
total: 0,
sortBy: new Map([['lDepth', true], ['lLayer', true], ['lCol', true], ['lRow', true]]),//
standId: STAND_ID,
userName: USER_NAME
})
let searchQueryFormEntity = reactive({
locationId: '',
vehicleId: '',
isLock: -99,
isOccupy: -99
})
let searchQueryFormRef = ref()
let rowEditFlag = ref(false)
let locationId = ''
let rowEditFormRef = ref()
let rowFormEntity = reactive({})
/**
* 系统方法
*/
onMounted(() => {
nextTick(() => {
window.addEventListener('resize', resizeHeight)
search()
})
})
onBeforeUnmount(() => {
nextTick(() => {
window.removeEventListener('resize', resizeHeight)
})
})
const resizeHeight = () => {
maxHeight.value = window.innerHeight * 0.55
}
/**
* 自定义方法
*/
//
const search = () => {
tableLoading.value = true
let request = genTableRequest(baseTableQuery)
//
request.locationId = searchQueryFormEntity.locationId.trim()
request.vehicleId = searchQueryFormEntity.vehicleId.trim()
request.isLock = searchQueryFormEntity.isLock === -99 ? null : searchQueryFormEntity.isLock
request.isOccupy = searchQueryFormEntity.isOccupy === -99 ? null : searchQueryFormEntity.isOccupy
queryLocationsByPage(request).then((res) => {
const response = res.data
if (response.code === 0) {
const data = response.data
if (data != null) {
tableData.value = data.lists
baseTableQuery.total = data.total
} else {
tableData.value = []
baseTableQuery.total = 0
}
} else {
ElMessage.error(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('查询数据异常。')
}).finally(() => {
tableLoading.value = false
})
}
const clearQuery = () => {
searchQueryFormEntity.locationId = ''
searchQueryFormEntity.vehicleId = ''
}
const handleSortChange = (data) => {
if (baseTableQuery.sortBy.has(data.prop)) {
baseTableQuery.sortBy.delete(data.prop)
}
baseTableQuery.sortBy.set(data.prop, data.order.toLowerCase() === 'ascending')
search()
}
const getCurrentRow = (row) => {
locationId = row.locationId
}
const timeFormat = (row, column, cellValue, index) => {
return timeFormatter(cellValue)
}
const isLockFormat = (row, column, cellValue, index) => {
return cellValue === 1 ? '已锁定' : '未锁定'
}
const isOccupyFormat = (row, column, cellValue, index) => {
return cellValue === 1 ? '占用' : '空闲'
}
//
const editCurrentRowFormEntity = (row) => {
// form
rowFormEntity.workIndex = row.workIndex
rowFormEntity.workOrder = row.workOrder
rowFormEntity.productId = row.productId
rowFormEntity.singleProductId = row.singleProductId
rowFormEntity.boxNo = row.boxNo
rowFormEntity.goodsId = row.goodsId
rowFormEntity.needNum = row.needNum
rowFormEntity.distributeNum = row.distributeNum
rowFormEntity.finishNum = row.finishNum
rowFormEntity.workStatus = row.workStatus
rowFormEntity.lackStatus = row.lackStatus
//
rowEditFlag.value = true
}
//
const closeLackWork = (row) => {
const request = {
workIndex: row.workIndex,
standId: STAND_ID,
userName: USER_NAME
}
loading.open('关闭中...')
closeCurrentWorks(request).then(res => {
const response = res.data
if (response.code == 0) {
ElMessage.success(response.message)
search()
} else {
ElMessage.error(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('请求异常。')
}).finally(() => {
loading.close()
})
}
//
const submitUpdateRow = (rowFormEntity) => {
const request = {
workIndex: rowFormEntity.workIndex,
distributeNum: rowFormEntity.distributeNum,
finishNum: rowFormEntity.finishNum,
workStatus: rowFormEntity.workStatus,
lackStatus: rowFormEntity.lackStatus,
standId: STAND_ID,
userName: USER_NAME
}
loading.open('更新中...')
updateKateWorks(request).then(res => {
if (res.data.code == 0) {
ElMessage.success('更新数据成功。')
rowEditFlag.value = false
search()
} else {
ElMessage.error('更新数据失败。')
}
}).catch(err => {
console.log(err)
ElMessage.error('更新数据异常。')
}).finally(() => {
loading.close()
})
}
const exportExcel = () => {
const params = {
standId: STAND_ID,
userName: USER_NAME
}
exportLocationDetailExcel(params).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) {
console.log(e)
ElMessage.error('下载文件失败')
}
}).catch(err => {
console.log(err)
ElMessage.error('导出失败')
})
}
</script>
<style scoped>
.content {
display: flex;
width: 100%;
}
.work-area {
width: 100%;
/* padding: 5px; */
}
.search-area {
margin: auto;
min-height: fit-content;
max-height: 40%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.table-area {
margin: auto;
min-height: fit-content;
max-height: 60%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.el-form-item {
margin: 5px 5px 5px 5px;
}
.el-form-item .el-input {
width: 196px;
}
.el-form-item .el-input-number {
width: 196px;
}
.el-form-item .el-select-v2 {
width: 196px;
}
.table-class {
margin: 5px 5px 5px 5px;
width: inherit;
}
.el-pagination {
padding-left: 5px;
}
.my-autocomplete li {
width: 196px;
line-height: normal;
padding: 7px;
}
.my-autocomplete li .name {
text-overflow: ellipsis;
overflow: hidden;
}
.my-autocomplete li .addr {
font-size: 12px;
color: #b4b4b4;
}
.my-autocomplete li .highlighted .addr {
color: #ddd;
}
.my-autocomplete li .goods_id {
color: brown;
}
.my-autocomplete li .goods_name {
color: cornflowerblue;
}
.btn-search {
height: 30px;
width: 80px;
margin: auto 5px 5px auto;
color: black;
}
</style>

View File

@ -0,0 +1,346 @@
<template>
<el-config-provider :locale="zhCn">
<el-container class="content">
<div class="work-area">
<fieldset class="search-area">
<el-form ref="searchQueryFormRef" :model="searchQueryFormEntity" :label-position="labelPosition"
label-width="158px" style="max-width: 100%" status-icon>
<div style="display: flex;justify-content: space-between;">
<el-row>
<el-form-item label="箱号">
<el-input v-model="searchQueryFormEntity.vehicleId" @keyup.enter="search()" clearable/>
</el-form-item>
<el-form-item label="料号">
<el-input v-model="searchQueryFormEntity.goodsId" @keyup.enter="search()" clearable/>
</el-form-item>
<el-form-item label="创建时间from">
<el-date-picker v-model="searchQueryFormEntity.fromTime" type="datetime"
placeholder="请选择from时间" :shortcuts="shortcuts"
style="width: 196px;" clearable/>
</el-form-item>
<el-form-item label="创建时间to">
<el-date-picker v-model="searchQueryFormEntity.toTime" type="datetime"
placeholder="请选择to时间" :shortcuts="shortcuts"
style="width: 196px;" clearable/>
</el-form-item>
</el-row>
<div style="align-content: center;">
<el-row>
<el-button type="primary" class="btn-search" @click="search()">查询</el-button>
<el-button type="warning" class="btn-search" @click="clearQuery()">清除输入</el-button>
</el-row>
<el-row>
<el-button type="success" class="btn-search"
@click="exportExcel()">导出excel
</el-button>
</el-row>
</div>
</div>
</el-form>
</fieldset>
<div class="table-area">
<el-table :data="tableData" stripe border v-loading="tableLoading" class="table-class"
:max-height="maxHeight" highlight-current-row @row-click="getCurrentRow"
:header-cell-style="{ 'text-align': 'center' }" :cell-style="{ 'text-align': 'center' }"
@sort-change="handleSortChange">
<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="taskId" label="任务号" fixed="left" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="taskType" label="任务类型" :formatter="taskTypeFormat" min-width="120px"
sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="taskStatus" label="任务状态" :formatter="taskStatusFormat" min-width="120px"
sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="taskPriority" label="优先级" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="vehicleId" label="箱号" fixed="left" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="goodsId" label="料号" min-width="120px" fixed="left" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="goodsDesc" label="物料描述"
min-width="120px" sortable="custom" show-overflow-tooltip/>
<el-table-column prop="opNum" label="操作数量" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="stockNum" label="库存数量" min-width="120px"
sortable="custom" show-overflow-tooltip/>
<el-table-column prop="origin" label="起点" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="destination" label="终点" min-width="120px"
sortable="custom" show-overflow-tooltip/>
<el-table-column prop="wcsTaskId" label="wcs任务号" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="createTime" label="创建时间" :formatter="timeFormat" fixed="right" min-width="120px"
sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="finishTime" label="完成时间" :formatter="timeFormat" fixed="right" min-width="120px"
sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="opUser" label="操作用户" min-width="120px"
sortable="custom" show-overflow-tooltip/>
<el-table-column prop="remark" label="备注" min-width="120px"
sortable="custom" show-overflow-tooltip/>
<el-table-column prop="callStand" label="呼叫站台" min-width="120px"
sortable="custom" show-overflow-tooltip/>
</el-table>
<br/>
<el-pagination v-model:current-page="baseTableQuery.currentPage"
v-model:page-size="baseTableQuery.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="baseTableQuery.total"/>
</div>
</div>
</el-container>
</el-config-provider>
</template>
<script setup>
import store from '@/store'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import {queryOutTaskRecordByPage} from '@/api/taskQuery.js'
import {exportOutTaskRecordExcel} from "@/api/excel"
import {timeFormatter, wmsTaskTypeFormatter, wmsTaskStatusFormatter, dateFormatter} from '@/utils/formatter.js'
import {ref, reactive, onMounted, nextTick, onBeforeUnmount} from 'vue'
import {ElMessage} from 'element-plus'
import {genTableRequest} from '@/utils/generator.js'
import {labelPosition, shortcuts} from '@/constant/form.js'
/**
* 常量定义
*/
const STAND_ID = store.getters.getStandId
const USER_NAME = store.getters.getUserName
/**
* 变量定义
*/
let maxHeight = ref(window.innerHeight * 0.55)
let tableLoading = ref(false)
let tableData = ref([])
let baseTableQuery = reactive({
currentPage: 1,
pageSize: 10,
total: 0,
sortBy: new Map([['createTime', false]]),//
standId: STAND_ID,
userName: USER_NAME
})
let searchQueryFormEntity = reactive({
vehicleId: '',
goodsId: '',
fromTime: null,
toTime: null
})
let searchQueryFormRef = ref()
let taskId = ''
/**
* 系统方法
*/
onMounted(() => {
nextTick(() => {
window.addEventListener('resize', resizeHeight)
search()
})
})
onBeforeUnmount(() => {
nextTick(() => {
window.removeEventListener('resize', resizeHeight)
})
})
const resizeHeight = () => {
maxHeight.value = window.innerHeight * 0.55
}
/**
* 自定义方法
*/
//
const search = () => {
tableLoading.value = true
let request = genTableRequest(baseTableQuery)
//
request.vehicleId = searchQueryFormEntity.vehicleId.trim()
request.goodsId = searchQueryFormEntity.goodsId.trim()
request.fromTime = searchQueryFormEntity.fromTime == null ? null : timeFormatter(searchQueryFormEntity.fromTime)
request.toTime = searchQueryFormEntity.toTime == null ? null : timeFormatter(searchQueryFormEntity.toTime)
queryOutTaskRecordByPage(request).then((res) => {
const response = res.data
if (response.code === 0) {
const data = response.data
if (data != null) {
tableData.value = data.lists
baseTableQuery.total = data.total
} else {
tableData.value = []
baseTableQuery.total = 0
}
} else {
ElMessage.error(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('查询数据异常。')
}).finally(() => {
tableLoading.value = false
})
}
const clearQuery = () => {
searchQueryFormEntity.vehicleId = ''
searchQueryFormEntity.goodsId = ''
searchQueryFormEntity.fromTime = null
searchQueryFormEntity.toTime = null
}
const handleSortChange = (data) => {
if (baseTableQuery.sortBy.has(data.prop)) {
baseTableQuery.sortBy.delete(data.prop)
}
baseTableQuery.sortBy.set(data.prop, data.order == 'ascending')
search()
}
const getCurrentRow = (row) => {
taskId = row.taskId
}
const timeFormat = (row, column, cellValue, index) => {
return timeFormatter(cellValue)
}
const taskTypeFormat = (row, column, cellValue, index) => {
return wmsTaskTypeFormatter(cellValue)
}
const taskStatusFormat = (row, column, cellValue, index) => {
return wmsTaskStatusFormatter(cellValue)
}
const exportExcel = () => {
const params = {
goodsId: searchQueryFormEntity.goodsId,
vehicleId: searchQueryFormEntity.vehicleId,
fromTime: searchQueryFormEntity.fromTime == null ? null : timeFormatter(searchQueryFormEntity.fromTime),
toTime: searchQueryFormEntity.toTime == null ? null : timeFormatter(searchQueryFormEntity.toTime),
userName: USER_NAME
}
exportOutTaskRecordExcel(params).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) {
console.log(e)
ElMessage.error('下载文件失败')
}
}).catch(err => {
console.log(err)
ElMessage.error('导出失败')
})
}
</script>
<style scoped>
.content {
display: flex;
width: 100%;
}
.work-area {
width: 100%;
/* padding: 5px; */
}
.search-area {
margin: auto;
min-height: fit-content;
max-height: 40%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.table-area {
margin: auto;
min-height: fit-content;
max-height: 60%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.el-form-item {
margin: 5px 5px 5px 5px;
}
.el-form-item .el-input {
width: 196px;
}
.el-form-item .el-input-number {
width: 196px;
}
.el-form-item .el-select-v2 {
width: 196px;
}
.table-class {
margin: 5px 5px 5px 5px;
width: inherit;
}
.el-pagination {
padding-left: 5px;
}
.my-autocomplete li {
width: 196px;
line-height: normal;
padding: 7px;
}
.my-autocomplete li .name {
text-overflow: ellipsis;
overflow: hidden;
}
.my-autocomplete li .addr {
font-size: 12px;
color: #b4b4b4;
}
.my-autocomplete li .highlighted .addr {
color: #ddd;
}
.my-autocomplete li .goods_id {
color: brown;
}
.my-autocomplete li .goods_name {
color: cornflowerblue;
}
.btn-search {
height: 30px;
width: 80px;
margin: auto 5px 5px auto;
color: black;
}
</style>

View File

@ -0,0 +1,450 @@
<template>
<el-config-provider :locale="zhCn">
<el-container class="content">
<fieldset class="input-area">
<legend style="font-size: 30px;">PDA拣货系统</legend>
<el-form :model="bindingData" :label-position="labelPosition"
label-width="100px" style="max-width: 100%" :rules="rules" status-icon size="large">
<div class="table-container">
<el-row>
<el-col :span="22" :offset="1">
<el-form-item label="箱号:" required>
<el-input class="form-input large-center-input" v-model="bindingData.sourceBox" @keyup.enter="handleSourceBoxEnter" clearable ref="sourceBoxInput"/>
</el-form-item>
</el-col>
<el-col :span="22" :offset="1">
<el-form-item label="物料号:" required>
<el-input class="form-input large-center-input" v-model="bindingData.goodsId" clearable readonly/>
</el-form-item>
</el-col>
<el-col :span="22" :offset="1">
<el-form-item label="本次实际拣选:" required>
<el-input class="form-input large-center-input" v-model="bindingData.planPickQty" clearable/>
</el-form-item>
</el-col>
<el-col :span="22" :offset="1">
<el-form-item label="实际剩余数量:" required>
<el-input class="form-input large-center-input" v-model="bindingData.realRemainQty" clearable/>
</el-form-item>
</el-col>
<el-col :span="22" :offset="1">
<el-form-item label="目标箱号:" required>
<el-input class="form-input large-center-input" v-model="bindingData.containerNo" @keyup.enter="transferBox" clearable ref="destinationBoxInput"/>
</el-form-item>
</el-col>
</el-row>
</div>
<br>
<br>
<el-row :gutter="15" class="btn-area">
<el-col :span="8">
<el-form-item>
<el-button type="warning" round @click="resetInput" class="action-button">重置数据</el-button>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item>
<el-button type="primary" round @click="queryInventory" class="action-button">查询</el-button>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item>
<el-button
type="success"
round
@click="transferBox"
class="action-button">
确认放行
</el-button>
</el-form-item>
</el-col>
</el-row>
</el-form>
</fieldset>
<div ref="btnArea"></div>
<!-- 添加全局加载指示器 -->
<div v-if="showLoading" class="loading-overlay">
<div class="loading-spinner">
<i class="el-icon-loading"></i>
<p>处理中...</p>
</div>
</div>
</el-container>
</el-config-provider>
</template>
<script>
import store from '@/store'
import {ElMessage, ElMessageBox} from 'element-plus'
import {confirmCurrentTask, confirmCurrentTaskByPDA, getPdaData} from '@/api/task.js'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import {queryStocks} from '@/api/stock.js'
import {errorBox, warningBox} from "@/utils/myMessageBox";
import {ref} from "vue";
const USER_NAME = store.getters.getUserName
let pauseGetPickFlag = ref(false)
export default {
name: 'BoxTransfer',
data() {
return {
showLoading: false, //
userName: store.getters.getUserName,
bindingData: {
taskId: '',
outType: null,
goodsId: '',
totalNeed: null,
remainNeed: null,
planPickQty: null,
realPickQty: null,
stockId: '',
vehicleId: '',
planRemainQty: null,
realRemainQty: null,
isOut: null,
putArea: '',
warningQty: null,
containerNo: '',
standId: ''
},
transferList: [],
inventoryList: [],
labelPosition: "top",
rules: {
sourceBox: [
{ required: true, message: '请输入原始料箱编号' }
],
destinationBox: [
{ required: true, message: '请输入目的料箱编号' }
]
}
}
},
computed: {
zhCn() {
return zhCn;
}
},
mounted() {
this.$refs.sourceBoxInput.focus();
},
methods: {
handleSourceBoxEnter() {
if (this.bindingData.sourceBox) {
this.queryInventory();
//
this.$nextTick(() => {
setTimeout(() => {
this.$refs.destinationBoxInput.focus();
}, 100);
});
}
},
focusDestinationBox() {
this.$refs.destinationBoxInput.focus();
},
focusSourceBox() {
this.$refs.sourceBoxInput.focus();
},
transferBox() {
//
if (this.showLoading) {
return;
}
if (this.bindingData.sourceBox === '' || this.bindingData.containerNo === '') {
ElMessage({
message: '料箱和目的料箱都不能为空',
type: 'error',
});
return;
}
if (this.bindingData.sourceBox === this.bindingData.containerNo) {
ElMessage({
message: '原始料箱和目的料箱不能相同',
type: 'error',
});
return;
}
const request = {
taskConfirm: {
taskId: this.bindingData.taskId,
outType: this.bindingData.outType,
goodsId: this.bindingData.goodsId,
totalNeed: this.bindingData.totalNeed,
remainNeed: this.bindingData.remainNeed,
planPickQty: this.bindingData.planPickQty,
realPickQty: this.bindingData.realPickQty,
containerNo: this.bindingData.containerNo,
},
stockConfirm: {
stockId: this.bindingData.stockId,
vehicleId: this.bindingData.vehicleId,
goodsId: this.bindingData.goodsId,
planRemainQty: this.bindingData.planRemainQty,
realRemainQty: this.bindingData.realRemainQty,
isOut: this.bindingData.isOut,
putArea: this.bindingData.putArea,
},
standId: this.bindingData.standId,
userName: USER_NAME
}
ElMessageBox.confirm(
`确认将料箱 ${this.bindingData.sourceBox} 转移到 ${this.bindingData.containerNo} 吗?`,
'转移确认'
).then(() => {
//
this.showLoading = true;
confirmCurrentTask(request).then(res => {
const responseData = res.data;
if (responseData.code === 0) {
ElMessage({
message: '转移成功',
type: 'success',
});
//this.transferList.push(responseData.data());
this.resetInput();
this.focusSourceBox();
} else {
ElMessageBox.alert(`服务器返回失败:${responseData.message}`, '转移失败', {
type: 'warning',
confirmButtonText: '确定',
showClose: false
})
}
}).catch(err => {
ElMessageBox.alert(`请求服务器失败:${err}`, '转移失败', {
type: 'warning',
confirmButtonText: '确定'
})
}).finally(() => {
//
this.showLoading = false;
})
}).catch(() => {
//
})
},
resetInput() {
this.bindingData.sourceBox = '';
this.bindingData.goodsId = '';
this.bindingData.planPickQty = '';
this.bindingData.realRemainQty = '';
this.bindingData.containerNo = '';
},
//
queryInventory() {
if (!this.bindingData.sourceBox) {
ElMessage({
message: '请输入箱号进行查询',
type: 'error',
});
return;
}
//
const params = {
containerNo: this.bindingData.sourceBox
}
getPdaData(params).then(res => {
const response = res.data
if (response.code === 0) {
// data
if (response.data && Array.isArray(response.data) && response.data.length > 0) {
//
const result = response.data[0];
this.bindingData.standId = result.childStandId || ''
// taskConfirm
if (result.taskConfirm) {
this.bindingData.taskId = result.taskConfirm.taskId || ''
this.bindingData.outType = result.taskConfirm.outType
this.bindingData.goodsId = result.taskConfirm.goodsId || ''
this.bindingData.totalNeed = result.taskConfirm.totalNeed
this.bindingData.remainNeed = result.taskConfirm.remainNeed
this.bindingData.planPickQty = result.taskConfirm.planPickQty
this.bindingData.realPickQty = result.taskConfirm.realPickQty
this.bindingData.containerNo = result.taskConfirm.containerNo || '' // containerNo
}
// stockConfirm
if (result.stockConfirm) {
this.bindingData.stockId = result.stockConfirm.stockId || ''
this.bindingData.vehicleId = result.stockConfirm.vehicleId || ''
this.bindingData.planRemainQty = result.stockConfirm.planRemainQty
this.bindingData.realRemainQty = result.stockConfirm.realRemainQty
this.bindingData.isOut = result.stockConfirm.isOut
this.bindingData.putArea = result.stockConfirm.putArea || ''
this.bindingData.warningQty = result.stockConfirm.warningQty
}
console.log(this.bindingData)
} else {
ElMessage({
message: '未查询到相关数据',
type: 'warning',
});
}
} else if (response.code === 999) {
//
pauseGetPickFlag.value = true
warningBox(response.message)
}
}).catch(err => {
console.log(err)
pauseGetPickFlag.value = true
errorBox('请求错误,请检查完原因后刷新界面。')
})
},
}
}
</script>
<style scoped>
.content {
display: flex;
width: 100%;
}
.el-row {
margin: 0 0;
}
:deep(.el-form-item__label) {
font-size: 10px;
padding: -5px 0;
}
:deep(.el-select-v2--large .el-select-v2__placeholder) {
font-size: 25px;
}
.el-row .el-form-item {
justify-content: center;
margin-bottom: 10px; /* 减小表单项底部间距 */
}
/* 使用深度选择器更改字体大小 */
:deep(.el-table__body .cell) {
font-size: 10px !important;
}
.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;
}
.small-label .cell {
font-size: 12px;
}
.input-area {
margin: 0;
width: 800px;
border: solid 1px;
border-radius: 10px;
box-shadow: 0 15px 10px -15px #000;
padding: 20px;
}
/* 新增样式:居中大字体输入框 */
.large-center-input {
text-align: center;
font-size: 24px !important;
}
:deep(.large-center-input .el-input__inner) {
text-align: center;
font-size: 18px !important; /* 减小字体 */
height: 35px; /* 减小高度 */
padding: 0 8px;
}
/* 增加表单标签字体大小 */
:deep(.el-form-item__label) {
font-size: 22px !important;
}
/* 按钮样式 */
.action-button {
width: 100px;
height: 40px;
font-size: 16px;
margin: auto;
}
.el-row .el-form-item .el-button {
width: 100px;
height: 40px;
font-size: 16px;
margin: auto;
}
/* 按钮区域样式 */
.btn-area {
display: flex;
justify-content: center;
align-items: center;
}
:deep(.btn-area .el-col) {
display: flex;
justify-content: center;
}
/* 全局加载动画样式 */
.loading-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 9999;
}
.loading-spinner {
text-align: center;
color: white;
}
.loading-spinner i {
font-size: 48px;
animation: rotating 1s linear infinite;
}
@keyframes rotating {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.loading-spinner p {
margin-top: 10px;
font-size: 18px;
}
</style>

View File

@ -0,0 +1,235 @@
<template>
<el-config-provider :locale="zhCn">
<el-container class="content">
<div class="work-area">
<fieldset class="search-area">
<el-form ref="searchQueryFormRef" :model="searchQueryFormEntity" :label-position="labelPosition"
label-width="158px" style="max-width: 100%" status-icon>
<div style="display: flex;justify-content: space-between;">
<el-row>
<el-form-item label="箱号">
<el-input v-model="searchQueryFormEntity.vehicleId" @keyup.enter="search()" clearable />
</el-form-item>
<el-form-item label="目标站台">
<el-input v-model="searchQueryFormEntity.standId" @keyup.enter="search()" clearable />
</el-form-item>
</el-row>
<div style="align-content: center;">
<el-row>
<el-button type="primary" class="btn-search" @click="search()">查询</el-button>
<el-button type="warning" class="btn-search" @click="clearQuery()">清除输入</el-button>
</el-row>
</div>
</div>
</el-form>
</fieldset>
<div class="table-area">
<el-table :data="tableData" stripe border v-loading="tableLoading" class="table-class"
:max-height="maxHeight" highlight-current-row @row-click="getCurrentRow"
:header-cell-style="{ 'text-align': 'center' }" :cell-style="{ 'text-align': 'center' }"
@sort-change="handleSortChange">
<el-table-column width="65px" fixed="left">
<template v-slot="scope">
<el-radio :label="scope.row.planId" v-model="planId">&nbsp;</el-radio>
</template>
</el-table-column>
<el-table-column prop="planId" label="计划号" fixed="left" min-width="120px" sortable="custom"
show-overflow-tooltip />
<el-table-column prop="vehicleId" label="箱号" fixed="left" min-width="120px" sortable="custom"
show-overflow-tooltip />
<el-table-column prop="goodsId" label="商品编号" min-width="120px" sortable="custom"
show-overflow-tooltip />
<el-table-column prop="planPickQty" label="计划拣选数量" min-width="120px" sortable="custom"
show-overflow-tooltip />
<el-table-column prop="pickType" label="拣选类型" min-width="120px" sortable="custom"
show-overflow-tooltip />
<el-table-column prop="workIndex" label="作业顺序" min-width="120px" sortable="custom"
show-overflow-tooltip />
<el-table-column prop="standId" label="目标站台" min-width="120px" sortable="custom"
show-overflow-tooltip />
</el-table>
<br />
<el-pagination v-model:current-page="baseTableQuery.currentPage"
v-model:page-size="baseTableQuery.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="baseTableQuery.total" />
</div>
</div>
</el-container>
</el-config-provider>
</template>
<script setup>
import store from '@/store'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import { queryPickPlansByPage } from '@/api/pickPlan.js'
import { ref, reactive, onMounted, nextTick, onBeforeUnmount } from 'vue'
import { ElMessage } from 'element-plus'
import { genTableRequest } from '@/utils/generator.js'
import { labelPosition } from '@/constant/form.js'
/**
* 常量定义
*/
const STAND_ID = store.getters.getStandId
const USER_NAME = store.getters.getUserName
/**
* 变量定义
*/
let maxHeight = ref(window.innerHeight * 0.55)
let tableLoading = ref(false)
let tableData = ref([])
let baseTableQuery = reactive({
currentPage: 1,
pageSize: 10,
total: 0,
sortBy: new Map([['planId', true]]),
standId: STAND_ID,
userName: USER_NAME
})
let searchQueryFormEntity = reactive({
vehicleId: '',
standId: ''
})
let searchQueryFormRef = ref()
let planId = ref('')
/**
* 系统方法
*/
onMounted(() => {
nextTick(() => {
window.addEventListener('resize', resizeHeight)
search()
})
})
onBeforeUnmount(() => {
nextTick(() => {
window.removeEventListener('resize', resizeHeight)
})
})
const resizeHeight = () => {
maxHeight.value = window.innerHeight * 0.55
}
/**
* 自定义方法
*/
//
const search = () => {
tableLoading.value = true
let request = genTableRequest(baseTableQuery)
//
request.vehicleId = searchQueryFormEntity.vehicleId.trim()
request.standId = searchQueryFormEntity.standId.trim()
queryPickPlansByPage(request).then((res) => {
const response = res.data
if (response.code === 0) {
const data = response.data
if (data != null) {
// 使
tableData.value = data.lists
baseTableQuery.total = data.total
} else {
tableData.value = []
baseTableQuery.total = 0
}
} else {
ElMessage.error(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('查询数据异常。')
}).finally(() => {
tableLoading.value = false
})
}
const clearQuery = () => {
searchQueryFormEntity.vehicleId = ''
searchQueryFormEntity.standId = ''
}
const handleSortChange = (data) => {
if (baseTableQuery.sortBy.has(data.prop)) {
baseTableQuery.sortBy.delete(data.prop)
}
baseTableQuery.sortBy.set(data.prop, data.order.toLowerCase() === 'ascending')
search()
}
const getCurrentRow = (row) => {
planId.value = row.planId
}
</script>
<style scoped>
.content {
display: flex;
width: 100%;
}
.work-area {
width: 100%;
/* padding: 5px; */
}
.search-area {
margin: auto;
min-height: fit-content;
max-height: 40%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.table-area {
margin: auto;
min-height: fit-content;
max-height: 60%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.el-form-item {
margin: 5px 5px 5px 5px;
}
.el-form-item .el-input {
width: 196px;
}
.el-form-item .el-input-number {
width: 196px;
}
.table-class {
margin: 5px 5px 5px 5px;
width: inherit;
}
.el-pagination {
padding-left: 5px;
}
.btn-search {
height: 30px;
width: 80px;
margin: auto 5px 5px auto;
color: black;
}
</style>

View File

@ -0,0 +1,278 @@
<template>
<el-config-provider :locale="zhCn">
<el-container class="content">
<div class="work-area">
<fieldset class="search-area">
<el-form ref="searchQueryFormRef" :model="searchQueryFormEntity" :label-position="labelPosition"
label-width="158px" style="max-width: 100%" status-icon>
<div style="display: flex;justify-content: space-between;">
<el-row>
<el-form-item label="任务状态">
<el-select-v2 style="width: 196px" v-model="searchQueryFormEntity.pickStatus" placeholder="任务状态"
:options="addAllOptionOfOptions(pickingTaskStatusOptions)"
@change="search()"></el-select-v2>
</el-form-item>
<el-form-item label="箱号">
<el-input v-model="searchQueryFormEntity.vehicleId" @keyup.enter="search()" clearable />
</el-form-item>
<el-form-item label="拣选站台">
<el-input v-model="searchQueryFormEntity.pickStand" @keyup.enter="search()" clearable />
</el-form-item>
</el-row>
<div style="align-content: center;">
<el-row>
<el-button type="primary" class="btn-search" @click="search()">查询</el-button>
<el-button type="warning" class="btn-search" @click="clearQuery()">清除输入</el-button>
</el-row>
</div>
</div>
</el-form>
</fieldset>
<div class="table-area">
<el-table :data="tableData" stripe border v-loading="tableLoading" class="table-class"
:max-height="maxHeight" highlight-current-row @row-click="getCurrentRow"
:header-cell-style="{ 'text-align': 'center' }" :cell-style="{ 'text-align': 'center' }"
@sort-change="handleSortChange">
<el-table-column width="65px" fixed="left">
<template v-slot="scope">
<el-radio :label="scope.row.pickId" v-model="pickId">&nbsp;</el-radio>
</template>
</el-table-column>
<el-table-column prop="pickId" label="任务号" fixed="left" min-width="120px" sortable="custom"
show-overflow-tooltip />
<el-table-column prop="pickStatus" label="任务状态" :formatter="pickStatusFormat" fixed="right" min-width="120px" sortable="custom"
show-overflow-tooltip />
<el-table-column prop="pickStand" label="拣选站台" min-width="120px" sortable="custom"
show-overflow-tooltip />
<el-table-column prop="vehicleId" label="箱号" fixed="left" min-width="120px" sortable="custom"
show-overflow-tooltip />
<el-table-column prop="createTime" label="创建时间" :formatter="timeFormat" min-width="120px" sortable="custom"
show-overflow-tooltip />
<el-table-column prop="sendTime" label="发送时间" :formatter="timeFormat" min-width="120px" sortable="custom"
show-overflow-tooltip />
<el-table-column prop="arriveTime" label="到达时间" :formatter="timeFormat" min-width="120px" sortable="custom"
show-overflow-tooltip />
<el-table-column prop="leaveTime" label="离开时间" :formatter="timeFormat" min-width="120px" sortable="custom"
show-overflow-tooltip />
</el-table>
<br />
<el-pagination v-model:current-page="baseTableQuery.pageNo"
v-model:page-size="baseTableQuery.pageSize" :page-sizes="[10, 25, 50]" :small="false"
:disabled="false" :background="false" :default-page-size="10" @size-change="handleSizeChange"
@current-change="handleCurrentChange" layout="total, sizes, prev, pager, next, jumper"
:total="baseTableQuery.total" />
</div>
</div>
</el-container>
</el-config-provider>
</template>
<script setup>
import store from '@/store'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import { queryPickTaskBaksByPage } from '@/api/pickTaskBak.js'
import { ref, reactive, onMounted, nextTick, onBeforeUnmount } from 'vue'
import { ElMessage } from 'element-plus'
import { labelPosition } from '@/constant/form.js'
import { pickingTaskStatusOptions } from '@/constant/options.js'
import { addAllOptionOfOptions } from '@/utils/generator.js'
import { timeFormatter, pickTaskStatusFormatter } from '@/utils/formatter.js'
/**
* 常量定义
*/
const STAND_ID = store.getters.getStandId
const USER_NAME = store.getters.getUserName
/**
* 变量定义
*/
let maxHeight = ref(window.innerHeight * 0.55)
let tableLoading = ref(false)
let tableData = ref([])
let baseTableQuery = reactive({
pageNo: 1,
pageSize: 10,
total: 0,
sortBy: [{
asc: true,
column: ''
}],
standId: STAND_ID,
userName: USER_NAME
})
let searchQueryFormEntity = reactive({
vehicleId: '',
pickStand: '',
pickStatus: -99
})
let searchQueryFormRef = ref()
let pickId = ref('')
/**
* 系统方法
*/
onMounted(() => {
nextTick(() => {
window.addEventListener('resize', resizeHeight)
search()
})
})
onBeforeUnmount(() => {
nextTick(() => {
window.removeEventListener('resize', resizeHeight)
})
})
const resizeHeight = () => {
maxHeight.value = window.innerHeight * 0.55
}
/**
* 自定义方法
*/
//
const search = () => {
tableLoading.value = true
let request = {
pageNo: baseTableQuery.pageNo,
pageSize: baseTableQuery.pageSize,
sortBy: baseTableQuery.sortBy,
pickStand: searchQueryFormEntity.pickStand.trim(),
vehicleId: searchQueryFormEntity.vehicleId.trim(),
pickStatus: searchQueryFormEntity.pickStatus === -99 ? null : searchQueryFormEntity.pickStatus
}
queryPickTaskBaksByPage(request).then((res) => {
const response = res.data
if (response.code === 0) {
const data = response.data
if (data != null) {
tableData.value = data.lists
baseTableQuery.total = data.total
} else {
tableData.value = []
baseTableQuery.total = 0
}
} else {
ElMessage.error(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('查询数据异常。')
}).finally(() => {
tableLoading.value = false
})
}
const clearQuery = () => {
searchQueryFormEntity.vehicleId = ''
searchQueryFormEntity.pickStand = ''
searchQueryFormEntity.pickStatus = -99
}
const handleSortChange = (data) => {
const columnMap = {
'pickId': 'pick_id',
'pickStand': 'pick_stand',
'vehicleId': 'vehicle_id',
'pickStatus': 'pick_status',
'createTime': 'create_time',
'sendTime': 'send_time',
'arriveTime': 'arrive_time',
'leaveTime': 'leave_time'
}
baseTableQuery.sortBy[0].column = columnMap[data.prop] || data.prop
baseTableQuery.sortBy[0].asc = data.order === 'ascending'
search()
}
const handleSizeChange = (val) => {
baseTableQuery.pageSize = val
search()
}
const handleCurrentChange = (val) => {
baseTableQuery.pageNo = val
search()
}
const getCurrentRow = (row) => {
pickId.value = row.pickId
}
const timeFormat = (row, column, cellValue) => {
return timeFormatter(cellValue)
}
const pickStatusFormat = (row, column, cellValue) => {
return pickTaskStatusFormatter(cellValue)
}
</script>
<style scoped>
.content {
display: flex;
width: 100%;
}
.work-area {
width: 100%;
/* padding: 5px; */
}
.search-area {
margin: auto;
min-height: fit-content;
max-height: 40%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.table-area {
margin: auto;
min-height: fit-content;
max-height: 60%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.el-form-item {
margin: 5px 5px 5px 5px;
}
.el-form-item .el-input {
width: 196px;
}
.el-form-item .el-input-number {
width: 196px;
}
.table-class {
margin: 5px 5px 5px 5px;
width: inherit;
}
.el-pagination {
padding-left: 5px;
}
.btn-search {
height: 30px;
width: 80px;
margin: auto 5px 5px auto;
color: black;
}
</style>

View File

@ -0,0 +1,278 @@
<template>
<el-config-provider :locale="zhCn">
<el-container class="content">
<div class="work-area">
<fieldset class="search-area">
<el-form ref="searchQueryFormRef" :model="searchQueryFormEntity" :label-position="labelPosition"
label-width="158px" style="max-width: 100%" status-icon>
<div style="display: flex;justify-content: space-between;">
<el-row>
<el-form-item label="任务状态">
<el-select-v2 style="width: 196px" v-model="searchQueryFormEntity.pickStatus" placeholder="任务状态"
:options="addAllOptionOfOptions(pickingTaskStatusOptions)"
@change="search()"></el-select-v2>
</el-form-item>
<el-form-item label="箱号">
<el-input v-model="searchQueryFormEntity.vehicleId" @keyup.enter="search()" clearable />
</el-form-item>
<el-form-item label="目标站台">
<el-input v-model="searchQueryFormEntity.pickStand" @keyup.enter="search()" clearable />
</el-form-item>
</el-row>
<div style="align-content: center;">
<el-row>
<el-button type="primary" class="btn-search" @click="search()">查询</el-button>
<el-button type="warning" class="btn-search" @click="clearQuery()">清除输入</el-button>
</el-row>
</div>
</div>
</el-form>
</fieldset>
<div class="table-area">
<el-table :data="tableData" stripe border v-loading="tableLoading" class="table-class"
:max-height="maxHeight" highlight-current-row @row-click="getCurrentRow"
:header-cell-style="{ 'text-align': 'center' }" :cell-style="{ 'text-align': 'center' }"
@sort-change="handleSortChange">
<el-table-column width="65px" fixed="left">
<template v-slot="scope">
<el-radio :label="scope.row.pickId" v-model="pickId">&nbsp;</el-radio>
</template>
</el-table-column>
<el-table-column prop="pickId" label="任务号" fixed="left" min-width="120px" sortable="custom"
show-overflow-tooltip />
<el-table-column prop="pickStatus" label="任务状态" :formatter="pickStatusFormat" fixed="right" min-width="120px" sortable="custom"
show-overflow-tooltip />
<el-table-column prop="pickStand" label="目标站台" min-width="120px" sortable="custom"
show-overflow-tooltip />
<el-table-column prop="vehicleId" label="箱号" fixed="left" min-width="120px" sortable="custom"
show-overflow-tooltip />
<el-table-column prop="createTime" label="创建时间" :formatter="timeFormat" min-width="120px" sortable="custom"
show-overflow-tooltip />
<el-table-column prop="sendTime" label="发送时间" :formatter="timeFormat" min-width="120px" sortable="custom"
show-overflow-tooltip />
<el-table-column prop="arriveTime" label="到达时间" :formatter="timeFormat" min-width="120px" sortable="custom"
show-overflow-tooltip />
<el-table-column prop="leaveTime" label="离开时间" :formatter="timeFormat" min-width="120px" sortable="custom"
show-overflow-tooltip />
<!-- <el-table-column fixed="right" label="操作" width="170px">
<template v-slot="scope">
<div style="display: inline-block; align-content: center;">
<el-button type="primary"
@click="editCurrentRowFormEntity(scope.row)">编辑</el-button>
</div>
</template>
</el-table-column> -->
</el-table>
<br />
<el-pagination v-model:current-page="baseTableQuery.currentPage"
v-model:page-size="baseTableQuery.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="baseTableQuery.total" />
</div>
</div>
</el-container>
</el-config-provider>
</template>
<script setup>
import store from '@/store'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import { queryPickTasksByPage } from '@/api/taskQuery.js'
import { timeFormatter, pickTaskStatusFormatter } from '@/utils/formatter.js'
import { ref, reactive, onMounted, nextTick, onBeforeUnmount } from 'vue'
import { ElMessage } from 'element-plus'
import { genTableRequest } from '@/utils/generator.js'
import { labelPosition } from '@/constant/form.js'
import {pickingTaskStatusOptions} from '@/constant/options.js'
import { addAllOptionOfOptions } from '@/utils/generator.js'
import { loading } from '@/utils/loading'
/**
* 常量定义
*/
const STAND_ID = store.getters.getStandId
const USER_NAME = store.getters.getUserName
/**
* 变量定义
*/
let maxHeight = ref(window.innerHeight * 0.55)
let tableLoading = ref(false)
let tableData = ref([])
let baseTableQuery = reactive({
currentPage: 1,
pageSize: 10,
total: 0,
sortBy: new Map([['createTime', true]]),//
standId: STAND_ID,
userName: USER_NAME
})
let searchQueryFormEntity = reactive({
vehicleId: '',
pickStand: '',
pickStatus: -99
})
let searchQueryFormRef = ref()
let pickId = ''
/**
* 系统方法
*/
onMounted(() => {
nextTick(() => {
window.addEventListener('resize', resizeHeight)
search()
})
})
onBeforeUnmount(() => {
nextTick(() => {
window.removeEventListener('resize', resizeHeight)
})
})
const resizeHeight = () => {
maxHeight.value = window.innerHeight * 0.55
}
/**
* 自定义方法
*/
//
const search = () => {
tableLoading.value = true
let request = genTableRequest(baseTableQuery)
//
request.vehicleId = searchQueryFormEntity.vehicleId.trim()
request.pickStand = searchQueryFormEntity.pickStand.trim()
request.pickStatus = searchQueryFormEntity.pickStatus === -99 ? null : searchQueryFormEntity.pickStatus
queryPickTasksByPage(request).then((res) => {
const response = res.data
if (response.code === 0) {
const data = response.data
if (data != null) {
tableData.value = data.lists
baseTableQuery.total = data.total
} else {
tableData.value = []
baseTableQuery.total = 0
}
} else {
ElMessage.error(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('查询数据异常。')
}).finally(() => {
tableLoading.value = false
})
}
const clearQuery = () => {
searchQueryFormEntity.vehicleId = ''
searchQueryFormEntity.goodsId = ''
}
const handleSortChange = (data) => {
if (baseTableQuery.sortBy.has(data.prop)) {
baseTableQuery.sortBy.delete(data.prop)
}
baseTableQuery.sortBy.set(data.prop, data.order.toLowerCase() === 'ascending')
search()
}
const getCurrentRow = (row) => {
pickId = row.pickId
}
const timeFormat = (row, column, cellValue, index) => {
return timeFormatter(cellValue)
}
const pickStatusFormat = (row, column, cellValue, index) => {
return pickTaskStatusFormatter(cellValue)
}
</script>
<style scoped>
.content {
display: flex;
width: 100%;
}
.work-area {
width: 100%;
/* padding: 5px; */
}
.search-area {
margin: auto;
min-height: fit-content;
max-height: 40%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.table-area {
margin: auto;
min-height: fit-content;
max-height: 60%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.el-form-item {
margin: 5px 5px 5px 5px;
}
.el-form-item .el-input {
width: 196px;
}
.el-form-item .el-input-number {
width: 196px;
}
.table-class {
margin: 5px 5px 5px 5px;
width: inherit;
}
.el-pagination {
padding-left: 5px;
}
.my-autocomplete li {
width: 196px;
line-height: normal;
padding: 7px;
}
.my-autocomplete li .name {
text-overflow: ellipsis;
overflow: hidden;
}
.my-autocomplete li .addr {
font-size: 12px;
color: #b4b4b4;
}
.my-autocomplete li .highlighted .addr {
color: #ddd;
}
.my-autocomplete li .goods_id {
color: brown;
}
.my-autocomplete li .goods_name {
color: cornflowerblue;
}
.btn-search {
height: 30px;
width: 80px;
margin: auto 5px 5px auto;
color: black;
}
</style>

View File

@ -0,0 +1,388 @@
<template>
<div style="margin-bottom: 10px; height: 100%; padding-left: 1%; padding-right: 1%;">
<el-config-provider :locale="zhCn">
<div style="display: flex;justify-content: space-between;">
<el-row>
<el-input v-model="roleNameQuery" style="width: 216px; margin-right: 10px;" placeholder="角色名"
:suffix-icon="Search" />
<el-button type="primary" @click="search()">搜索</el-button>
<el-button type="warning" @click="reset()">重置</el-button>
</el-row>
<el-row>
<el-button type="success" @click="openAddRoleDialog()">新增角色</el-button>
</el-row>
</div>
<br />
<el-table :data="roleList" stripe border v-loading="loading" class="table-class" highlight-current-row
max-height="650px" @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.roleId" v-model="roleId">&nbsp;</el-radio>
</template>
</el-table-column>
<el-table-column prop="roleId" label="id" fixed="left" min-width="120px" show-overflow-tooltip />
<el-table-column prop="roleName" label="角色名" min-width="120px" show-overflow-tooltip />
<el-table-column fixed="right" label="操作" width="216px">
<template v-slot="scope">
<div style="display: flex;justify-content: space-between;">
<el-button plain type="primary" @click="editCurrentRow(scope.row)">编辑角色</el-button>
<el-button plain type="danger" @click="deleteCurrentRow(scope.row)">删除角色</el-button>
</div>
</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">
<div
style="max-width: 100%; max-height: 350px; overflow: auto; display: flex; justify-content: center;">
<el-form ref="roleFormRef" :model="roleFormEntity" :label-position="labelPosition"
label-width="100px" style="width: 95%;" :rules="rules" status-icon>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="角色id" prop="roleId">
<el-input v-model="roleFormEntity.roleId" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="角色名" prop="roleName">
<el-input v-model="roleFormEntity.roleName" clearable />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="权限" prop="permission">
<el-tree ref="permissionRef" style="max-width: 600px"
:data="roleFormEntity.permissionTreeData" show-checkbox default-expand-all
node-key="id" highlight-current :props="defaultProps" />
</el-form-item></el-col>
</el-row>
</el-form>
</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitInfo(roleFormEntity)">
确认更新
</el-button>
</span>
</template>
</el-dialog>
<el-dialog v-model="addRoleDialogVisible" title="添加角色信息" width="40%" draggable :show-close="false">
<div
style="max-width: 100%; max-height: 350px; overflow: auto; display: flex; justify-content: center;">
<el-form ref="addRoleFormRef" :model="addRoleFormEntity" :label-position="labelPosition"
label-width="100px" style="width: 95%;" :rules="rules" status-icon>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="角色id" prop="roleId">
<el-input v-model="addRoleFormEntity.roleId" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="角色名" prop="roleName">
<el-input v-model="addRoleFormEntity.roleName" clearable />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="权限" prop="permission">
<el-tree ref="addRolePermissionRef" style="max-width: 600px"
:data="addRoleFormEntity.permissionTreeData" show-checkbox default-expand-all
node-key="id" highlight-current :props="defaultProps" />
</el-form-item></el-col>
</el-row>
</el-form>
</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="addRoleDialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitAddRole(addRoleFormEntity)">
确认添加
</el-button>
</span>
</template>
</el-dialog>
</el-config-provider>
</div>
</template>
<script setup>
import store from '@/store'
import { getRoleList, getPermissionList, updateRoleInfo, deleteRoleInfo, addRoleInfo } from '@/api/user.js'
import { errorBox } from '@/utils/myMessageBox.js'
import { ElMessageBox, ElMessage } from 'element-plus'
import { ref, reactive } from 'vue'
import { dateFormatter, timeFormatter } from '@/utils/formatter.js'
import { Search } from '@element-plus/icons-vue'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
</script>
<script>
export default {
name: 'role_permission',
data() {
return {
roleList: [],
currentPage: 1,
pageSize: 10,
total: 0,
roleNameQuery: '',
loading: true,
dialogVisible: false,
roleId: '',
roleFormEntity: reactive({}),
roleFormRef: ref(),
labelPosition: 'top',
rules: reactive({}),
defaultProps: {
children: 'children',
label: 'label'
},
addRoleDialogVisible: false,
addRoleFormEntity: reactive({}),
addRoleFormRef: ref(),
}
},
mounted() {
this.search()
},
methods: {
search() {
this.loading = true
const request = {
pageNo: this.currentPage,
pageSize: this.pageSize,
userName: store.getters.getUserName,
roleId: store.getters.getUser.roleId,
roleName: this.roleNameQuery.trim()
}
getRoleList(request).then(res => {
const tableResponse = res.data
if (tableResponse.code == 0) {
this.roleList = tableResponse.returnData.lists
this.total = tableResponse.returnData.total
} else {
errorBox(tableResponse.message)
}
}).catch(err => {
console.log(err)
errorBox('查询角色列表错误')
})
this.loading = false
},
dateFormat: (row, column, cellValue, index) => {
return dateFormatter(cellValue)
},
timeFormat: (row, column, cellValue, index) => {
return timeFormatter(cellValue)
},
reset() {
this.standIdQuery = ''
this.standTypeQuery = -99
this.search()
},
editCurrentRow(row) {
this.roleId = row.roleId
if (store.getters.getUser.roleId != 1) {
errorBox("操作人必须是管理员级别。")
return
}
//
this.loading = true
const request = {
roleId1: store.getters.getUser.roleId,
roleId2: row.roleId,
userName: store.getters.getUserName
}
getPermissionList(request).then(res => {
const response = res.data
if (response.code == 0) {
this.roleFormEntity = {
roleId: row.roleId,
roleName: row.roleName,
permissionTreeData: response.returnData.menu
}
//
this.$refs.permissionRef.setCheckedKeys(response.returnData.menuIds, false)
} else {
errorBox(response.message)
this.dialogVisible = false
}
}).catch(err => {
console.log(err)
errorBox('查询权限列表错误')
this.dialogVisible = false
})
this.loading = false
this.dialogVisible = true
},
openAddRoleDialog() {
if (store.getters.getUser.roleId != 1) {
errorBox("操作人必须是管理员级别。")
return
}
//
this.loading = true
const request = {
roleId1: store.getters.getUser.roleId,
roleId2: null,
userName: store.getters.getUserName
}
getPermissionList(request).then(res => {
const response = res.data
if (response.code == 0) {
this.addRoleFormEntity = {
roleId: '',
roleName: '',
permissionTreeData: response.returnData.menu
}
//
this.$refs.addRolePermissionRef.setCheckedKeys([], false)
} else {
errorBox(response.message)
this.addRoleDialogVisible = false
}
}).catch(err => {
console.log(err)
errorBox('查询权限列表错误')
this.addRoleDialogVisible = false
})
this.loading = false
this.addRoleDialogVisible = true
},
submitInfo(formData) {
const params = {
roleId1: store.getters.getUser.roleId,
roleId2: formData.roleId,
role2Name: formData.roleName,
menuIds: this.$refs.permissionRef.getCheckedKeys(false),
userName: store.getters.getUserName
}
updateRoleInfo(params).then(res => {
if (res.data.code == 0) {
this.dialogVisible = false
ElMessage.success('更新角色信息成功。')
this.search()
} else {
errorBox(res.data.message)
}
}).catch(err => {
console.log(err)
errorBox('更新角色信息失败。')
})
},
submitAddRole(formData) {
const params = {
roleId1: store.getters.getUser.roleId,
roleId2: formData.roleId,
role2Name: formData.roleName,
menuIds: this.$refs.addRolePermissionRef.getCheckedKeys(false),
userName: store.getters.getUserName
}
addRoleInfo(params).then(res => {
if (res.data.code == 0) {
this.addRoleDialogVisible = false
ElMessage.success('添加角色信息成功。')
this.search()
} else {
errorBox(res.data.message)
}
}).catch(err => {
console.log(err)
errorBox('添加角色信息失败。')
})
},
deleteCurrentRow(row) {
this.roleId = row.roleId
if (store.getters.getUser.roleId != 1) {
errorBox("操作人员必须是管理员级别。")
return
}
ElMessageBox.confirm(
'该操作会从数据库中删除角色。\n是否继续',
'警告',
{
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
}
).then(() => {
const params = {
roleId1: store.getters.getUser.roleId,
roleId2: row.roleId,
userName: store.getters.getUserName
}
deleteRoleInfo(params).then(res => {
if (res.data.code == 0) {
ElMessage.success('删除角色信息成功。')
this.search()
} else {
errorBox(res.data.message)
}
}).catch(err => {
console.log(err)
errorBox('删除角色信息失败。')
})
}).catch(() => {
ElMessage.info('操作取消')
})
},
getCurrentRow(row) {
this.roleId = row.roleId
},
},
}
</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;
}
.title-area {
display: flex;
/* min-height: 10%; */
max-height: max-content;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
flex-direction: column;
padding: 10px;
}
</style>

View File

@ -0,0 +1,376 @@
<template>
<div style="margin-bottom: 10px; height: 100%; padding-left: 1%; padding-right: 1%;">
<el-config-provider :locale="zhCn">
<div style="display: flex;justify-content: space-between;">
<el-row>
<el-input v-model="userNameQuery" style="width: 216px; margin-right: 10px;" placeholder="用户名"
:suffix-icon="Search" />
<el-button type="primary" @click="search()">搜索</el-button>
<el-button type="warning" @click="reset()">重置</el-button>
</el-row>
<el-row>
<el-button type="success" @click="addOneUser()">新增用户</el-button>
</el-row>
</div>
<br />
<el-table :data="userList" stripe border v-loading="loading" class="table-class" highlight-current-row
max-height="650px" @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.userId" v-model="userId">&nbsp;</el-radio>
</template>
</el-table-column>
<el-table-column prop="userId" label="id" fixed="left" min-width="120px" show-overflow-tooltip />
<el-table-column prop="userName" label="用户名" min-width="120px" show-overflow-tooltip />
<el-table-column prop="roleId" label="角色" :formatter="roleFormat" min-width="120px"
show-overflow-tooltip />
<el-table-column prop="loginAccount" label="登录账户" min-width="120px" show-overflow-tooltip />
<el-table-column prop="addTime" label="增加时间" :formatter="timeFormat" show-overflow-tooltip
min-width="120px" />
<el-table-column prop="updateTime" label="更新时间" :formatter="timeFormat" min-width="120px"
show-overflow-tooltip />
<el-table-column prop="addUser" label="添加用户" min-width="120px" show-overflow-tooltip />
<el-table-column fixed="right" label="操作" min-width="120px">
<template v-slot="scope">
<div style="display: flex;justify-content: space-between;">
<el-button plain type="primary" @click="editCurrentRow(scope.row)">编辑</el-button>
<el-button plain type="danger" @click="deleteCurrentRow(scope.row)">删除</el-button>
</div>
</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">
<div
style="max-width: 100%; max-height: 500px; overflow: auto; display: flex; justify-content: center;">
<el-form ref="userFormRef" :model="userFormEntity" :label-position="labelPosition"
label-width="100px" style="width: 95%;" :rules="rules" status-icon>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="用户id" prop="userId">
<el-input v-model="userFormEntity.userId" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="用户名" prop="userName">
<el-input v-model="userFormEntity.userName" clearable />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="登录账户" prop="loginAccount">
<el-input v-model="userFormEntity.loginAccount" clearable />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="角色" prop="roleId">
<el-select-v2 v-model="userFormEntity.roleId" placeholder="请选择角色"
:options="roleOptions"></el-select-v2>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitInfo(userFormEntity)">
确定
</el-button>
</span>
</template>
</el-dialog>
<el-dialog v-model="addUserDialogVisible" title="添加用户信息" width="40%" draggable :show-close="false">
<div
style="max-width: 100%; max-height: 350px; overflow: auto; display: flex; justify-content: center;">
<el-form ref="addUserFormRef" :model="addUserFormEntity" :label-position="labelPosition"
label-width="100px" style="width: 95%;" :rules="rules" status-icon>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="角色" prop="roleIdUpdate">
<el-select-v2 v-model="addUserFormEntity.roleIdUpdate" placeholder="请选择角色"
:options="roleOptions"></el-select-v2>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="用户名" prop="userNameUpdate">
<el-input v-model="addUserFormEntity.userNameUpdate" clearable />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="登录账户" prop="loginAccountUpdate">
<el-input v-model="addUserFormEntity.loginAccountUpdate" clearable />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="登录密码" prop="loginPasswordUpdate">
<el-input v-model="addUserFormEntity.loginPasswordUpdate" show-password clearable />
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="addUserDialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitAddUser(addUserFormEntity)">
确认添加
</el-button>
</span>
</template>
</el-dialog>
</el-config-provider>
</div>
</template>
<script setup>
import store from '@/store'
import { getUserList, getRoleOptions, updateUserInfo, addUserInfo, deleteUserInfo } from '@/api/user.js'
import { errorBox } from '@/utils/myMessageBox.js'
import { ElMessageBox, ElMessage } from 'element-plus'
import { ref, reactive } from 'vue'
import { dateFormatter, timeFormatter } from '@/utils/formatter.js'
import { Search } from '@element-plus/icons-vue'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
</script>
<script>
export default {
name: 'role_user',
data() {
return {
userList: [],
currentPage: 1,
pageSize: 10,
total: 0,
userNameQuery: '',
loading: true,
dialogVisible: false,
userId: '',
userFormEntity: reactive({}),
userFormRef: ref(),
labelPosition: 'top',
rules: reactive({}),
roleOptions: [],
addUserDialogVisible: false,
addUserFormEntity: reactive({}),
addUserFormRef: ref(),
}
},
mounted() {
this.getRoleOptions()
this.search()
},
methods: {
getRoleOptions() {
const request = {
roleId: store.getters.getUser.roleId,
}
getRoleOptions(request).then(res => {
const tableResponse = res.data
if (tableResponse.code == 0) {
this.roleOptions = tableResponse.returnData
} else {
this.roleOptions = []
}
}).catch(err => {
console.log(err)
this.roleOptions = []
})
},
search() {
this.loading = true
const request = {
pageNo: this.currentPage,
pageSize: this.pageSize,
userName: this.userNameQuery.trim(),
roleId: store.getters.getUser.roleId,
}
getUserList(request).then(res => {
const tableResponse = res.data
if (tableResponse.code == 0) {
this.userList = tableResponse.returnData.lists
this.total = tableResponse.returnData.total
} else {
errorBox(tableResponse.message)
}
}).catch(err => {
console.log(err)
errorBox('查询用户列表错误')
})
this.loading = false
},
dateFormat: (row, column, cellValue, index) => {
return dateFormatter(cellValue)
},
timeFormat: (row, column, cellValue, index) => {
return timeFormatter(cellValue)
},
roleFormat(row, column, cellValue, index) {
const roleOptionInfo = this.roleOptions.find(item => {
return item.value == cellValue
})
return roleOptionInfo == null|undefined ? '未知角色' : roleOptionInfo.label
},
reset() {
this.userNameQuery = ''
this.search()
},
editCurrentRow(row) {
this.userId = row.userId
this.userFormEntity = {
userId: row.userId,
userName: row.userName,
loginAccount: row.loginAccount,
roleId: row.roleId,
}
this.dialogVisible = true
},
deleteCurrentRow(row) {
this.userId = row.userId
if (store.getters.getUser.roleId != 1) {
errorBox("操作人员必须是管理员级别。")
return
}
ElMessageBox.confirm(
'该操作会从数据库中删除用户。\n是否继续',
'警告',
{
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
}
).then(() => {
const params = {
userIdUpdate: row.userId,
roleId1: store.getters.getUser.roleId,
userName: store.getters.getUserName
}
deleteUserInfo(params).then(res => {
if (res.data.code == 0) {
ElMessage.success('删除用户信息成功。')
this.search()
} else {
errorBox(res.data.message)
}
}).catch(err => {
console.log(err)
errorBox('删除用户信息失败。')
})
}).catch(() => {
ElMessage.info('操作取消')
})
},
addOneUser() {
this.addUserFormEntity = {
roleIdUpdate: null,
userNameUpdate: '',
loginAccountUpdate: '',
loginPasswordUpdate: '',
}
this.addUserDialogVisible = true
},
submitInfo(formData) {
const params = {
roleIdUpdate: formData.roleId,
userIdUpdate: formData.userId,
userNameUpdate: formData.userName,
loginAccountUpdate: formData.loginAccount,
roleId1: store.getters.getUser.roleId,
userName: store.getters.getUserName
}
updateUserInfo(params).then(res => {
if (res.data.code == 0) {
this.dialogVisible = false
ElMessage.success('更新用户信息成功。')
this.search()
} else {
errorBox(res.data.message)
}
}).catch(err => {
console.log(err)
errorBox('更新用户信息失败。')
})
},
submitAddUser(formData) {
const params = {
roleIdUpdate: formData.roleIdUpdate,
userNameUpdate: formData.userNameUpdate,
loginAccountUpdate: formData.loginAccountUpdate,
loginPasswordUpdate: formData.loginPasswordUpdate,
roleId1: store.getters.getUser.roleId,
userName: store.getters.getUserName
}
addUserInfo(params).then(res => {
if (res.data.code == 0) {
this.addUserDialogVisible = false
ElMessage.success('添加用户信息成功。')
this.search()
} else {
errorBox(res.data.message)
}
}).catch(err => {
console.log(err)
errorBox('添加用户信息失败。')
})
},
getCurrentRow(row) {
this.userId = row.userId
},
},
}
</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;
}
.title-area {
display: flex;
/* min-height: 10%; */
max-height: max-content;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
flex-direction: column;
padding: 10px;
}
</style>

View File

@ -0,0 +1,121 @@
<template>
<!-- 图纸展示 -->
<div class="content">
<el-image class="image-full" :src="imageData.base64" :fit="fit">
<template #error>
<div class="error-slot">
{{ imageData.errMsg }}
</div>
</template>
</el-image>
</div>
</template>
<script setup>
//
import store from '@/store'
import { requestImageDetail } from '@/api/kateWork.js'
import { isSingleCharacter, isNumber } from '@/utils/stringUtils';
import { onBeforeUnmount, onMounted, reactive } from 'vue';
//
const USER_NAME = store.getters.getUserName
const STAND_ID = store.getters.getStandId
const fit = 'contain'
let imageData = reactive({
url: '',
base64: '',
name: '',
errMsg: ''
})
let inputStr = ''
let imageRequest = reactive({
imageId: '',
userName: USER_NAME,
standId: STAND_ID
})
//
onMounted(() => {
document.addEventListener('keydown', handleKeyDown)
})
onBeforeUnmount(() => {
document.removeEventListener('keydown', handleKeyDown)
})
//
const handleKeyDown = (event) => {
if (event.key.toLowerCase() === 'enter') {
solveInput()
} else {
if (event.key.toLowerCase() === 'backspace') {
inputStr = inputStr.substring(0, inputStr.length - 1)
} else if (isSingleCharacter(event.key) || isNumber(event.key)) {
inputStr += event.key
}
}
}
//
const solveInput = () => {
//
if (inputStr === '') {
closePreview('空输入。')
}
//
imageRequest.imageId = inputStr
//
findImage()
}
//
const findImage = () => {
if (imageRequest.imageId === '') {
closePreview('请求缺少图纸编号。')
}
requestImageDetail(imageRequest).then(res => {
const response = res.data
if (response.code === 0) {
const results = response.data
if (results === undefined || results.length !== 1) {
closePreview('无图纸或图纸歧义。')
return
}
const image = results[0]
openPreview(image)
} else {
closePreview(response.message)
}
}).catch(err => {
console.log(err)
closePreview("查询图纸失败,请检查。")
}).finally(() => {
inputStr = ''
})
}
//
const openPreview = (image) => {
imageData.url = image.imageIp + image.imagePath + image.imageName
imageData.base64 = 'data:image/png;base64,' + image.imageDetail
imageData.name = image.imageName
imageData.errMsg = ''
}
//
const closePreview = (errMsg) => {
imageData.url = ''
imageData.base64 = ''
imageData.name = ''
imageData.errMsg = errMsg
}
</script>
<style scoped>
.content {
width: 100%;
height: 100%;
}
.image-full {
width: 100%;
height: 100%;
}
.image-full .error-slot {
color: red;
font-size: 50px;
font-weight: bold;
}
</style>

View File

@ -0,0 +1,495 @@
<template>
<el-config-provider :locale="zhCn">
<el-container class="content">
<div class="work-area">
<fieldset class="search-area">
<el-form ref="searchQueryFormRef" :model="searchQueryFormEntity" :label-position="labelPosition"
label-width="158px" style="max-width: 100%" status-icon>
<div style="display: flex;justify-content: space-between;">
<el-row>
<el-form-item label="站台类型">
<el-select-v2 style="width: 196px;" v-model="searchQueryFormEntity.standType" placeholder="站台类型"
:options="addAllOptionOfOptions(standTypeOptions)"
@change="search()"></el-select-v2>
</el-form-item>
<el-form-item label="站台ID">
<el-input v-model="searchQueryFormEntity.standId" @keyup.enter="search()" clearable/>
</el-form-item>
</el-row>
<div style="align-content: center;">
<el-row>
<el-button type="primary" class="btn-search" @click="search()">查询</el-button>
<el-button type="warning" class="btn-search" @click="clearQuery()">清除输入</el-button>
</el-row>
</div>
</div>
</el-form>
</fieldset>
<div class="table-area">
<el-table :data="tableData" stripe border v-loading="tableLoading" class="table-class"
:max-height="maxHeight" highlight-current-row @row-click="getCurrentRow"
:header-cell-style="{ 'text-align': 'center' }" :cell-style="{ 'text-align': 'center' }"
@sort-change="handleSortChange">
<el-table-column width="65px" fixed="left">
<template v-slot="scope">
<el-radio :label="scope.row.standId" v-model="standId">&nbsp;</el-radio>
</template>
</el-table-column>
<el-table-column prop="standId" label="站台ID" fixed="left" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="standName" label="站台名称" min-width="150px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="standType" label="站台类型" min-width="120px" :formatter="standTypeFormat"
sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="standStatus" label="站台状态" :formatter="standStatusFormat"
min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="standIp" label="站台IP" min-width="150px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="standDesc" label="站台描述" min-width="180px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="lastUpdateTime" label="最后更新时间" min-width="180px" sortable="custom"
:formatter="timeFormat" show-overflow-tooltip/>
<el-table-column prop="lastUpdateUser" label="最后更新人" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column fixed="right" label="操作" width="170px">
<template v-slot="scope">
<div style="display: inline-block; align-content: center;">
<el-button type="primary"
@click="editCurrentRowFormEntity(scope.row)">编辑</el-button>
</div>
</template>
</el-table-column>
</el-table>
<br/>
<el-pagination v-model:current-page="baseTableQuery.currentPage"
v-model:page-size="baseTableQuery.pageSize" :page-sizes="[10, 25, 50]" :small="false"
:disabled="false" :background="false" :default-page-size="10" @size-change="handlePageSizeChange"
@current-change="processTableData" layout="total, sizes, prev, pager, next, jumper"
:total="baseTableQuery.total"/>
</div>
<el-dialog v-model="rowEditFlag" title="站台信息" width="40%" draggable :show-close="false">
<el-form ref="rowEditFormRef" :model="rowFormEntity" :label-position="labelPosition"
label-width="100px" style="max-width: 100%" status-icon>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="站台ID">
<el-input v-model="rowFormEntity.standId" disabled/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="站台名称">
<el-input v-model="rowFormEntity.standName"/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="站台类型">
<el-select-v2 v-model="rowFormEntity.standType" placeholder="请选择站台类型"
:options="standTypeOptions"></el-select-v2>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="站台状态">
<el-select-v2 v-model="rowFormEntity.standStatus" placeholder="请选择站台状态"
:options="standStatusOptions"></el-select-v2>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="站台IP">
<el-input v-model="rowFormEntity.standIp"/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="站台描述">
<el-input v-model="rowFormEntity.standDesc"/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="rowEditFlag = false">取消</el-button>
<el-button type="success" @click="submitUpdateRow(rowFormEntity)">
确定
</el-button>
</span>
</template>
</el-dialog>
</div>
</el-container>
</el-config-provider>
</template>
<script setup>
import store from '@/store'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import {timeFormatter} from '@/utils/formatter.js'
import {ref, reactive, onMounted, nextTick, onBeforeUnmount} from 'vue'
import {ElMessage} from 'element-plus'
import {genTableRequest, addAllOptionOfOptions} from '@/utils/generator.js'
import {labelPosition} from '@/constant/form.js'
import {loading} from '@/utils/loading'
import {getAllStands, updateStandInfo} from "@/api/stand";
/**
* 常量定义
*/
const STAND_ID = store.getters.getStandId
const USER_NAME = store.getters.getUserName
//
const standTypeOptions = [
{ value: 1, label: '拣选站台' },
{ value: 2, label: '入库站台' }
]
//
const standStatusOptions = [
{ value: 0, label: '可用' },
{ value: 1, label: '不可用' }
]
/**
* 变量定义
*/
let maxHeight = ref(window.innerHeight * 0.55)
let tableLoading = ref(false)
let tableData = ref([])
let allTableData = ref([]) //
let baseTableQuery = reactive({
currentPage: 1,
pageSize: 10,
total: 0,
sortBy: new Map([['standId', true]]),// ID
standId: STAND_ID,
userName: USER_NAME
})
let searchQueryFormEntity = reactive({
standId: '',
standType: -99
})
let searchQueryFormRef = ref()
let rowEditFlag = ref(false)
let standId = ''
let rowEditFormRef = ref()
let rowFormEntity = reactive({})
/**
* 系统方法
*/
onMounted(() => {
nextTick(() => {
window.addEventListener('resize', resizeHeight)
search()
})
})
onBeforeUnmount(() => {
nextTick(() => {
window.removeEventListener('resize', resizeHeight)
})
})
const resizeHeight = () => {
maxHeight.value = window.innerHeight * 0.55
}
/**
* 自定义方法
*/
//
const search = () => {
tableLoading.value = true
let request = {}
//
if (searchQueryFormEntity.standId.trim()) {
request.standId = searchQueryFormEntity.standId.trim()
}
if (searchQueryFormEntity.standType !== -99) {
request.standType = searchQueryFormEntity.standType
}
getAllStands(request).then((res) => {
const response = res.data
if (response.code === 0) {
const data = response.data
if (data != null) {
allTableData.value = data
baseTableQuery.total = data.length
//
processTableData()
} else {
allTableData.value = []
tableData.value = []
baseTableQuery.total = 0
}
} else {
ElMessage.error(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('查询数据异常。')
}).finally(() => {
tableLoading.value = false
})
}
//
const processTableData = () => {
let data = [...allTableData.value]
//
if (baseTableQuery.sortBy.size > 0) {
data = sortTableData(data, baseTableQuery.sortBy)
}
//
const startIndex = (baseTableQuery.currentPage - 1) * baseTableQuery.pageSize
const endIndex = startIndex + baseTableQuery.pageSize
tableData.value = data.slice(startIndex, endIndex)
}
//
const sortTableData = (data, sortBy) => {
if (sortBy.size === 0) {
return data
}
return data.slice().sort((a, b) => {
for (const [key, ascending] of sortBy) {
let aValue = a[key]
let bValue = b[key]
// null/undefined
if (aValue == null && bValue == null) continue
if (aValue == null) return ascending ? 1 : -1 // null
if (bValue == null) return ascending ? -1 : 1
//
if (key === 'lastUpdateTime') {
aValue = new Date(aValue).getTime()
bValue = new Date(bValue).getTime()
}
// standType, standStatus
if (typeof aValue === 'number' && typeof bValue === 'number') {
if (aValue !== bValue) {
return ascending ? aValue - bValue : bValue - aValue
}
continue
}
//
if (typeof aValue === 'string' && typeof bValue === 'string') {
aValue = aValue.toLowerCase()
bValue = bValue.toLowerCase()
}
//
aValue = String(aValue)
bValue = String(bValue)
if (aValue < bValue) {
return ascending ? -1 : 1
}
if (aValue > bValue) {
return ascending ? 1 : -1
}
}
return 0
})
}
const clearQuery = () => {
searchQueryFormEntity.standId = ''
searchQueryFormEntity.standType = -99
//
baseTableQuery.currentPage = 1
//
baseTableQuery.sortBy.clear()
baseTableQuery.sortBy.set('standId', true) // ID
search()
}
//
const handlePageSizeChange = () => {
//
baseTableQuery.currentPage = 1
processTableData()
}
const handleSortChange = (data) => {
//
console.log('handleSortChange called with:', data)
console.log('allTableData length:', allTableData.value.length)
//
baseTableQuery.sortBy.clear()
// null
if (data.order) {
const isAscending = data.order.toLowerCase() === 'ascending'
baseTableQuery.sortBy.set(data.prop, isAscending)
console.log('Setting sort:', data.prop, isAscending)
} else {
// ordernull
baseTableQuery.sortBy.set('standId', true)
console.log('Resetting to default sort: standId')
}
//
baseTableQuery.currentPage = 1
processTableData()
}
const getCurrentRow = (row) => {
standId = row.standId
}
const timeFormat = (row, column, cellValue, index) => {
return timeFormatter(cellValue)
}
const standTypeFormat = (row, column, cellValue, index) => {
const typeMap = {
1: '拣选站台',
2: '入库站台'
}
return typeMap[cellValue] || '未知'
}
const standStatusFormat = (row, column, cellValue, index) => {
return cellValue === 1 ? '可用' : '不可用'
}
//
const editCurrentRowFormEntity = (row) => {
// form
rowFormEntity.standId = row.standId
rowFormEntity.standName = row.standName
rowFormEntity.standType = row.standType
rowFormEntity.standStatus = row.standStatus
rowFormEntity.standIp = row.standIp
rowFormEntity.standDesc = row.standDesc
//
rowEditFlag.value = true
}
//
const submitUpdateRow = (rowFormEntity) => {
const request = {
standId: rowFormEntity.standId,
standName: rowFormEntity.standName,
standType: rowFormEntity.standType,
standStatus: rowFormEntity.standStatus,
standIp: rowFormEntity.standIp,
standDesc: rowFormEntity.standDesc,
userName: 'wms-web'
}
loading.open('更新中...')
updateStandInfo(request).then(res => {
if (res.data.code == 0) {
ElMessage.success('更新数据成功。')
rowEditFlag.value = false
search()
} else {
ElMessage.error('更新数据失败。')
}
}).catch(err => {
console.log(err)
ElMessage.error('更新数据异常。')
}).finally(() => {
loading.close()
})
}
</script>
<style scoped>
.content {
display: flex;
width: 100%;
}
.work-area {
width: 100%;
/* padding: 5px; */
}
.search-area {
margin: auto;
min-height: fit-content;
max-height: 40%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.table-area {
margin: auto;
min-height: fit-content;
max-height: 60%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.el-form-item {
margin: 5px 5px 5px 5px;
}
.el-form-item .el-input {
width: 196px;
}
.el-form-item .el-input-number {
width: 196px;
}
.el-form-item .el-select-v2 {
width: 196px;
}
.table-class {
margin: 5px 5px 5px 5px;
width: inherit;
}
.el-pagination {
padding-left: 5px;
}
.my-autocomplete li {
width: 196px;
line-height: normal;
padding: 7px;
}
.my-autocomplete li .name {
text-overflow: ellipsis;
overflow: hidden;
}
.my-autocomplete li .addr {
font-size: 12px;
color: #b4b4b4;
}
.my-autocomplete li .highlighted .addr {
color: #ddd;
}
.my-autocomplete li .goods_id {
color: brown;
}
.my-autocomplete li .goods_name {
color: cornflowerblue;
}
.btn-search {
height: 30px;
width: 80px;
margin: auto 5px 5px auto;
color: black;
}
</style>

View File

@ -0,0 +1,597 @@
<template>
<el-config-provider :locale="zhCn">
<el-container class="content">
<div class="work-area">
<fieldset class="search-area">
<el-form ref="stockQueryFormRef" :model="stockQuery" :label-position="labelPosition"
label-width="auto" style="max-width: 100%" status-icon>
<div style="display: flex;justify-content: space-between;">
<el-row>
<el-form-item label="箱号">
<el-input v-model="stockQuery.vehicleId" @keyup.enter="search()" clearable />
</el-form-item>
<el-form-item label="料号">
<el-input v-model="stockQuery.goodsId" @keyup.enter="search()" clearable />
<!-- <el-autocomplete v-model="stockQuery.goodsId" :fetch-suggestions="filterGoodsId"
popper-class="my-autocomplete" placeholder="料号" @select="handleSelectGoodsId"
style="width: 196px;">
<template #default="{ item }">
<div>
料号<span class="goods_id">{{ item.goodsId }}</span>
名称<span class="goods_name">{{ item.goodsDesc }}</span>
</div>
</template>
</el-autocomplete> -->
</el-form-item>
<el-form-item label="库位">
<el-input v-model="stockQuery.locationId" @keyup.enter="search()" clearable />
</el-form-item>
<el-form-item label="库存状态">
<el-select-v2 style="width: 196px" v-model="stockQuery.stockStatus" placeholder="库存状态"
:options="addAllOptionOfOptions(stockStatusOptions)"
@change="search()"></el-select-v2>
</el-form-item>
<el-form-item label="物料状态">
<el-select-v2 style="width: 196px" v-model="stockQuery.goodsStatus" placeholder="物料状态"
:options="addAllOptionOfOptions(goodsStatusOptions)"
@change="search()"></el-select-v2>
</el-form-item>
<el-form-item label="起始日期">
<el-date-picker v-model="stockQuery.fromDate" type="date" placeholder="起始日期"
:shortcuts="shortcuts" style="width: 196px;" clearable />
</el-form-item>
<el-form-item label="结束日期">
<el-date-picker v-model="stockQuery.toDate" type="date" placeholder="结束日期"
:shortcuts="shortcuts" style="width: 196px;" clearable />
</el-form-item>
</el-row>
<div style="align-content: center;">
<el-row>
<el-button type="primary"
style="height: 30px; width: 80px; margin: auto 5px 5px auto; color: black;"
@click="search()">查询库存</el-button>
<el-button type="warning"
style="height: 30px; width: 80px; margin: auto 5px 5px auto; color: black;"
@click="clearQuery()">清除输入</el-button>
</el-row>
<el-row>
<el-button type="success"
style="height: 30px; width: 80px; margin: auto 5px 5px auto; color: black;"
@click="exportExcel()">导出excel</el-button>
</el-row>
</div>
</div>
</el-form>
</fieldset>
<div class="table-area">
<el-table :data="displayStocks" stripe border v-loading="tableLoading" class="table-class"
:max-height="maxHeight" highlight-current-row @row-click="getCurrentRow" :row-style="rowStyle"
:header-cell-style="{ 'text-align': 'center' }" :cell-style="{ 'text-align': 'center' }"
@sort-change="handleSortChange">
<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="库存编号" fixed="left" min-width="120px" sortable="custom"-->
<!-- show-overflow-tooltip />-->
<el-table-column prop="vehicleId" label="箱号" fixed="left" min-width="120px" sortable="custom"
show-overflow-tooltip />
<el-table-column prop="goodsId" label="物料号" fixed="left" min-width="120px" sortable="custom"
show-overflow-tooltip />
<el-table-column prop="specialStock" label="特殊库存" min-width="120px" sortable="custom"
show-overflow-tooltip />
<el-table-column prop="specialStockNo" label="特殊库存号" min-width="120px" sortable="custom"
show-overflow-tooltip />
<el-table-column prop="specialStockItemNo" label="特殊库存item号" min-width="120px" sortable="custom"
show-overflow-tooltip />
<el-table-column prop="batchNo" label="批次号" min-width="120px" sortable="custom"
show-overflow-tooltip />
<el-table-column prop="goodsDesc" label="物料名称" min-width="120px" sortable="custom" show-overflow-tooltip />
<el-table-column prop="locationId" label="库位" :formatter="locationFormat" min-width="120px"
sortable="custom" show-overflow-tooltip />
<el-table-column prop="totalNum" label="入库数量" sortable="custom" min-width="120px" show-overflow-tooltip />
<el-table-column prop="remainNum" label="剩余可用数量" sortable="custom" min-width="120px" show-overflow-tooltip />
<el-table-column prop="realNum" label="实际剩余数量" sortable="custom" min-width="120px" show-overflow-tooltip />
<el-table-column prop="goodsStatus" label="物料状态" :formatter="goodsStatusFormat"
min-width="120px" sortable="custom" show-overflow-tooltip />
<el-table-column prop="stockStatus" label="库存状态" :formatter="stockStatusFormat" fixed="right"
min-width="120px" sortable="custom" show-overflow-tooltip />
<el-table-column prop="firstInTime" label="上架时间" sortable="custom" :formatter="timeFormat"
min-width="120px" show-overflow-tooltip />
<el-table-column prop="firstInUser" label="上架用户" min-width="120px" sortable="custom" show-overflow-tooltip />
<el-table-column prop="lastUpdateTime" label="最近更新时间" sortable="custom" :formatter="timeFormat"
min-width="140px" show-overflow-tooltip />
<el-table-column prop="lastUpdateUser" label="最近更新用户" min-width="120px" show-overflow-tooltip />
<!-- <el-table-column fixed="right" label="操作" width="120px">
<template v-slot="scope">
<el-button plain type="primary" @click="editCurrentRowStock(scope.row)">编辑</el-button>
</template>
</el-table-column> -->
</el-table>
<br />
<el-pagination v-model:current-page="baseTableQuery.currentPage"
v-model:page-size="baseTableQuery.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="baseTableQuery.total" />
</div>
<!-- <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="stockId">
<el-input v-model="stockFormEntity.stockId" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="箱号" prop="vehicleId">
<el-input v-model="stockFormEntity.vehicleId" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="料号" prop="goodsId">
<el-input v-model="stockFormEntity.goodsId" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="料名" prop="goodsName">
<el-input v-model="stockFormEntity.goodsName" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="入库数量" prop="totalNum">
<el-input-number v-model.number="stockFormEntity.totalNum" controls-position="right"
:min="0" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="剩余数量为0时删除库存" prop="remainNum">
<el-input-number v-model.number="stockFormEntity.remainNum"
controls-position="right" :min="0" :max="stockFormEntity.totalNum" clearable />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="库位" prop="locationId">
<el-input v-model="stockFormEntity.locationId" clearable />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="未使用天数" prop="noUseDays">
<el-input-number v-model.number="stockFormEntity.noUseDays"
controls-position="right" :min="0" disabled />
</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-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="盘点任务号" prop="inventoryTaskId">
<el-input v-model="stockFormEntity.inventoryTaskId" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="是否盘点" prop="isInventory">
<el-input v-model="stockFormEntity.isInventory" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="创建时间" prop="createTime">
<el-input v-model="stockFormEntity.createTime" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="最近更新时间" prop="lastUpdateTime">
<el-input v-model="stockFormEntity.lastUpdateTime" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="最近更新用户" prop="lastUpdateUser">
<el-input v-model="stockFormEntity.lastUpdateUser" disabled />
</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> -->
</div>
</el-container>
</el-config-provider>
</template>
<script setup>
import store from '@/store'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import { queryStocksByPage } from '@/api/stock.js'
import { exportStockExcel } from '@/api/excel.js'
import { dateFormatter, locationFormatter, timeFormatter, yesOrNoFormatter } from '@/utils/formatter.js'
import { ref, reactive, onMounted, nextTick, onBeforeUnmount } from 'vue'
import { ElMessage } from 'element-plus'
import { genTableRequest, addAllOptionOfOptions } from '@/utils/generator.js'
import { labelPosition, shortcuts } from '@/constant/form'
import { stockStatusOptions, goodsStatusOptions } from '@/constant/options'
/**
* 常量定义
*/
/**
* 变量定义
*/
let maxHeight = ref(window.innerHeight * 0.55)
let tableLoading = ref(false)
let displayStocks = ref([])
let baseTableQuery = reactive({
currentPage: 1,
pageSize: 10,
total: 0,
sortBy: new Map([['firstInTime', true]]),
standId: store.getters.getStandId,
userName: store.getters.getUserName
})
let stockQuery = reactive({
vehicleId: '',
goodsId: '',
locationId: '',
stockStatus: -99,
goodsStatus: -99,
fromDate: null,
toDate: null
})
let stockQueryFormRef = ref()
let goodsIdList = ref([])
let showStockEditFlag = ref(false)
let stockId = ''
let stockFormRef = ref()
let stockFormEntity = reactive({})
/**
* 系统方法
*/
onMounted(() => {
nextTick(() => {
window.addEventListener('resize', resizeHeight)
search()
})
})
onBeforeUnmount(() => {
nextTick(() => {
window.removeEventListener('resize', resizeHeight)
})
})
const resizeHeight = () => {
maxHeight.value = window.innerHeight * 0.55
}
/**
* 自定义方法
*/
//
const search = () => {
tableLoading.value = true
let request = genTableRequest(baseTableQuery)
//
request.vehicleId = stockQuery.vehicleId.trim()
request.goodsId = stockQuery.goodsId.trim()
request.locationId = stockQuery.locationId.trim()
request.stockStatus = stockQuery.stockStatus === -99 ? null : stockQuery.stockStatus
request.goodsStatus = stockQuery.goodsStatus === -99 ? null : stockQuery.goodsStatus
request.fromDate = stockQuery.fromDate == null ? null : dateFormatter(stockQuery.fromDate)
request.toDate = stockQuery.toDate == null ? null : dateFormatter(stockQuery.toDate)
queryStocksByPage(request).then((res) => {
const response = res.data
if (response.code === 0) {
const data = response.data
console.log(data)
if (data != null) {
displayStocks.value = data.lists
baseTableQuery.total = data.total
} else {
displayStocks.value = []
baseTableQuery.total = 0
}
} else {
ElMessage.error(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('查询库存信息异常。')
}).finally(() => {
tableLoading.value = false
})
}
const clearQuery = () => {
stockQuery.vehicleId = '',
stockQuery.goodsId = '',
stockQuery.locationId = '',
stockQuery.stockStatus = -99,
stockQuery.goodsStatus = -99,
stockQuery.fromDate = null,
stockQuery.toDate = null
}
const loadAllGoodsInfo = () => {
const request = {
userName: store.getters.getUserName
}
getGoodsInfoByGoodsId(request).then(res => {
const tableResponse = res.data
if (tableResponse.code == 0) {
this.goodsList = tableResponse.returnData
} else {
ElMessage.error(tableResponse.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('查询物料信息异常。')
})
}
const filterGoodsId = (queryString, cb) => {
const results = queryString
? this.goodsList.filter(this.createFilter(queryString))
: this.goodsList
// call callback function to return suggestion objects
cb(results)
}
const createFilter = (queryString) => {
return (restaurant) => {
return (
restaurant.goodsId.toLowerCase().indexOf(queryString.toLowerCase()) != -1
)
}
}
const handleSelectGoodsId = (item) => {
this.goodsIdQuery = item.goodsId
}
const locationFormat = (row, column, cellValue, index) => {
return locationFormatter(cellValue)
}
const dateFormat = (row, column, cellValue, index) => {
return dateFormatter(cellValue)
}
const timeFormat = (row, column, cellValue, index) => {
return timeFormatter(cellValue)
}
const 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 '长时间未使用'
}
}
const stockStatusFormat = (row, column, cellValue, index) => {
switch (cellValue) {
case 0:
return '在库中'
case 1:
return '出库中'
case 2:
return '已出库'
case 3:
return '回库中'
case 4:
return '盘点中'
case 9:
return '库存锁定'
default:
return '异常'
}
}
const yesOrNoFormat = (row, column, cellValue, index) => {
return yesOrNoFormatter(cellValue)
}
const rowStyle = ({ row, rowIndex }) => {
if (row.goodsStatus == 3) {
return { "color": "red" }
}
if (row.goodsStatus == 5) {
return { "color": "yellow" }
}
}
const handleSortChange = (data) => {
if (baseTableQuery.sortBy.has(data.prop)) {
baseTableQuery.sortBy.delete(data.prop)
}
baseTableQuery.sortBy.set(data.prop, data.order == 'ascending')
search()
}
const getCurrentRow = (row) => {
stockId = row.stockId
}
const exportExcel = () => {
const params = {
vehicleId: stockQuery.vehicleId,
goodsId: stockQuery.goodsId,
locationId: stockQuery.locationId,
stockStatus: stockQuery.stockStatus == -99 ? null : stockQuery.stockStatus,
goodsStatus: stockQuery.goodsStatus == -99 ? null : stockQuery.goodsStatus,
fromDate: stockQuery.fromDate,
toDate: stockQuery.toDate
}
exportStockExcel(params).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) {
console.log(e)
ElMessage.error('下载文件失败')
}
}).catch(err => {
console.log(err)
ElMessage.error('导出失败')
})
}
const editCurrentRowStock = (row) => {
this.stockFormEntity = {
stockId: row.stockId,
locationId: row.locationId,
vehicleId: row.vehicleId,
stockStatus: row.stockStatus,
createTime: row.createTime,
lastUpdateTime: row.lastUpdateTime,
lastUpdateUser: row.lastUpdateUser,
isInventory: row.isInventory,
inventoryTaskId: row.inventoryTaskId,
noUseDays: row.noUseDays,
goodsId: row.goodsId,
goodsName: row.goodsName,
goodsStatus: row.goodsStatus,
remainNum: row.remainNum,
totalNum: row.totalNum
}
this.dialogVisible = true
}
const submitStockInfo = () => {
const request = {
stockId: this.stockFormEntity.stockId,
locationId: this.stockFormEntity.locationId,
vehicleId: this.stockFormEntity.vehicleId,
stockStatus: this.stockFormEntity.stockStatus,
goodsId: this.stockFormEntity.goodsId,
goodsStatus: this.stockFormEntity.goodsStatus,
remainNum: this.stockFormEntity.remainNum,
userName: store.getters.getUserName
}
updateStockInfo(request).then(res => {
if (res.data.code == 0) {
this.dialogVisible = false
ElMessage.success('更新库存成功')
this.search()
} else {
errorBox(res.data.message)
}
}).catch(err => {
console.log(err)
errorBox('更新库存失败')
})
}
</script>
<style scoped>
.content {
display: flex;
width: 100%;
}
.work-area {
width: 100%;
/* padding: 5px; */
}
.search-area {
margin: auto;
min-height: fit-content;
max-height: 40%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.table-area {
margin: auto;
min-height: fit-content;
max-height: 60%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.el-form-item {
margin: 5px 5px 5px 5px;
}
.el-form-item .el-input {
width: 196px;
}
.table-class {
margin: 5px 5px 5px 5px;
width: inherit;
}
.el-pagination {
padding-left: 5px;
}
.my-autocomplete li {
width: 196px;
line-height: normal;
padding: 7px;
}
.my-autocomplete li .name {
text-overflow: ellipsis;
overflow: hidden;
}
.my-autocomplete li .addr {
font-size: 12px;
color: #b4b4b4;
}
.my-autocomplete li .highlighted .addr {
color: #ddd;
}
.my-autocomplete li .goods_id {
color: brown;
}
.my-autocomplete li .goods_name {
color: cornflowerblue;
}
</style>

View File

@ -0,0 +1,298 @@
<template>
<el-config-provider :locale="zhCn">
<el-container class="content">
<div class="work-area">
<fieldset class="search-area">
<el-form ref="stockQueryFormRef" :model="stockQuery" :label-position="labelPosition"
label-width="auto" style="max-width: 100%" status-icon>
<div style="display: flex;justify-content: space-between;">
<div style="align-content: center;">
<el-row>
<el-button type="primary" style="height: 40px; width: 120px; margin: auto 15px 5px auto; color: black;"
@click="queryStocks()">进行库存比对</el-button>
<el-button type="success" style="height: 40px; width: 80px; margin: auto 5px 5px auto; color: black;"
@click="search()">查询</el-button>
</el-row>
</div>
</div>
</el-form>
</fieldset>
<div class="table-area">
<el-table :data="displayStocks" stripe border v-loading="tableLoading" class="table-class"
:max-height="maxHeight" highlight-current-row @row-click="getCurrentRow" :row-style="rowStyle"
:header-cell-style="{ 'text-align': 'center' }" :cell-style="{ 'text-align': 'center', 'color': 'black' }"
@sort-change="handleSortChange">
<el-table-column width="65px" fixed="left">
<template v-slot="scope">
<el-radio :label="scope.row.id" v-model="stockId">&nbsp;</el-radio>
</template>
</el-table-column>
<el-table-column type="index" label="序号" fixed="left" min-width="80px" show-overflow-tooltip />
<el-table-column prop="goodsId" label="物料编号" fixed="left" min-width="120px"
show-overflow-tooltip />
<el-table-column prop="goodsDesc" label="物料描述" min-width="120px" show-overflow-tooltip />
<el-table-column prop="wmsTotalNum" label="WMS总数量" min-width="120px" show-overflow-tooltip />
<el-table-column prop="ewmTotalNum" label="EWM总数量" min-width="120px" show-overflow-tooltip />
<el-table-column prop="specialStock" label="特殊库存标识" min-width="120px" show-overflow-tooltip />
<el-table-column prop="specialStockNo" label="SO单号/供应商编号" min-width="150px" show-overflow-tooltip />
<el-table-column prop="specialStockItemNo" label="特殊库存item号" min-width="130px" show-overflow-tooltip />
<el-table-column prop="batchNo" label="批次号" min-width="120px" show-overflow-tooltip />
<el-table-column prop="createTime" label="创建时间" :formatter="timeFormat"
min-width="180px" show-overflow-tooltip />
<el-table-column prop="compareStatus" label="对比状态" min-width="150px" show-overflow-tooltip>
<template #default="scope">
<el-tag :type="getStatusType(scope.row.compareStatus)">
{{ getStatusText(scope.row.compareStatus) }}
</el-tag>
</template>
</el-table-column>
</el-table>
<br />
<el-pagination v-model:current-page="baseTableQuery.currentPage"
v-model:page-size="baseTableQuery.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="baseTableQuery.total" />
</div>
</div>
</el-container>
</el-config-provider>
</template>
<script setup>import store from '@/store'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import {getCompareData, queryStocksCompare} from '@/api/task.js'
import { timeFormatter } from '@/utils/formatter.js'
import { ref, reactive, onMounted, nextTick, onBeforeUnmount } from 'vue'
import { ElMessage } from 'element-plus'
import { labelPosition } from '@/constant/form'
/**
* 常量定义
*/
/**
* 变量定义
*/
let maxHeight = ref(window.innerHeight * 0.55)
let tableLoading = ref(false)
let displayStocks = ref([])
let baseTableQuery = reactive({
currentPage: 1,
pageSize: 10,
total: 0,
sortBy: new Map([['createTime', true]]),
standId: store.getters.getStandId,
userName: store.getters.getUserName
})
let stockQuery = reactive({
goodsId: '',
compareStatus: ''
})
let stockQueryFormRef = ref()
let stockId = ''
/**
* 系统方法
*/
onMounted(() => {
nextTick(() => {
window.addEventListener('resize', resizeHeight)
search()
})
})
onBeforeUnmount(() => {
nextTick(() => {
window.removeEventListener('resize', resizeHeight)
})
})
const resizeHeight = () => {
maxHeight.value = window.innerHeight * 0.55
}
/**
* 自定义方法
*/
/**
* 自定义方法
*/
//
const search = () => {
tableLoading.value = true
getCompareData().then((res) => {
const response = res.data
if (response.code === 0) {
const data = response.data
if (data != null) {
displayStocks.value = data
baseTableQuery.total = data.length
} else {
displayStocks.value = []
baseTableQuery.total = 0
}
} else {
ElMessage.error(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('查询库存对比信息异常。')
}).finally(() => {
tableLoading.value = false
})
}
/**
* 执行库存比对
*/
const queryStocks = () => {
tableLoading.value = true;
// API
queryStocksCompare().then((res) => {
const response = res.data;
if (response.code === 0) {
ElMessage.success('库存比对执行成功');
//
search();
} else {
ElMessage.error(response.message || '库存比对执行失败');
}
}).catch(err => {
console.error('库存比对异常:', err);
ElMessage.error('执行库存比对时发生异常');
}).finally(() => {
tableLoading.value = false;
});
}
const timeFormat = (row, column, cellValue, index) => {
return timeFormatter(cellValue)
}
const rowStyle = ({ row, rowIndex }) => {
// compareStatus
if (row.compareStatus === 0) {
return { "color": "green" }
} else if (row.compareStatus === 1 || row.compareStatus === -1) {
return { "color": "orange" }
} else if (row.compareStatus === 2 || row.compareStatus === -2) {
return { "color": "red" }
}
}
const handleSortChange = (data) => {
if (baseTableQuery.sortBy.has(data.prop)) {
baseTableQuery.sortBy.delete(data.prop)
}
baseTableQuery.sortBy.set(data.prop, data.order == 'ascending')
search()
}
const getCurrentRow = (row) => {
stockId = row.id
}
const getStatusText = (status) => {
const statusMap = {
'0': '数量一致',
'1': 'WMS多于EWM',
'-1': 'EWM多于WMS',
'2': 'WMS有EWM没有',
'-2': 'EWM有WMS没有'
}
return statusMap[status] || '未知状态'
}
const getStatusType = (status) => {
const typeMap = {
'0': 'success',
'1': 'warning',
'-1': 'warning',
'2': 'danger',
'-2': 'danger'
}
return typeMap[status] || 'info'
}
</script>
<style scoped>
.content {
display: flex;
width: 100%;
}
.work-area {
width: 100%;
/* padding: 5px; */
}
.search-area {
margin: auto;
min-height: fit-content;
max-height: 40%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.table-area {
margin: auto;
min-height: fit-content;
max-height: 60%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.el-form-item {
margin: 5px 5px 5px 5px;
}
.el-form-item .el-input {
width: 196px;
}
.table-class {
margin: 5px 5px 5px 5px;
width: inherit;
color: black;
}
.el-pagination {
padding-left: 5px;
}
.my-autocomplete li {
width: 196px;
line-height: normal;
padding: 7px;
}
.my-autocomplete li .name {
text-overflow: ellipsis;
overflow: hidden;
}
.my-autocomplete li .addr {
font-size: 12px;
color: #b4b4b4;
}
.my-autocomplete li .highlighted .addr {
color: #ddd;
}
.my-autocomplete li .goods_id {
color: brown;
}
.my-autocomplete li .goods_name {
color: cornflowerblue;
}
</style>

View File

@ -0,0 +1,315 @@
<template>
<el-config-provider :locale="zhCn">
<el-container class="content">
<div class="work-area">
<fieldset class="search-area">
<el-form ref="searchQueryFormRef" :model="searchQueryFormEntity" :label-position="labelPosition"
label-width="158px" style="max-width: 100%" status-icon>
<div style="display: flex;justify-content: space-between;">
<el-row>
<el-form-item label="料号">
<el-input v-model="searchQueryFormEntity.goodsId" clearable/>
</el-form-item>
<el-form-item label="箱号">
<el-input v-model="searchQueryFormEntity.vehicleId" clearable/>
</el-form-item>
<el-form-item label="创建时间from">
<el-date-picker v-model="searchQueryFormEntity.fromTime" type="datetime"
placeholder="请选择from时间" :shortcuts="shortcuts"
style="width: 196px;" clearable/>
</el-form-item>
<el-form-item label="创建时间to">
<el-date-picker v-model="searchQueryFormEntity.toTime" type="datetime"
placeholder="请选择to时间" :shortcuts="shortcuts"
style="width: 196px;" clearable/>
</el-form-item>
</el-row>
<div style="align-content: center;">
<el-row>
<el-button type="primary" class="btn-search" @click="search()">查询</el-button>
<el-button type="warning" class="btn-search" @click="clearQuery()">清除输入</el-button>
</el-row>
<el-row>
<el-button type="success" class="btn-search"
@click="exportExcel()">导出excel
</el-button>
</el-row>
</div>
</div>
</el-form>
</fieldset>
<div class="table-area">
<el-table :data="tableData" stripe border v-loading="tableLoading" class="table-class"
:max-height="maxHeight" highlight-current-row @row-click="getCurrentRow"
:header-cell-style="{ 'text-align': 'center' }" :cell-style="{ 'text-align': 'center' }"
@sort-change="handleSortChange">
<el-table-column width="65px" fixed="left">
<template v-slot="scope">
<el-radio :label="scope.row.updateId" v-model="updateId">&nbsp;</el-radio>
</template>
</el-table-column>
<el-table-column prop="updateId" label="数据编号" fixed="left" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="goodsId" label="料号" fixed="left" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="vehicleId" label="箱号" fixed="left" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="firstInTime" label="初次入库时间" :formatter="timeFormat" min-width="120px"
sortable="custom" show-overflow-tooltip/>
<el-table-column prop="beforeNum" label="原数量" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="afterNum" label="新数量" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="reason" label="原因" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="updateTime" label="更新时间" :formatter="timeFormat" min-width="120px"
sortable="custom" show-overflow-tooltip/>
<el-table-column prop="updateUser" label="更新用户" min-width="120px" sortable="custom"
show-overflow-tooltip/>
</el-table>
<br/>
<el-pagination v-model:current-page="baseTableQuery.currentPage"
v-model:page-size="baseTableQuery.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="baseTableQuery.total"/>
</div>
</div>
</el-container>
</el-config-provider>
</template>
<script setup>
import store from '@/store'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import {queryStockUpdateByPage} from '@/api/stock.js'
import {dateFormatter, timeFormatter} from '@/utils/formatter.js'
import {ref, reactive, onMounted, nextTick, onBeforeUnmount} from 'vue'
import {ElMessage} from 'element-plus'
import {genTableRequest} from '@/utils/generator.js'
import {labelPosition, shortcuts} from '@/constant/form.js'
import {exportStockUpdateExcel} from '@/api/excel.js'
/**
* 常量定义
*/
const STAND_ID = store.getters.getStandId
const USER_NAME = store.getters.getUserName
/**
* 变量定义
*/
let maxHeight = ref(window.innerHeight * 0.55)
let tableLoading = ref(false)
let tableData = ref([])
let baseTableQuery = reactive({
currentPage: 1,
pageSize: 10,
total: 0,
sortBy: new Map([['updateTime', false]]),//
standId: STAND_ID,
userName: USER_NAME
})
let searchQueryFormEntity = reactive({
vehicleId: '',
goodsId: '',
fromTime: null,
toTime: null
})
let searchQueryFormRef = ref()
let updateId = ''
/**
* 系统方法
*/
onMounted(() => {
nextTick(() => {
window.addEventListener('resize', resizeHeight)
search()
})
})
onBeforeUnmount(() => {
nextTick(() => {
window.removeEventListener('resize', resizeHeight)
})
})
const resizeHeight = () => {
maxHeight.value = window.innerHeight * 0.55
}
/**
* 自定义方法
*/
//
const search = () => {
tableLoading.value = true
let request = genTableRequest(baseTableQuery)
//
request.goodsId = searchQueryFormEntity.goodsId.trim()
request.vehicleId = searchQueryFormEntity.vehicleId.trim()
request.fromTime = searchQueryFormEntity.fromTime == null ? null : timeFormatter(searchQueryFormEntity.fromTime)
request.toTime = searchQueryFormEntity.toTime == null ? null : timeFormatter(searchQueryFormEntity.toTime)
queryStockUpdateByPage(request).then((res) => {
const response = res.data
if (response.code === 0) {
const data = response.data
if (data != null) {
tableData.value = data.lists
baseTableQuery.total = data.total
} else {
tableData.value = []
baseTableQuery.total = 0
}
} else {
ElMessage.error(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('查询数据异常。')
}).finally(() => {
tableLoading.value = false
})
}
const clearQuery = () => {
searchQueryFormEntity.goodsId = ''
searchQueryFormEntity.vehicleId = ''
}
const handleSortChange = (data) => {
if (baseTableQuery.sortBy.has(data.prop)) {
baseTableQuery.sortBy.delete(data.prop)
}
baseTableQuery.sortBy.set(data.prop, data.order == 'ascending')
search()
}
const getCurrentRow = (row) => {
updateId = row.updateId
}
const timeFormat = (row, column, cellValue, index) => {
return timeFormatter(cellValue)
}
const exportExcel = () => {
const params = {
goodsId: searchQueryFormEntity.goodsId.trim(),
vehicleId: searchQueryFormEntity.vehicleId.trim(),
fromTime: searchQueryFormEntity.fromTime == null ? null : timeFormatter(searchQueryFormEntity.fromTime),
toTime: searchQueryFormEntity.toTime == null ? null : timeFormatter(searchQueryFormEntity.toTime),
standId: STAND_ID,
userName: USER_NAME
}
exportStockUpdateExcel(params).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) {
console.log(e)
ElMessage.error('下载文件失败')
}
}).catch(err => {
console.log(err)
ElMessage.error('导出失败')
})
}
</script>
<style scoped>
.content {
display: flex;
width: 100%;
}
.work-area {
width: 100%;
/* padding: 5px; */
}
.search-area {
margin: auto;
min-height: fit-content;
max-height: 40%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.table-area {
margin: auto;
min-height: fit-content;
max-height: 60%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.el-form-item {
margin: 5px 5px 5px 5px;
}
.el-form-item .el-input {
width: 196px;
}
.el-form-item .el-input-number {
width: 196px;
}
.table-class {
margin: 5px 5px 5px 5px;
width: inherit;
}
.el-pagination {
padding-left: 5px;
}
.my-autocomplete li {
width: 196px;
line-height: normal;
padding: 7px;
}
.my-autocomplete li .name {
text-overflow: ellipsis;
overflow: hidden;
}
.my-autocomplete li .addr {
font-size: 12px;
color: #b4b4b4;
}
.my-autocomplete li .highlighted .addr {
color: #ddd;
}
.my-autocomplete li .goods_id {
color: brown;
}
.my-autocomplete li .goods_name {
color: cornflowerblue;
}
.btn-search {
height: 30px;
width: 80px;
margin: auto 5px 5px auto;
color: black;
}
</style>

View File

@ -0,0 +1,551 @@
<template>
<el-config-provider :locale="zhCn">
<el-container class="content">
<div class="work-area">
<fieldset class="search-area">
<el-form ref="searchQueryFormRef" :model="searchQueryFormEntity" :label-position="labelPosition"
label-width="158px" style="max-width: 100%" status-icon>
<div style="display: flex;justify-content: space-between;">
<el-row>
<el-form-item label="任务类型">
<el-select-v2 style="width: 196px" v-model="searchQueryFormEntity.taskType" placeholder="任务类型"
:options="addAllOptionOfOptions(taskTypeOptions)"
@change="search()"></el-select-v2>
</el-form-item>
<el-form-item label="任务状态">
<el-select-v2 style="width: 196px" v-model="searchQueryFormEntity.taskStatus" placeholder="任务状态"
:options="addAllOptionOfOptions(wmsTaskStatusOptions)"
@change="search()"></el-select-v2>
</el-form-item>
<el-form-item label="箱号">
<el-input v-model="searchQueryFormEntity.vehicleId" @keyup.enter="search()" clearable/>
</el-form-item>
<el-form-item label="料号">
<el-input v-model="searchQueryFormEntity.goodsId" @keyup.enter="search()" clearable/>
</el-form-item>
</el-row>
<div style="align-content: center;">
<el-row>
<el-button type="primary" class="btn-search" @click="search()">查询</el-button>
<el-button type="warning" class="btn-search" @click="clearQuery()">清除输入</el-button>
</el-row>
</div>
</div>
</el-form>
</fieldset>
<div class="table-area">
<el-table :data="tableData" stripe border v-loading="tableLoading" class="table-class"
:max-height="maxHeight" highlight-current-row @row-click="getCurrentRow"
:header-cell-style="{ 'text-align': 'center' }" :cell-style="{ 'text-align': 'center' }"
@sort-change="handleSortChange">
<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="taskId" label="任务号" fixed="left" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="taskType" label="任务类型" fixed="left" :formatter="taskTypeFormat" min-width="120px"
sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="taskStatus" label="任务状态" :formatter="taskStatusFormat" fixed="right"
min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="taskPriority" label="优先级" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="vehicleId" label="箱号" fixed="left" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="goodsId" label="料号" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="goodsDesc" label="物料描述"
min-width="120px" sortable="custom" show-overflow-tooltip/>
<el-table-column prop="opNum" label="操作数量" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="stockNum" label="库存数量" min-width="120px"
sortable="custom" show-overflow-tooltip/>
<el-table-column prop="origin" label="起点" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="destination" label="终点" min-width="120px"
sortable="custom" show-overflow-tooltip/>
<el-table-column prop="wcsTaskId" label="wcs任务号" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="createTime" label="创建时间" :formatter="timeFormat" min-width="120px"
sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="finishTime" label="完成时间" :formatter="timeFormat" min-width="120px"
sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="opUser" label="操作用户" min-width="120px"
sortable="custom" show-overflow-tooltip/>
<el-table-column prop="callStand" label="呼叫站台" min-width="120px"
sortable="custom" show-overflow-tooltip/>
<el-table-column prop="remark" label="备注" min-width="120px"
sortable="custom" show-overflow-tooltip/>
<el-table-column fixed="right" label="操作" width="170px">
<template v-slot="scope">
<div style="display: inline-block; align-content: center;">
<el-button type="primary"
@click="editCurrentRowTask(scope.row)">编辑
</el-button>
<el-button type="danger"
@click="deleteCurrentRowTask(scope.row)">删除
</el-button>
</div>
</template>
</el-table-column>
</el-table>
<br/>
<el-pagination v-model:current-page="baseTableQuery.currentPage"
v-model:page-size="baseTableQuery.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="baseTableQuery.total"/>
</div>
<el-dialog v-model="rowEditFlag" title="任务详情" width="40%" draggable :show-close="false">
<el-form ref="rowEditFormRef" :model="rowEditFormEntity" :label-position="labelPosition"
label-width="100px" style="max-width: 100%" status-icon>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="任务号">
<el-input v-model="rowEditFormEntity.taskId" disabled/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="任务类型">
<el-select-v2 style="width: 196px" v-model="rowEditFormEntity.taskType" placeholder="请选择任务类型"
:options="taskTypeOptions" disabled></el-select-v2>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="任务状态">
<el-select-v2 style="width: 196px" v-model="rowEditFormEntity.taskStatus" placeholder="请选择任务状态"
:options="wmsTaskStatusOptions"></el-select-v2>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="优先级">
<el-input-number v-model.number="rowEditFormEntity.taskPriority" controls-position="right"
:min="0" :max="9"/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="箱号">
<el-input v-model="rowEditFormEntity.vehicleId" disabled/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="料号">
<el-input v-model="rowEditFormEntity.goodsId" disabled/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="描述">
<el-input v-model="rowEditFormEntity.goodsDesc" disabled/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="wcs任务号">
<el-input v-model="rowEditFormEntity.wcsTaskId" disabled/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="操作数量">
<el-input-number v-model.number="rowEditFormEntity.opNum" controls-position="right"
:min="0" clearable/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="库存数量">
<el-input-number v-model.number="rowEditFormEntity.stockNum" controls-position="right" disabled/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="起点">
<el-input v-model="rowEditFormEntity.origin" disabled/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="终点">
<el-input v-model="rowEditFormEntity.destination" clearable/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="创建时间">
<el-input type="text" v-model="rowEditFormEntity.createTime" :formatter="timeFormatter" disabled>
</el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="完成时间">
<el-input type="text" v-model="rowEditFormEntity.finishTime" :formatter="timeFormatter" disabled>
</el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="操作用户">
<el-input v-model="rowEditFormEntity.opUser" disabled/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="呼叫站台">
<el-input v-model="rowEditFormEntity.callStand" disabled/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="备注">
<el-input type="textarea" style="width: 196px" v-model="rowEditFormEntity.remark" maxlength="1024"
:autosize="{minRows: 1, maxRows: 4}"></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="rowEditFlag = false">取消</el-button>
<el-button type="success" @click="submitUpdateRow(rowEditFormEntity)">
确定
</el-button>
</span>
</template>
</el-dialog>
</div>
</el-container>
</el-config-provider>
</template>
<script setup>
import store from '@/store'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import {queryTasksByPage} from '@/api/taskQuery.js'
import {deleteWmsTask, updateWmsTask} from '@/api/taskOperation'
import {timeFormatter, wmsTaskTypeFormatter, wmsTaskStatusFormatter} from '@/utils/formatter.js'
import {ref, reactive, onMounted, nextTick, onBeforeUnmount} from 'vue'
import {ElMessage, ElMessageBox} from 'element-plus'
import {genTableRequest} from '@/utils/generator.js'
import {labelPosition} from '@/constant/form.js'
import {taskTypeOptions, wmsTaskStatusOptions} from '@/constant/options.js'
import {addAllOptionOfOptions} from '@/utils/generator.js'
import {loading} from '@/utils/loading'
/**
* 常量定义
*/
const STAND_ID = store.getters.getStandId
const USER_NAME = store.getters.getUserName
/**
* 变量定义
*/
let maxHeight = ref(window.innerHeight * 0.55)
let tableLoading = ref(false)
let tableData = ref([])
let baseTableQuery = reactive({
currentPage: 1,
pageSize: 10,
total: 0,
sortBy: new Map([['createTime', true]]),//
standId: STAND_ID,
userName: USER_NAME
})
let searchQueryFormEntity = reactive({
vehicleId: '',
goodsId: '',
taskType: -99,
taskStatus: -99
})
let searchQueryFormRef = ref()
let rowEditFlag = ref(false)
let taskId = ''
let rowEditFormRef = ref()
let rowEditFormEntity = reactive({
taskId: '',
taskType: null,
taskStatus: null,
taskPriority: null,
vehicleId: '',
origin: '',
destination: '',
wcsTaskId: '',
createTime: null,
finishTime: null,
goodsId: '',
opNum: null,
stockNum: null,
opUser: '',
remark: '',
callStand: '',
goodsDesc: ''
})
/**
* 系统方法
*/
onMounted(() => {
nextTick(() => {
window.addEventListener('resize', resizeHeight)
search()
})
})
onBeforeUnmount(() => {
nextTick(() => {
window.removeEventListener('resize', resizeHeight)
})
})
const resizeHeight = () => {
maxHeight.value = window.innerHeight * 0.55
}
/**
* 自定义方法
*/
//
const search = () => {
tableLoading.value = true
let request = genTableRequest(baseTableQuery)
//
request.vehicleId = searchQueryFormEntity.vehicleId.trim()
request.goodsId = searchQueryFormEntity.goodsId.trim()
request.taskType = searchQueryFormEntity.taskType === -99 ? null : searchQueryFormEntity.taskType
request.taskStatus = searchQueryFormEntity.taskStatus === -99 ? null : searchQueryFormEntity.taskStatus
queryTasksByPage(request).then((res) => {
const response = res.data
if (response.code === 0) {
const data = response.data
if (data != null) {
tableData.value = data.lists
baseTableQuery.total = data.total
} else {
tableData.value = []
baseTableQuery.total = 0
}
} else {
ElMessage.error(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('查询数据异常。')
}).finally(() => {
tableLoading.value = false
})
}
const clearQuery = () => {
searchQueryFormEntity.vehicleId = ''
searchQueryFormEntity.goodsId = ''
}
const handleSortChange = (data) => {
if (baseTableQuery.sortBy.has(data.prop)) {
baseTableQuery.sortBy.delete(data.prop)
}
baseTableQuery.sortBy.set(data.prop, data.order.toLowerCase() === 'ascending')
search()
}
const getCurrentRow = (row) => {
taskId = row.taskId
}
const timeFormat = (row, column, cellValue, index) => {
return timeFormatter(cellValue)
}
const taskTypeFormat = (row, column, cellValue, index) => {
return wmsTaskTypeFormatter(cellValue)
}
const taskStatusFormat = (row, column, cellValue, index) => {
return wmsTaskStatusFormatter(cellValue)
}
//
const editCurrentRowTask = (row) => {
// form
rowEditFormEntity.taskId = row.taskId
rowEditFormEntity.taskType = row.taskType
rowEditFormEntity.taskStatus = row.taskStatus
rowEditFormEntity.taskPriority = row.taskPriority
rowEditFormEntity.vehicleId = row.vehicleId
rowEditFormEntity.origin = row.origin
rowEditFormEntity.destination = row.destination
rowEditFormEntity.wcsTaskId = row.wcsTaskId
rowEditFormEntity.createTime = row.createTime
rowEditFormEntity.finishTime = row.finishTime
rowEditFormEntity.goodsId = row.goodsId
rowEditFormEntity.opNum = row.opNum
rowEditFormEntity.stockNum = row.stockNum
rowEditFormEntity.opUser = row.opUser
rowEditFormEntity.remark = row.remark
rowEditFormEntity.callStand = row.callStand
rowEditFormEntity.goodsDesc = row.goodsDesc
//
rowEditFlag.value = true
}
//
const deleteCurrentRowTask = (row) => {
ElMessageBox.confirm(
'当前操作仅涉及删除当前任务行。\n是否确认',
'警告',
{
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
}
).then(() => {
const request = {
taskId: row.taskId,
userName: USER_NAME,
standId: STAND_ID
}
loading.open('删除中...')
deleteWmsTask(request).then(res => {
const response = res.data
if (response.code === 0) {
ElMessage.success(response.message)
} else {
ElMessage.error(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('删除异常')
}).finally(() => {
search()
loading.close()
})
}).catch(() => {
ElMessage.info('操作取消')
})
}
//
const submitUpdateRow = (rowFormEntity) => {
const request = {
taskId: rowFormEntity.taskId,
taskStatus: rowFormEntity.taskStatus,
taskPriority: rowFormEntity.taskPriority,
opNum: rowFormEntity.opNum,
destination: rowFormEntity.destination,
remark: rowFormEntity.remark,
standId: STAND_ID,
userName: USER_NAME
}
loading.open('更新中...')
updateWmsTask(request).then(res => {
if (res.data.code === 0) {
ElMessage.success('更新数据成功。')
rowEditFlag.value = false
search()
} else {
ElMessage.error('更新数据失败。')
}
}).catch(err => {
console.log(err)
ElMessage.error('更新数据异常。')
}).finally(() => {
loading.close()
})
}
</script>
<style scoped>
.content {
display: flex;
width: 100%;
}
.work-area {
width: 100%;
/* padding: 5px; */
}
.search-area {
margin: auto;
min-height: fit-content;
max-height: 40%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.table-area {
margin: auto;
min-height: fit-content;
max-height: 60%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.el-form-item {
margin: 5px 5px 5px 5px;
}
.el-form-item .el-input {
width: 196px;
}
.el-form-item .el-input-number {
width: 196px;
}
.table-class {
margin: 5px 5px 5px 5px;
width: inherit;
}
.el-pagination {
padding-left: 5px;
}
.my-autocomplete li {
width: 196px;
line-height: normal;
padding: 7px;
}
.my-autocomplete li .name {
text-overflow: ellipsis;
overflow: hidden;
}
.my-autocomplete li .addr {
font-size: 12px;
color: #b4b4b4;
}
.my-autocomplete li .highlighted .addr {
color: #ddd;
}
.my-autocomplete li .goods_id {
color: brown;
}
.my-autocomplete li .goods_name {
color: cornflowerblue;
}
.btn-search {
height: 30px;
width: 80px;
margin: auto 5px 5px auto;
color: black;
}
.dialog-footer {
display: flex;
justify-content: center;
}
</style>

View File

@ -0,0 +1,8 @@
<template>
</template>
<script setup>
</script>
<style scoped>
</style>

View File

@ -0,0 +1,453 @@
<template>
<el-config-provider :locale="zhCn">
<el-container class="content">
<div class="work-area">
<fieldset class="search-area">
<el-form ref="searchQueryFormRef" :model="searchQueryFormEntity" :label-position="labelPosition"
label-width="158px" style="max-width: 100%" status-icon>
<div style="display: flex;justify-content: space-between;">
<el-row>
<el-form-item label="空箱">
<el-select-v2 style="width: 196px" v-model="searchQueryFormEntity.isEmpty" placeholder="任务类型"
:options="addAllOptionOfOptions(yesOrNoOptions)"
@change="search()"></el-select-v2>
</el-form-item>
<el-form-item label="锁定">
<el-select-v2 style="width: 196px" v-model="searchQueryFormEntity.isLock" placeholder="任务状态"
:options="addAllOptionOfOptions(yesOrNoOptions)"
@change="search()"></el-select-v2>
</el-form-item>
<el-form-item label="状态">
<el-select-v2 style="width: 196px" v-model="searchQueryFormEntity.vehicleStatus" placeholder="任务状态"
:options="addAllOptionOfOptions(vehicleStatusOptions)"
@change="search()"></el-select-v2>
</el-form-item>
<el-form-item label="箱号">
<el-input v-model="searchQueryFormEntity.vehicleId" @keyup.enter="search()"
clearable />
</el-form-item>
<el-form-item label="库位">
<el-input v-model="searchQueryFormEntity.locationId" @keyup.enter="search()"
clearable />
</el-form-item>
</el-row>
<div style="align-content: center;">
<el-row>
<el-button type="primary" class="btn-search" @click="search()">查询</el-button>
<el-button type="warning" class="btn-search" @click="clearQuery()">清除输入</el-button>
</el-row>
</div>
</div>
</el-form>
</fieldset>
<div class="table-area">
<el-table :data="tableData" stripe border v-loading="tableLoading" class="table-class"
:max-height="maxHeight" highlight-current-row @row-click="getCurrentRow"
:header-cell-style="{ 'text-align': 'center' }" :cell-style="{ 'text-align': 'center' }"
@sort-change="handleSortChange">
<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" sortable="custom"
show-overflow-tooltip />
<el-table-column prop="vehicleStatus" label="状态" :formatter="vehicleStatusFormat" fixed="right"
min-width="120px" sortable="custom" show-overflow-tooltip />
<el-table-column prop="isEmpty" label="空箱" :formatter="yesOrNoFormat" min-width="120px"
sortable="custom" show-overflow-tooltip />
<!-- <el-table-column prop="vehicleType" label="料箱类型" min-width="120px" sortable="custom"
show-overflow-tooltip /> -->
<el-table-column prop="isLock" label="锁定" :formatter="yesOrNoFormat" min-width="120px"
sortable="custom" show-overflow-tooltip />
<el-table-column prop="locationId" label="库位" :formatter="locationFormat" min-width="120px"
sortable="custom" show-overflow-tooltip />
<el-table-column prop="lastInTime" label="上次入库时间" :formatter="timeFormat" min-width="120px"
sortable="custom" show-overflow-tooltip />
<!-- <el-table-column fixed="right" label="操作" width="170px">
<template v-slot="scope">
<div style="display: inline-block; align-content: center;">
<el-button type="primary"
@click="editCurrentRowFormEntity(scope.row)">编辑</el-button>
</div>
</template>
</el-table-column> -->
</el-table>
<br />
<el-pagination v-model:current-page="baseTableQuery.currentPage"
v-model:page-size="baseTableQuery.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="baseTableQuery.total" />
</div>
<el-dialog v-model="rowEditFlag" title="工作信息" width="40%" draggable :show-close="false">
<el-form ref="rowEditFormRef" :model="rowFormEntity" :label-position="labelPosition"
label-width="100px" style="max-width: 100%" status-icon>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="工作编号">
<el-input v-model="rowFormEntity.workIndex" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="工单号">
<el-input v-model="rowFormEntity.workOrder" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="总成号">
<el-input v-model="rowFormEntity.productId" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="成品号">
<el-input v-model="rowFormEntity.singleProductId" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="料盒号">
<el-input v-model="rowFormEntity.boxNo" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="料号">
<el-input v-model="rowFormEntity.goodsId" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="需求数量">
<el-input-number v-model.number="rowFormEntity.needNum" controls-position="right"
:min="0" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="已完成数量">
<el-input-number v-model.number="rowFormEntity.finishNum" controls-position="right"
:min="0" :max="rowFormEntity.needNum" clearable />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="已分配数量">
<el-input-number v-model.number="rowFormEntity.distributeNum"
controls-position="right" :min="0" :max="rowFormEntity.needNum" clearable />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="工作状态">
<el-select-v2 v-model="rowFormEntity.workStatus" placeholder="请选择工作状态"
:options="workStatusOptions"></el-select-v2>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="缺料状态">
<el-select-v2 v-model="rowFormEntity.lackStatus" placeholder="请选择缺料状态"
:options="lackStatusOptions"></el-select-v2>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="rowEditFlag = false">取消</el-button>
<el-button type="success" @click="submitUpdateRow(rowFormEntity)">
确定
</el-button>
</span>
</template>
</el-dialog>
</div>
</el-container>
</el-config-provider>
</template>
<script setup>
import store from '@/store'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import { queryVehicleInfoByPage } from '@/api/vehicle.js'
import { timeFormatter, locationFormatter, yesOrNoFormatter, vehicleStatusFormatter } from '@/utils/formatter.js'
import { ref, reactive, onMounted, nextTick, onBeforeUnmount } from 'vue'
import { ElMessage } from 'element-plus'
import { genTableRequest } from '@/utils/generator.js'
import { labelPosition } from '@/constant/form.js'
import { yesOrNoOptions, vehicleStatusOptions } from '@/constant/options.js'
import { addAllOptionOfOptions } from '@/utils/generator.js'
import { loading } from '@/utils/loading'
/**
* 常量定义
*/
const STAND_ID = store.getters.getStandId
const USER_NAME = store.getters.getUserName
/**
* 变量定义
*/
let maxHeight = ref(window.innerHeight * 0.55)
let tableLoading = ref(false)
let tableData = ref([])
let baseTableQuery = reactive({
currentPage: 1,
pageSize: 10,
total: 0,
sortBy: new Map([['lastInTime', true]]),//
standId: STAND_ID,
userName: USER_NAME
})
let searchQueryFormEntity = reactive({
vehicleId: '',
locationId: '',
vehicleStatus: -99,
isLock: -99,
isEmpty: -99
})
let searchQueryFormRef = ref()
let rowEditFlag = ref(false)
let vehicleId = ''
let rowEditFormRef = ref()
let rowFormEntity = reactive({})
/**
* 系统方法
*/
onMounted(() => {
nextTick(() => {
window.addEventListener('resize', resizeHeight)
search()
})
})
onBeforeUnmount(() => {
nextTick(() => {
window.removeEventListener('resize', resizeHeight)
})
})
const resizeHeight = () => {
maxHeight.value = window.innerHeight * 0.55
}
/**
* 自定义方法
*/
//
const search = () => {
tableLoading.value = true
let request = genTableRequest(baseTableQuery)
//
request.vehicleId = searchQueryFormEntity.vehicleId.trim()
request.locationId = searchQueryFormEntity.locationId.trim()
request.vehicleStatus = searchQueryFormEntity.vehicleStatus == -99 ? null : searchQueryFormEntity.vehicleStatus
request.isLock = searchQueryFormEntity.isLock == -99 ? null : searchQueryFormEntity.isLock
request.isEmpty = searchQueryFormEntity.isEmpty == -99 ? null : searchQueryFormEntity.isEmpty
queryVehicleInfoByPage(request).then((res) => {
const response = res.data
if (response.code == 0) {
const data = response.data
if (data != null) {
tableData.value = data.lists
baseTableQuery.total = data.total
} else {
tableData.value = []
baseTableQuery.total = 0
}
} else {
ElMessage.error(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('查询数据异常。')
}).finally(() => {
tableLoading.value = false
})
}
const clearQuery = () => {
searchQueryFormEntity.vehicleId = ''
searchQueryFormEntity.locationId = ''
}
const handleSortChange = (data) => {
if (baseTableQuery.sortBy.has(data.prop)) {
baseTableQuery.sortBy.delete(data.prop)
}
baseTableQuery.sortBy.set(data.prop, data.order == 'ascending')
search()
}
const getCurrentRow = (row) => {
vehicleId = row.vehicleId
}
const timeFormat = (row, column, cellValue, index) => {
return timeFormatter(cellValue)
}
const yesOrNoFormat = (row, column, cellValue, index) => {
return yesOrNoFormatter(cellValue)
}
const locationFormat = (row, column, cellValue, index) => {
return locationFormatter(cellValue)
}
const vehicleStatusFormat = (row, column, cellValue, index) => {
return vehicleStatusFormatter(cellValue)
}
//
const editCurrentRowFormEntity = (row) => {
// form
rowFormEntity.workIndex = row.workIndex
rowFormEntity.workOrder = row.workOrder
rowFormEntity.productId = row.productId
rowFormEntity.singleProductId = row.singleProductId
rowFormEntity.boxNo = row.boxNo
rowFormEntity.goodsId = row.goodsId
rowFormEntity.needNum = row.needNum
rowFormEntity.distributeNum = row.distributeNum
rowFormEntity.finishNum = row.finishNum
rowFormEntity.workStatus = row.workStatus
rowFormEntity.lackStatus = row.lackStatus
//
rowEditFlag.value = true
}
//
const closeLackWork = (row) => {
const request = {
workIndex: row.workIndex,
standId: STAND_ID,
userName: USER_NAME
}
loading.open('关闭中...')
closeCurrentWorks(request).then(res => {
const response = res.data
if (response.code == 0) {
ElMessage.success(response.message)
search()
} else {
ElMessage.error(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('请求异常。')
}).finally(() => {
loading.close()
})
}
//
const submitUpdateRow = (rowFormEntity) => {
const request = {
workIndex: rowFormEntity.workIndex,
distributeNum: rowFormEntity.distributeNum,
finishNum: rowFormEntity.finishNum,
workStatus: rowFormEntity.workStatus,
lackStatus: rowFormEntity.lackStatus,
standId: STAND_ID,
userName: USER_NAME
}
loading.open('更新中...')
updateKateWorks(request).then(res => {
if (res.data.code == 0) {
ElMessage.success('更新数据成功。')
rowEditFlag.value = false
search()
} else {
ElMessage.error('更新数据失败。')
}
}).catch(err => {
console.log(err)
ElMessage.error('更新数据异常。')
}).finally(() => {
loading.close()
})
}
</script>
<style scoped>
.content {
display: flex;
width: 100%;
}
.work-area {
width: 100%;
/* padding: 5px; */
}
.search-area {
margin: auto;
min-height: fit-content;
max-height: 40%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.table-area {
margin: auto;
min-height: fit-content;
max-height: 60%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.el-form-item {
margin: 5px 5px 5px 5px;
}
.el-form-item .el-input {
width: 196px;
}
.el-form-item .el-input-number {
width: 196px;
}
.table-class {
margin: 5px 5px 5px 5px;
width: inherit;
}
.el-pagination {
padding-left: 5px;
}
.my-autocomplete li {
width: 196px;
line-height: normal;
padding: 7px;
}
.my-autocomplete li .name {
text-overflow: ellipsis;
overflow: hidden;
}
.my-autocomplete li .addr {
font-size: 12px;
color: #b4b4b4;
}
.my-autocomplete li .highlighted .addr {
color: #ddd;
}
.my-autocomplete li .goods_id {
color: brown;
}
.my-autocomplete li .goods_name {
color: cornflowerblue;
}
.btn-search {
height: 30px;
width: 80px;
margin: auto 5px 5px auto;
color: black;
}
</style>

View File

@ -0,0 +1,377 @@
<template>
<el-config-provider :locale="zhCn">
<el-container class="content">
<div class="work-area">
<fieldset class="search-area">
<el-form ref="configQueryFormRef" :model="configQueryFormEntity" :label-position="labelPosition"
label-width="158px" style="max-width: 100%" status-icon>
<div style="display: flex;justify-content: space-between;">
<el-row>
<el-form-item label="配置键">
<el-input v-model="configQueryFormEntity.configKey" clearable/>
</el-form-item>
<el-form-item label="配置名">
<el-input v-model="configQueryFormEntity.configName" clearable/>
</el-form-item>
</el-row>
<div style="align-content: center;">
<el-row>
<el-button type="primary" class="btn-search" @click="search()">查询</el-button>
<el-button type="warning" class="btn-search" @click="clearQuery()">清除输入</el-button>
</el-row>
</div>
</div>
</el-form>
</fieldset>
<div class="table-area">
<el-table :data="displayConfigs" stripe border v-loading="tableLoading" class="table-class"
:max-height="maxHeight" highlight-current-row @row-click="getCurrentRow"
:header-cell-style="{ 'text-align': 'center' }" :cell-style="{ 'text-align': 'center' }"
@sort-change="handleSortChange">
<el-table-column width="65px" fixed="left">
<template v-slot="scope">
<el-radio :label="scope.row.configId" v-model="configId">&nbsp;</el-radio>
</template>
</el-table-column>
<el-table-column prop="configId" label="配置id" fixed="left" min-width="80px"
show-overflow-tooltip sortable="custom" />
<el-table-column prop="configName" label="配置名称" fixed="left" min-width="120px"
show-overflow-tooltip sortable="custom" />
<el-table-column prop="configKey" label="配置键" show-overflow-tooltip min-width="120px" sortable="custom" />
<el-table-column prop="configValue" label="配置值" show-overflow-tooltip min-width="140px" sortable="custom" />
<el-table-column prop="configType" label="配置类型" :formatter="configTypeFormat" min-width="100px"
show-overflow-tooltip sortable="custom" />
<el-table-column fixed="right" label="操作" width="120px">
<template v-slot="scope">
<el-button plain type="primary" @click="editCurrentRow(scope.row)">编辑</el-button>
</template>
</el-table-column>
</el-table>
<br/>
<el-pagination v-model:current-page="baseTableQuery.currentPage"
v-model:page-size="baseTableQuery.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="baseTableQuery.total"/>
</div>
<el-dialog v-model="showConfigEditFlag" title="编辑配置信息" width="40%" draggable :show-close="false">
<el-form ref="configEditFormRef" :model="configEditFormEntity" :label-position="labelPosition"
label-width="100px" style="max-width: 100%" :rules="editRules" status-icon>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="配置名称" prop="configName">
<el-input v-model="configEditFormEntity.configName" disabled/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="配置类型" prop="configType">
<el-select-v2 v-model="configEditFormEntity.configType" placeholder="请选择配置类型"
:options="configTypeOptions" disabled></el-select-v2>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="配置键" prop="configKey">
<el-input v-model="configEditFormEntity.configKey" disabled/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="配置值" prop="configValue">
<el-input v-if="configEditFormEntity.configType === 1" type="textarea" :rows="1"
v-model="configEditFormEntity.configValue" placeholder="" :maxlength="-1"
:show-word-limit="false" :autosize="{ minRows: 1, maxRows: 4 }">
</el-input>
<!-- 类型2需要增加subKey-->
<!-- <el-select v-if="configEditFormEntity.configType === 2"-->
<!-- v-model="configEditFormEntity.configValue" multiple collapse-tags-->
<!-- collapse-tags-tooltip :placeholder="'请选择' + configEditFormEntity.configName">-->
<!-- <el-option v-for="(value, index) in mails" :key="index" :label="value"-->
<!-- :value="value"/>-->
<!-- </el-select>-->
<el-switch v-if="configEditFormEntity.configType === 3" style="margin-left: 5px;"
v-model="configEditFormEntity.configValue" active-value="1" inactive-value="0"/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="showConfigEditFlag = false">取消</el-button>
<el-button type="primary" @click="submitChange()">
确定
</el-button>
</span>
</template>
</el-dialog>
</div>
</el-container>
</el-config-provider>
</template>
<script setup>
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import store from '@/store'
import {configTypeFormatter} from '@/utils/formatter.js'
import {ref, reactive, onMounted, nextTick, onBeforeUnmount} from 'vue'
import {ElMessage} from 'element-plus'
import {genTableRequest} from '@/utils/generator.js'
import {labelPosition} from '@/constant/form'
import {queryConfigsByPage, updateConfig} from "@/api/config";
/**
* 常量定义
*/
const USER_NAME = store.getters.getUserName
const STAND_ID = store.getters.getStandId
const configTypeOptions = [
{
value: '1',
label: '输入框'
},
{
value: '2',
label: '下拉多选'
},
{
value: '3',
label: '开关'
}
]
const editRules = {
configId: [
{required: true, message: '请输入配置id'}
],
configName: [
{required: true, message: '请输入配置名称'}
],
configKey: [
{required: true, message: '请输入配置键'}
],
configValue: [
{required: true, message: '请输入配置值'}
],
configType: [
{required: true, message: '请输入配置类型'}
]
}
/**
* 变量定义
*/
let maxHeight = ref(window.innerHeight * 0.55)
let tableLoading = ref(false)
let displayConfigs = ref([])
let baseTableQuery = reactive({
currentPage: 1,
pageSize: 10,
total: 0,
sortBy: new Map([['configId', true]]),//
standId: store.getters.getStandId,
userName: store.getters.getUserName
})
let configQueryFormEntity = reactive({
configKey: '',
configName: ''
})
let configQueryFormRef = ref()
let showConfigEditFlag = ref(false)
let configId = ''
let configEditFormRef = ref()
let configEditFormEntity = reactive({
configId: '',
configName: '',
configKey: '',
configValue: '',
configType: null
// subKey: ''
})
/**
* 系统方法
*/
onMounted(() => {
nextTick(() => {
window.addEventListener('resize', resizeHeight)
search()
})
})
onBeforeUnmount(() => {
nextTick(() => {
window.removeEventListener('resize', resizeHeight)
})
})
const resizeHeight = () => {
maxHeight.value = window.innerHeight * 0.55
}
/**
* 自定义方法
*/
//
const search = () => {
tableLoading.value = true
let request = genTableRequest(baseTableQuery)
//
request.configKey = configQueryFormEntity.configKey
request.configName = configQueryFormEntity.configName
queryConfigsByPage(request).then((res) => {
const response = res.data
if (response.code === 0) {
const data = response.data
if (data != null) {
displayConfigs.value = data.lists
baseTableQuery.total = data.total
} else {
displayConfigs.value = []
baseTableQuery.total = 0
}
} else {
ElMessage.error(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('查询配置数据异常。')
}).finally(() => {
tableLoading.value = false
})
}
const clearQuery = () => {
configQueryFormEntity.configKey = ''
configQueryFormEntity.configName = ''
}
const handleSortChange = (data) => {
if (baseTableQuery.sortBy.has(data.prop)) {
baseTableQuery.sortBy.delete(data.prop)
}
baseTableQuery.sortBy.set(data.prop, data.order.toLowerCase() === 'ascending')
search()
}
const getCurrentRow = (row) => {
configId = row.configId
}
const configTypeFormat = (row, column, cellValue, index) => {
return configTypeFormatter(cellValue)
}
const editCurrentRow = (row) => {
showConfigEditFlag.value = true
configEditFormEntity.configId = row.configId
configEditFormEntity.configName = row.configName
configEditFormEntity.configKey = row.configKey
configEditFormEntity.configValue = row.configValue
configEditFormEntity.configType = row.configType
}
const submitChange = () => {
const request = {
configId: configEditFormEntity.configId,
configName: configEditFormEntity.configName,
configKey: configEditFormEntity.configKey,
configValue: configEditFormEntity.configValue,
configType: configEditFormEntity.configType,
userName: USER_NAME,
standId: STAND_ID
}
updateConfig(request).then(res => {
const response = res.data
if (response.code === 0) {
showConfigEditFlag.value = false
ElMessage.success('更新系统配置成功')
search()
} else {
ElMessage.error(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('更新系统配置失败')
})
}
</script>
<style scoped>
.content {
display: flex;
width: 100%;
}
.work-area {
width: 100%;
/* padding: 5px; */
}
.search-area {
margin: auto;
min-height: fit-content;
max-height: 40%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.table-area {
margin: auto;
min-height: fit-content;
max-height: 60%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.el-form-item {
margin: 5px 5px 5px 5px;
}
.el-form-item .el-input {
width: 196px;
}
.el-form-item .el-select-v2 {
width: 196px;
}
.table-class {
margin: 5px 5px 5px 5px;
width: inherit;
}
.el-pagination {
padding-left: 5px;
}
.my-autocomplete li {
width: 196px;
line-height: normal;
padding: 7px;
}
.my-autocomplete li .name {
text-overflow: ellipsis;
overflow: hidden;
}
.my-autocomplete li .addr {
font-size: 12px;
color: #b4b4b4;
}
.my-autocomplete li .highlighted .addr {
color: #ddd;
}
.my-autocomplete li .goods_id {
color: brown;
}
.my-autocomplete li .goods_name {
color: cornflowerblue;
}
.btn-search {
height: 30px;
width: 80px;
margin: auto 5px 5px auto;
color: black;
}
</style>

View File

@ -0,0 +1,350 @@
<template>
<el-config-provider :locale="zhCn">
<el-container class="content">
<div class="work-area">
<fieldset class="search-area">
<el-form ref="searchQueryFormRef" :model="searchQueryFormEntity" :label-position="labelPosition"
label-width="158px" style="max-width: 100%" status-icon>
<div style="display: flex;justify-content: space-between;">
<el-row>
<el-form-item label="任务类型">
<el-select-v2 style="width: 196px" v-model="searchQueryFormEntity.logType" placeholder="任务类型"
:options="logTypeOptions"
@change="search()"></el-select-v2>
</el-form-item>
<el-form-item label="查询字符">
<el-input v-model="searchQueryFormEntity.queryStr" @keyup.enter="search()" clearable/>
</el-form-item>
</el-row>
<div style="align-content: center;">
<el-row>
<el-button type="primary" class="btn-search" @click="search()">查询</el-button>
<el-button type="warning" class="btn-search" @click="clearQuery()">清除输入</el-button>
</el-row>
</div>
</div>
</el-form>
</fieldset>
<div class="table-area">
<el-table :data="tableData" stripe border v-loading="tableLoading" class="table-class"
:max-height="maxHeight" highlight-current-row @row-click="getCurrentRow"
:header-cell-style="{ 'text-align': 'center' }" :cell-style="{ 'text-align': 'center' }"
@sort-change="handleSortChange">
<el-table-column width="65px" fixed="left">
<template v-slot="scope">
<el-radio :label="scope.row.logId" v-model="logId">&nbsp;</el-radio>
</template>
</el-table-column>
<el-table-column prop="logId" label="日志id" fixed="left" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="logTime" label="记录时间" fixed="right" :formatter="timeFormat" min-width="120px"
sortable="custom"
show-overflow-tooltip/>
<el-table-column v-if="searchQueryFormEntity.logType === 1" prop="method" label="请求方式" fixed="left"
min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column v-if="searchQueryFormEntity.logType === 1" prop="uri" label="请求地址" min-width="120px"
sortable="custom"
show-overflow-tooltip/>
<el-table-column v-if="searchQueryFormEntity.logType === 1" prop="remoteHost" label="客户端主机"
fixed="left" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column v-if="searchQueryFormEntity.logType === 1" prop="remoteAddr" label="客户端地址"
min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column v-if="searchQueryFormEntity.logType === 1" prop="requestContent" label="请求数据"
fixed="left" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column v-if="searchQueryFormEntity.logType === 1" prop="status" label="响应状态" min-width="120px"
sortable="custom"
show-overflow-tooltip/>
<el-table-column v-if="searchQueryFormEntity.logType === 1" prop="responseContent" label="响应数据"
fixed="left" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column v-if="searchQueryFormEntity.logType === 2" prop="url" label="请求地址" fixed="left"
min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column v-if="searchQueryFormEntity.logType === 2" prop="timeout" label="超时时间"
min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column v-if="searchQueryFormEntity.logType === 2" prop="method" label="请求方式"
min-width="120px" sortable="custom" show-overflow-tooltip/>
<el-table-column v-if="searchQueryFormEntity.logType === 2" prop="contentType" label="数据类型"
min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column v-if="searchQueryFormEntity.logType === 2" prop="data" label="请求数据" min-width="120px"
sortable="custom" show-overflow-tooltip/>
<el-table-column v-if="searchQueryFormEntity.logType === 2" prop="token" label="token" fixed="left"
min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column v-if="searchQueryFormEntity.logType === 2" prop="success" label="是否成功"
min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column v-if="searchQueryFormEntity.logType === 2" prop="responseCode" label="响应码"
min-width="120px" sortable="custom" show-overflow-tooltip/>
<el-table-column v-if="searchQueryFormEntity.logType === 2" prop="requestMessage" label="请求信息"
min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column v-if="searchQueryFormEntity.logType === 2" prop="responseMessage" label="响应信息"
min-width="120px"
sortable="custom" show-overflow-tooltip/>
<el-table-column v-if="searchQueryFormEntity.logType === 2" prop="requestTime" label="请求时间" fixed="left"
min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column v-if="searchQueryFormEntity.logType === 2" prop="responseTime" label="响应时间"
min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column v-if="searchQueryFormEntity.logType === 2" prop="useTime" label="耗时" min-width="120px"
sortable="custom"
show-overflow-tooltip/>
<el-table-column v-if="searchQueryFormEntity.logType === 2" prop="exceptionMessage" label="异常信息"
min-width="120px"
sortable="custom" show-overflow-tooltip/>
</el-table>
<br/>
<el-pagination v-model:current-page="baseTableQuery.currentPage"
v-model:page-size="baseTableQuery.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="baseTableQuery.total"/>
</div>
</div>
</el-container>
</el-config-provider>
</template>
<script setup>
import store from '@/store'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import {timeFormatter} from '@/utils/formatter.js'
import {ref, reactive, onMounted, nextTick, onBeforeUnmount} from 'vue'
import {ElMessage} from 'element-plus'
import {genTableRequest} from '@/utils/generator.js'
import {labelPosition} from '@/constant/form.js'
import {queryApisByPage, queryLogsByPage} from "@/api/wmsLog";
/**
* 常量定义
*/
const STAND_ID = store.getters.getStandId
const USER_NAME = store.getters.getUserName
/**
* 变量定义
*/
let maxHeight = ref(window.innerHeight * 0.55)
let tableLoading = ref(false)
let tableData = ref([])
let baseTableQuery = reactive({
currentPage: 1,
pageSize: 10,
total: 0,
sortBy: new Map([['logTime', false]]),//
standId: STAND_ID,
userName: USER_NAME
})
let searchQueryFormEntity = reactive({
logType: 1,
queryStr: ''
})
let searchQueryFormRef = ref()
let logId = ''
const logTypeOptions = [
{
label: '接收日志',
value: 1
},
{
label: '发送日志',
value: 2
}
]
/**
* 系统方法
*/
onMounted(() => {
nextTick(() => {
window.addEventListener('resize', resizeHeight)
search()
})
})
onBeforeUnmount(() => {
nextTick(() => {
window.removeEventListener('resize', resizeHeight)
})
})
const resizeHeight = () => {
maxHeight.value = window.innerHeight * 0.55
}
/**
* 自定义方法
*/
//
const search = () => {
let request = genTableRequest(baseTableQuery)
//
request.queryStr = searchQueryFormEntity.queryStr.trim()
if (searchQueryFormEntity.logType === 1) {
//
queryReceiveLog(request)
} else {
//
querySendLog(request)
}
}
const queryReceiveLog = (request) => {
tableLoading.value = true
queryLogsByPage(request).then((res) => {
const response = res.data
if (response.code === 0) {
const data = response.data
if (data != null) {
tableData.value = data.lists
baseTableQuery.total = data.total
} else {
tableData.value = []
baseTableQuery.total = 0
}
} else {
ElMessage.error(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('查询数据异常。')
}).finally(() => {
tableLoading.value = false
})
}
const querySendLog = (request) => {
tableLoading.value = true
queryApisByPage(request).then((res) => {
const response = res.data
if (response.code === 0) {
const data = response.data
if (data != null) {
tableData.value = data.lists
baseTableQuery.total = data.total
} else {
tableData.value = []
baseTableQuery.total = 0
}
} else {
ElMessage.error(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('查询数据异常。')
}).finally(() => {
tableLoading.value = false
})
}
const clearQuery = () => {
searchQueryFormEntity.vehicleId = ''
searchQueryFormEntity.goodsId = ''
}
const handleSortChange = (data) => {
if (baseTableQuery.sortBy.has(data.prop)) {
baseTableQuery.sortBy.delete(data.prop)
}
baseTableQuery.sortBy.set(data.prop, data.order === 'ascending')
search()
}
const getCurrentRow = (row) => {
logId = row.logId
}
const timeFormat = (row, column, cellValue, index) => {
return timeFormatter(cellValue)
}
</script>
<style scoped>
.content {
display: flex;
width: 100%;
}
.work-area {
width: 100%;
/* padding: 5px; */
}
.search-area {
margin: auto;
min-height: fit-content;
max-height: 40%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.table-area {
margin: auto;
min-height: fit-content;
max-height: 60%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.el-form-item {
margin: 5px 5px 5px 5px;
}
.el-form-item .el-input {
width: 196px;
}
.el-form-item .el-input-number {
width: 196px;
}
.table-class {
margin: 5px 5px 5px 5px;
width: inherit;
}
.el-pagination {
padding-left: 5px;
}
.my-autocomplete li {
width: 196px;
line-height: normal;
padding: 7px;
}
.my-autocomplete li .name {
text-overflow: ellipsis;
overflow: hidden;
}
.my-autocomplete li .addr {
font-size: 12px;
color: #b4b4b4;
}
.my-autocomplete li .highlighted .addr {
color: #ddd;
}
.my-autocomplete li .goods_id {
color: brown;
}
.my-autocomplete li .goods_name {
color: cornflowerblue;
}
.btn-search {
height: 30px;
width: 80px;
margin: auto 5px 5px auto;
color: black;
}
</style>

View File

@ -0,0 +1,797 @@
<template>
<el-config-provider :locale="zhCn">
<el-container class="content">
<div class="work-area">
<fieldset class="search-area">
<el-form ref="searchQueryFormRef" :model="searchQueryFormEntity" :label-position="labelPosition"
label-width="158px" style="max-width: 100%" status-icon>
<div style="display: flex;justify-content: space-between;">
<el-row>
<el-form-item label="数据类型">
<el-select-v2 style="width: 196px" v-model="searchQueryFormEntity.summaryType" placeholder="数据类型"
:options="summaryTypeOptions" @change="search()"></el-select-v2>
</el-form-item>
<el-form-item label="工单号">
<el-input v-model="searchQueryFormEntity.workOrder" @keyup.enter="search()" clearable/>
</el-form-item>
<el-form-item label="料盒号">
<el-input v-model="searchQueryFormEntity.boxNo" @keyup.enter="search()" clearable/>
</el-form-item>
<el-form-item label="成品号">
<el-input v-model="searchQueryFormEntity.productId" @keyup.enter="search()" clearable/>
</el-form-item>
<el-form-item label="单片号">
<el-input v-model="searchQueryFormEntity.singleProductId" @keyup.enter="search()" clearable/>
</el-form-item>
<el-form-item label="工作状态">
<el-select-v2 style="width: 196px" v-model="searchQueryFormEntity.workStatus" placeholder="工作状态"
:options="addAllOptionOfOptions(workStatusOptions)"
@change="search()"></el-select-v2>
</el-form-item>
<el-form-item label="缺料状态">
<el-select-v2 style="width: 196px" v-model="searchQueryFormEntity.lackStatus" placeholder="缺料状态"
:options="addAllOptionOfOptions(lackStatusOptions)"
@change="search()"></el-select-v2>
</el-form-item>
</el-row>
<div style="align-content: center;">
<el-row>
<el-button type="primary" class="btn-search" @click="search()">查询</el-button>
<el-button type="warning" class="btn-search" @click="clearQuery()">清除输入</el-button>
</el-row>
<el-row>
<el-button style="background-color: #00CED1;" class="btn-search"
@click="() => { showPrintDialog = true }">打印标签
</el-button>
<el-button type="success" class="btn-search"
@click="exportExcel()">导出excel
</el-button>
</el-row>
</div>
</div>
</el-form>
</fieldset>
<div class="table-area">
<el-table :data="tableData" stripe border v-loading="tableLoading" class="table-class"
:max-height="maxHeight" highlight-current-row @row-click="getCurrentRow"
:header-cell-style="{ 'text-align': 'center' }" :cell-style="{ 'text-align': 'center' }"
@sort-change="handleSortChange">
<el-table-column width="65px" fixed="left">
<template v-slot="scope">
<el-radio :label="scope.row.workIndex" v-model="workIndex">&nbsp;</el-radio>
</template>
</el-table-column>
<el-table-column prop="workIndex" label="数据编号" fixed="left" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="workOrder" label="工单" fixed="left" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="boxNo" label="料盒号" fixed="left" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="productId" label="成品号" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="singleProductId" label="单片号" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="goodsId" label="料号" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="planStartDate" label="计划开工日期" min-width="120px" :formatter="dateFormat"
sortable="custom" show-overflow-tooltip/>
<el-table-column prop="needNum" label="需求数量" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="distributeNum" label="已分配数量" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="finishNum" label="已完成数量" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="workStand" label="工作站台" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="workUser" label="操作用户" min-width="120px" sortable="custom"
show-overflow-tooltip/>
<el-table-column prop="createTime" label="创建时间" :formatter="timeFormat" min-width="120px"
sortable="custom" show-overflow-tooltip/>
<el-table-column prop="finishTime" label="完成时间" :formatter="timeFormat" min-width="120px"
sortable="custom" show-overflow-tooltip/>
<el-table-column prop="isOut" label="库外料" :formatter="outGoodsFormat" min-width="120px"
sortable="custom" show-overflow-tooltip/>
<el-table-column prop="productType" label="成品类型" :formatter="productTypeFormat"
min-width="120px" sortable="custom" show-overflow-tooltip/>
<el-table-column prop="lackStatus" label="缺料状态" :formatter="lackStatusFormat" fixed="right"
min-width="120px" sortable="custom" show-overflow-tooltip/>
<el-table-column prop="workStatus" label="工作状态" :formatter="workStatusFormat" fixed="right"
min-width="120px" sortable="custom" show-overflow-tooltip/>
<el-table-column fixed="right" label="操作" width="170px" v-if="searchQueryFormEntity.summaryType == 1">
<template v-slot="scope">
<div style="display: inline-block; align-content: center;">
<el-button type="primary" @click="editCurrentRowFormEntity(scope.row)">编辑</el-button>
<el-button type="danger" @click="closeLackWork(scope.row)">关闭</el-button>
</div>
</template>
</el-table-column>
</el-table>
<br/>
<el-pagination v-model:current-page="baseTableQuery.currentPage"
v-model:page-size="baseTableQuery.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="baseTableQuery.total"/>
</div>
<el-dialog v-model="rowEditFlag" title="工作信息" width="40%" draggable :show-close="false"
:close-on-click-modal="false">
<el-form ref="rowEditFormRef" :model="rowFormEntity" :label-position="labelPosition"
label-width="100px" style="max-width: 100%" status-icon>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="工作编号">
<el-input v-model="rowFormEntity.workIndex" disabled/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="工单号">
<el-input v-model="rowFormEntity.workOrder" disabled/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="总成号">
<el-input v-model="rowFormEntity.productId" disabled/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="成品号">
<el-input v-model="rowFormEntity.singleProductId" disabled/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="料盒号">
<el-input v-model="rowFormEntity.boxNo" disabled/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="料号">
<el-input v-model="rowFormEntity.goodsId" disabled/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="需求数量">
<el-input-number v-model.number="rowFormEntity.needNum" controls-position="right"
:min="0" disabled/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="已完成数量">
<el-input-number v-model.number="rowFormEntity.finishNum"
controls-position="right" :min="0" :max="rowFormEntity.needNum" clearable/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="已分配数量">
<el-input-number v-model.number="rowFormEntity.distributeNum"
controls-position="right" :min="0" :max="rowFormEntity.needNum" clearable/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12" :offset="0">
<el-form-item label="工作状态">
<el-select-v2 style="width: 196px;" v-model="rowFormEntity.workStatus" placeholder="请选择工作状态"
:options="workStatusOptions"></el-select-v2>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="缺料状态">
<el-select-v2 style="width: 196px;" v-model="rowFormEntity.lackStatus" placeholder="请选择缺料状态"
:options="lackStatusOptions"></el-select-v2>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="rowEditFlag = false">取消</el-button>
<el-button type="success" @click="submitUpdateRow(rowFormEntity)">
确定
</el-button>
</span>
</template>
</el-dialog>
<el-dialog v-model="showPrintDialog" title="打印标签" width="40%" draggable :close-on-click-modal="false">
<fieldset class="search-area">
<el-form ref="printRequestFormRef" :model="printRequestFormEntity" :label-position="labelPosition"
label-width="158px" style="max-width: 100%" status-icon>
<div style="display: flex;justify-content: space-between;">
<el-row>
<el-form-item label="工单号(必须)">
<el-input v-model="printRequestFormEntity.workOrder" clearable/>
</el-form-item>
<el-form-item label="料盒号(必须)">
<el-input v-model="printRequestFormEntity.boxNo" clearable/>
</el-form-item>
<el-form-item label="单片号(非必须)">
<el-input v-model="printRequestFormEntity.singleProductId" clearable/>
</el-form-item>
</el-row>
<div style="align-content: center;">
<el-row>
<el-button type="primary" class="btn-search" @click="printBoxTags()">打印料盒标签</el-button>
<el-button type="warning" class="btn-search" @click="printLackTags()">打印缺料标签</el-button>
</el-row>
</div>
</div>
</el-form>
</fieldset>
</el-dialog>
<div style="width: 0;height: 0;overflow: hidden">
<button ref="printBtn" style="display: none;" v-print="printObj"></button>
<div id="printArea" class="objectDialogFlowPrint">
<div class="pageWarp" v-for="item in printTabs">
<div class="print-tab-text">
<div class="print-row-normal">工单{{ item.workOrder }}</div>
<div class="print-row-normal">总成{{ item.productId }}</div>
<div class="print-row-normal">单片{{ item.singleProductId }}</div>
<div class="print-row-normal">配料{{ item.kittingDate }}</div>
</div>
<div class="print-tab-text">
<div class="print-row-normal">测试台{{ item.testNo }}</div>
<div class="print-row-normal">产量{{ item.productionQty }}</div>
<div class="print-row-normal">料盒号{{ item.boxNo }}</div>
<div class="print-row-normal">生产{{ item.produceDate }}</div>
</div>
<div class="print-tab-image">
<qrcode-vue
:value="item.imageId"
:size="size" :foreground="color" level="H"/>
</div>
</div>
</div>
</div>
<div style="width: 0;height: 0;overflow: hidden">
<button ref="printLackGoodsBtn" style="display: none;"
v-print="getPrintObj('printLackGoodsArea')"></button>
<div id="printLackGoodsArea" class="objectDialogFlowPrint">
<div class="pageWarp" v-for="item in lackGoodsForPrint">
<div class="print-tab-full" style="margin-left: 30px">
<div class="print-row-big">料盒{{ item.boxNo }}</div>
<div class="print-row-big">料号{{ item.goodsId }}</div>
<div class="print-row-big">需求{{ item.needNum }}</div>
<div class="print-row-big">缺料{{ item.needNum - item.finishNum }}</div>
</div>
</div>
</div>
</div>
</div>
</el-container>
</el-config-provider>
</template>
<script setup>
import store from '@/store'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import {
queryWorkSummaryByPage,
updateKateWorks,
closeCurrentWorks,
requestPrintBoxTags,
getLackGoods
} from '@/api/kateWork.js'
import {dateFormatter, timeFormatter, yesOrNoFormatter} from '@/utils/formatter.js'
import {ref, reactive, onMounted, nextTick, onBeforeUnmount} from 'vue'
import {ElMessage} from 'element-plus'
import {genTableRequest} from '@/utils/generator.js'
import {getPrintObj, labelPosition, printObj} from '@/constant/form.js'
import {summaryTypeOptions, workStatusOptions, lackStatusOptions} from '@/constant/options.js'
import {exportWorkSummaryExcel} from '@/api/excel.js'
import {addAllOptionOfOptions} from '@/utils/generator.js'
import {loading} from '@/utils/loading'
import QrcodeVue from "qrcode.vue";
/**
* 常量定义
*/
const STAND_ID = store.getters.getStandId
const USER_NAME = store.getters.getUserName
/**
* 变量定义
*/
let maxHeight = ref(window.innerHeight * 0.48)
let tableLoading = ref(false)
let tableData = ref([])
let baseTableQuery = reactive({
currentPage: 1,
pageSize: 10,
total: 0,
sortBy: new Map([['productId', true]]),//
standId: STAND_ID,
userName: USER_NAME
})
let searchQueryFormEntity = reactive({
summaryType: 1,
workOrder: '',
productId: '',
singleProductId: '',
boxNo: '',
lackStatus: -99,
workStatus: -99
})
let searchQueryFormRef = ref()
let rowEditFlag = ref(false)
let workIndex = ''
let rowEditFormRef = ref()
let rowFormEntity = reactive({})
let showPrintDialog = ref(false)
let printRequestFormRef = ref()
let printRequestFormEntity = reactive({
workOrder: '',
productId: '',
singleProductId: '',
boxNo: '',
})
let printTabs = ref([])
let lackGoodsForPrint = ref([])
const printBtn = ref()
const printLackGoodsBtn = ref()
const size = ref(35)
const color = ref('#000000')
/**
* 系统方法
*/
onMounted(() => {
nextTick(() => {
window.addEventListener('resize', resizeHeight)
search()
})
})
onBeforeUnmount(() => {
nextTick(() => {
window.removeEventListener('resize', resizeHeight)
})
})
const resizeHeight = () => {
maxHeight.value = window.innerHeight * 0.55
}
/**
* 自定义方法
*/
//
const search = () => {
tableLoading.value = true
let request = genTableRequest(baseTableQuery)
//
request.summaryType = searchQueryFormEntity.summaryType
request.workOrder = searchQueryFormEntity.workOrder.trim()
request.boxNo = searchQueryFormEntity.boxNo.trim()
request.productId = searchQueryFormEntity.productId.trim()
request.singleProductId = searchQueryFormEntity.singleProductId.trim()
request.workStatus = searchQueryFormEntity.workStatus == -99 ? null : searchQueryFormEntity.workStatus
request.lackStatus = searchQueryFormEntity.lackStatus == -99 ? null : searchQueryFormEntity.lackStatus
queryWorkSummaryByPage(request).then((res) => {
const response = res.data
if (response.code == 0) {
const data = response.data
if (data != null) {
tableData.value = data.lists
baseTableQuery.total = data.total
} else {
tableData.value = []
baseTableQuery.total = 0
}
} else {
ElMessage.error(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('查询数据异常。')
}).finally(() => {
tableLoading.value = false
})
}
const clearQuery = () => {
searchQueryFormEntity.workOrder = ''
searchQueryFormEntity.productId = ''
searchQueryFormEntity.singleProductId = ''
searchQueryFormEntity.boxNo = ''
}
const handleSortChange = (data) => {
if (baseTableQuery.sortBy.has(data.prop)) {
baseTableQuery.sortBy.delete(data.prop)
}
baseTableQuery.sortBy.set(data.prop, data.order == 'ascending')
search()
}
const getCurrentRow = (row) => {
workIndex = row.workIndex
}
const dateFormat = (row, column, cellValue, index) => {
return dateFormatter(cellValue)
}
const timeFormat = (row, column, cellValue, index) => {
return timeFormatter(cellValue)
}
const workStatusFormat = (row, column, cellValue, index) => {
switch (cellValue) {
case -1:
return '已暂停'
case 0:
return '未开始'
case 1:
return '已开始'
case 2:
return '已完成'
default:
return '异常'
}
}
const lackStatusFormat = (row, column, cellValue, index) => {
switch (cellValue) {
case 0:
return '不缺料'
case 1:
return '缺料'
default:
return '异常'
}
}
const productTypeFormat = (row, column, cellValue, index) => {
switch (cellValue) {
case 1:
return '非服务件'
case 2:
return '服务件'
default:
return '异常'
}
}
const outGoodsFormat = (row, column, cellValue, index) => {
return yesOrNoFormatter(cellValue)
}
const exportExcel = () => {
const params = {
summaryType: searchQueryFormEntity.summaryType,
workOrder: searchQueryFormEntity.workOrder.trim(),
boxNo: searchQueryFormEntity.boxNo.trim(),
productId: searchQueryFormEntity.productId.trim(),
singleProductId: searchQueryFormEntity.singleProductId.trim(),
workStatus: searchQueryFormEntity.workStatus == -99 ? null : searchQueryFormEntity.workStatus,
lackStatus: searchQueryFormEntity.lackStatus == -99 ? null : searchQueryFormEntity.lackStatus,
standId: STAND_ID,
userName: USER_NAME
}
exportWorkSummaryExcel(params).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) {
console.log(e)
ElMessage.error('下载文件失败')
}
}).catch(err => {
console.log(err)
ElMessage.error('导出失败')
})
}
//
const editCurrentRowFormEntity = (row) => {
// form
rowFormEntity.workIndex = row.workIndex
rowFormEntity.workOrder = row.workOrder
rowFormEntity.productId = row.productId
rowFormEntity.singleProductId = row.singleProductId
rowFormEntity.boxNo = row.boxNo
rowFormEntity.goodsId = row.goodsId
rowFormEntity.needNum = row.needNum
rowFormEntity.distributeNum = row.distributeNum
rowFormEntity.finishNum = row.finishNum
rowFormEntity.workStatus = row.workStatus
rowFormEntity.lackStatus = row.lackStatus
//
rowEditFlag.value = true
}
//
const closeLackWork = (row) => {
const request = {
workIndex: row.workIndex,
standId: STAND_ID,
userName: USER_NAME
}
loading.open('关闭中...')
closeCurrentWorks(request).then(res => {
const response = res.data
if (response.code == 0) {
ElMessage.success(response.message)
search()
} else {
ElMessage.error(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error('请求异常。')
}).finally(() => {
loading.close()
})
}
//
const submitUpdateRow = (rowFormEntity) => {
const request = {
workIndex: rowFormEntity.workIndex,
distributeNum: rowFormEntity.distributeNum,
finishNum: rowFormEntity.finishNum,
workStatus: rowFormEntity.workStatus,
lackStatus: rowFormEntity.lackStatus,
standId: STAND_ID,
userName: USER_NAME
}
loading.open('更新中...')
updateKateWorks(request).then(res => {
if (res.data.code == 0) {
ElMessage.success('更新数据成功。')
rowEditFlag.value = false
search()
} else {
ElMessage.error('更新数据失败。')
}
}).catch(err => {
console.log(err)
ElMessage.error('更新数据异常。')
}).finally(() => {
loading.close()
})
}
//
const printBoxTags = () => {
if (printRequestFormEntity.workOrder.trim() == '' || printRequestFormEntity.boxNo.trim() == '') {
ElMessage.error("工单号、料盒号必须。")
return
}
const requestParam = {
workOrder: printRequestFormEntity.workOrder.trim(),
boxNo: printRequestFormEntity.boxNo.trim(),
productId: printRequestFormEntity.productId.trim(),
singleProductId: printRequestFormEntity.singleProductId.trim(),
standId: STAND_ID,
userName: USER_NAME
}
loading.open('请求标签数据中...')
requestPrintBoxTags(requestParam).then(res => {
const response = res.data
if (response.code == 0) {
getPrintTabs(response.data)
nextTick(() => {
printBtn.value.click()
});
} else {
ElMessage.error(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error("请求发生异常")
}).finally(() => {
loading.close()
})
}
//
const printLackTags = () => {
if (printRequestFormEntity.workOrder.trim() == '' || printRequestFormEntity.boxNo.trim() == '') {
ElMessage.error("工单号、料盒号必须。")
return
}
const requestParam = {
workOrder: printRequestFormEntity.workOrder.trim(),
boxNo: printRequestFormEntity.boxNo.trim(),
productId: printRequestFormEntity.productId.trim(),
singleProductId: printRequestFormEntity.singleProductId.trim(),
standId: STAND_ID,
userName: USER_NAME
}
loading.open('请求缺料数据中...')
getLackGoods(requestParam).then(res => {
const response = res.data
if (response.code == 0) {
lackGoodsForPrint.value = response.data
nextTick(() => {
printLackGoodsBtn.value.click()
});
} else {
ElMessage.error(response.message)
}
}).catch(err => {
console.log(err)
ElMessage.error("请求发生异常")
}).finally(() => {
loading.close()
})
}
//
const getPrintTabs = (boxSummary) => {
printTabs.value = []
if (boxSummary != undefined) {
for (let i = 1; i <= boxSummary.boxQty; i++) {
printTabs.value.push(
{
workOrder: boxSummary.workOrder,
productId: boxSummary.productIdOrigin,
singleProductId: boxSummary.singleProductId,
boxNo: boxSummary.boxNo,
kittingDate: boxSummary.kittingDate,
produceDate: boxSummary.produceDate,
testNo: boxSummary.testNo,
productionQty: boxSummary.productionQty,
imageId: boxSummary.imageId,
}
)
}
}
}
</script>
<style scoped>
.content {
display: flex;
width: 100%;
}
.work-area {
width: 100%;
/* padding: 5px; */
}
.search-area {
margin: auto;
min-height: fit-content;
max-height: 40%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.table-area {
margin: auto;
min-height: fit-content;
max-height: 60%;
margin-bottom: 10px;
min-width: inherit;
border: solid 1px;
border-radius: 10px;
box-shadow: 0px 15px 10px -15px #000;
overflow: auto;
padding: 10px;
}
.el-form-item {
margin: 5px 5px 5px 5px;
}
.el-form-item .el-input {
width: 196px;
}
.el-form-item .el-input-number {
width: 196px;
}
.table-class {
margin: 5px 5px 5px 5px;
width: inherit;
}
.el-pagination {
padding-left: 5px;
}
.my-autocomplete li {
width: 196px;
line-height: normal;
padding: 7px;
}
.my-autocomplete li .name {
text-overflow: ellipsis;
overflow: hidden;
}
.my-autocomplete li .addr {
font-size: 12px;
color: #b4b4b4;
}
.my-autocomplete li .highlighted .addr {
color: #ddd;
}
.my-autocomplete li .goods_id {
color: brown;
}
.my-autocomplete li .goods_name {
color: cornflowerblue;
}
.btn-search {
height: 30px;
width: 100px;
margin: auto 5px 5px auto;
color: black;
}
@media print {
@page {
size: auto;
margin: 0;
}
body,
html {
height: auto !important;
}
}
.objectDialogFlowPrint {
width: 100% !important;
height: 100% !important;
}
.objectDialogFlowPrint .pageWarp {
/*这句话很重要,控制时候强制分页 https://www.w3school.com.cn/cssref/pr_page-break-after.asp*/
page-break-after: always;
width: 100%;
height: 100%;
text-align: center;
padding: 0;
display: flex;
print-color-adjust: exact;
}
.print-tab-text {
width: 40%;
align-content: center;
}
.print-tab-image {
width: 20%;
align-content: center;
}
.print-row-normal {
margin: 8px 3px 8px 3px;
font-size: 13px;
font-weight: bold;
text-align: left;
}
.print-tab-full {
width: 90%;
align-content: center;
}
.print-row-big {
margin: 8px 3px 8px 3px;
font-size: 20px;
font-weight: bold;
text-align: left;
}
.dialog-footer {
display: flex;
justify-content: center;
}
</style>

View File

@ -0,0 +1,20 @@
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'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
const app = createApp(App)
app.use(store)
app.use(router)
app.use(ElementPlus, {locale: zhCn})
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,89 @@
import {createRouter, createWebHashHistory} from 'vue-router'
import HomeView from '@/views/HomeView.vue'
import login from '@/views/login.vue'
import systemCenter from '@/views/SystemCenter.vue'
const routes = [
{
path: '/home',
name: 'home',
component: HomeView,
// redirect: '/stock',
children: [
{path: '/stock', component: () => import('@/layout/stock.vue')},// 库存
{path: '/goodsIn', component: () => import('@/layout/goodsIn.vue')},// 入库
{path: '/goodsOut', component: () => import('@/layout/goodsOut.vue')},// 出库
{path: '/kitting', component: () => import('@/layout/kitting.vue')},// 配料
{path: '/inTaskRecord', component: () => import('@/layout/inTaskRecord.vue')},// 入库记录
{path: '/outTaskRecord', component: () => import('@/layout/outTaskRecord.vue')},// 出库记录
{path: '/location', component: () => import('@/layout/locationsTable.vue')},// 库位
{path: '/goods', component: () => import('@/layout/goods.vue')},// 物料
{path: '/standSettings', component: () => import('@/layout/standSettings.vue')},// 站台(库口)设置
{path: '/config', component: () => import('@/layout/wmsConfigNew.vue')},// 系统配置
{path: '/taskMonitor', component: () => import('@/layout/taskMonitor.vue')},// 任务监控
{path: '/vehicles', component: () => import('@/layout/vehicle.vue')},// 料箱监控
{path: '/inventory', component: () => import('@/layout/inventory.vue')},// 盘点
{path: '/inventoryRecord', component: () => import('@/layout/inventoryRecord.vue')},// 盘点记录
{path: '/wmsLog', component: () => import('@/layout/wmsLog.vue')},// 日志
{path: '/workSummary', component: () => import('@/layout/workSummary.vue')},// 工作总结
{path: '/pickTask', component: () => import('@/layout/pickTaskMonitor.vue')},// 拣选任务
{path: '/outsMonitor', component: () => import('@/layout/OutsMonitor.vue')},// 任务表单
{path: '/clcKanban', component: () => import('@/layout/clcKanban.vue')},// 需求看板
{path: '/stockCompare', component: () => import('@/layout/stockCompare.vue')},
{path: '/stockUpdateRecord', component: () => import('@/layout/stockUpdateRecord.vue')},// 库存更新记录
{path: '/roleUser', component: () => import('@/layout/role_user.vue')},// 角色——用户列表
{path: '/rolePermission', component: () => import('@/layout/role_permission.vue')},// 角色——权限列表
{path: '/test', component: () => import('@/layout/testView.vue')},// 测试
{path: '/dbsList', component: () => import('@/layout/dbsList.vue')},// dbs计划
{path: '/kittingList', component: () => import('@/layout/kittingList.vue')},// 配料单
{path: '/kittingRelation', component: () => import('@/layout/kittingRelation.vue')},// 对应关系
{path: '/imageTable', component: () => import('@/layout/ImageTable.vue')},
{path: '/equipment', component: () => import('@/layout/equipment.vue')},
{path: '/job', component: () => import('@/layout/job.vue')},
{path: '/pickPlan', component: () => import('@/layout/pickPlan.vue')},
{path: '/pickTaskBak', component: () => import('@/layout/pickTaskBak.vue')},
]
},
{
path: '/',
name: 'login',
component: login
},
{
path: '/pda',
name: 'pda',
component: () => import('@/layout/pda.vue')
},
{
path: '/systemCenter',
name: 'systemCenter',
component: systemCenter
},
{
path: '/imageDisplay',
name: 'imageDisplay',
component: () => import('@/layout/imageDisplay.vue')
},
{
path: '/scanForImage',
name: 'scanForImage',
component: () => import('@/layout/scanForImage.vue')
}
]
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,128 @@
import { createStore } from 'vuex'
export default createStore({
state: {
stateTagsList: [],
user: {},
menuList: [],
token: '',
verifier: '',
stand: {},
kittingWork: {
workOrder: '',
productId: '',
singleProduct: '',
boxNo: ''
},
},
getters: {
getStateTagsList(state) {
return state.stateTagsList
},
getUser(state) {
return state.user
},
getUserName(state) {
return state.user.userName
},
getMenuList(state) {
return state.menuList
},
getToken(state) {
return state.token
},
getVerify(state) {
return state.verifier
},
getStand(state) {
return state.stand
},
getStandId(state) {
return state.stand.standId
},
getKittingWork(state) {
return state.kittingWork
},
getMenuItemByPath(state) {
return function (path) {
for (const item of state.menuList) {
for (const subItem of item.children) {
if (subItem.path === path) {
return subItem
}
}
}
return undefined
}
}
},
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)
},
/**
* 存储站台信息
*/
mutationStand(state, data) {
state.stand = data
// sessionStorage.setItem("stand", state.stand)
},
/**
* 存储站台配料信息
*/
mutationKittingWork(state, data) {
state.kittingWork = data
// sessionStorage.setItem("kittingWork", state.kittingWork)
},
/**
* 存储认证
*/
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,19 @@
export const 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('秒')
}

View File

@ -0,0 +1,13 @@
import * as XLSX from 'xlsx'
import {timeFormatter} from "@/utils/formatter";
export const exportToExcel = (excelHead, data, sheetName, fileName) => {
const workBook = XLSX.utils.book_new()
const dataWithHead = [excelHead, ...data]
const worksheet = XLSX.utils.json_to_sheet(dataWithHead, {
skipHeader: true
})
XLSX.utils.book_append_sheet(workBook, worksheet, sheetName)
const fileNameWithTime = fileName + timeFormatter(new Date()) + '.xlsx'
XLSX.writeFile(workBook, fileNameWithTime)
}

View File

@ -0,0 +1,203 @@
import moment from "moment";
import { revertSeconds } from '@/utils/dateUtils'
// 时间格式化
export const timeFormatter = (date) => {
if (date === null || date === undefined || date === '') {
return ''
}
return moment(date).format('yyyy-MM-DD HH:mm:ss');
}
// 日期格式化
export const dateFormatter = (date) => {
if (date === null || date === undefined) {
return ''
}
return moment(date).format('yyyy-MM-DD');
}
// 运行时长格式化
export const dueFormatter = (date) => {
if (date === null || date === undefined) {
return ''
}
return revertSeconds(moment(new Date().getTime()).diff(moment(date), 'seconds'));
}
// 库位格式化
export const locationFormatter = (locationId) => {
if (locationId === null || locationId === undefined || locationId === '') {
return ''
}
const locationArray = locationId.split('-')
if (locationArray.length === 3) {
return locationArray[0] + '排' + locationArray[1] + '列' + locationArray[2] + '层'
} else if (locationArray.length === 4) {
return locationArray[0] + '排' + locationArray[1] + '列' + locationArray[2] + '层' + locationArray[3] + '深度'
} else {
return ''
}
}
// 配置类型格式化
export const configTypeFormatter = (value) => {
switch (value) {
case 1:
return '输入框'
case 2:
return '下拉多选'
case 3:
return '开关'
default:
return '任务类型异常'
}
}
// 文件大小格式化
export const sizeFormatter = (value) => {
if (typeof value != 'number') {
return 'error'
}
const oneByte = 1
const oneKB = oneByte * 1024
const oneMB = oneKB * 1024
const oneGB = oneMB * 1024
const oneTB = oneGB * 1024
const onePB = oneTB * 1024
const oneEB = onePB * 1024
const oneZB = oneEB * 1024
const oneYB = oneZB * 1024
if (value < oneKB) {
return value + 'B'
} else if (value < oneMB) {
return (value / oneKB).toFixed(2) + 'KB'
} else if (value < oneGB) {
return (value / oneMB).toFixed(2) + 'MB'
} else if (value < oneTB) {
return (value / oneGB).toFixed(2) + 'GB'
} else if (value < onePB) {
return (value / oneTB).toFixed(2) + 'TB'
} else if (value < oneEB) {
return (value / onePB).toFixed(2) + 'PB'
} else if (value < oneZB) {
return (value / oneEB).toFixed(2) + 'EB'
} else if (value < oneYB) {
return (value / oneZB).toFixed(2) + 'ZB'
} else {
return (value / oneYB).toFixed(2) + 'YB'
}
}
// json格式化
export const jsonFormatter = (value) => {
if (value == null) {
return ""
}
if (typeof value == 'string') {
try {
return JSON.stringify(JSON.parse(value), null, 4)
} catch (e) {
return "error"
}
} else {
return JSON.stringify(value, null, 4)
}
}
// 去除英文和数字之外的字符
export const replaceEnglishAndNumberIGAI = (value) => {
return value.replace(/[^\u4e00-\u9fa5a-zA-Z0-9]/g, '')
}
// 是否格式化
export const yesOrNoFormatter = (value) => {
return value === 1 ? '是' : '否'
}
// 反转是否格式化
export const converseYesOrNoFormatter = (value) => {
return value === 0 ? '是' : '否'
}
// 任务类型格式化
export const wmsTaskTypeFormatter = (value) => {
switch (value) {
case 1:
return '入库'
case 2:
return '出库'
case 3:
return '盘点'
default:
return '未知类型'
}
}
// wms任务状态格式化
export const wmsTaskStatusFormatter = (value) => {
switch (value) {
case -1:
return '暂存'
case 0:
return '初始化'
case 1:
return '已解析'
case 2:
return '已下发'
case 3:
return '正在执行'
case 4:
return '执行完成'
case 98:
return '已取消'
case 99:
return '执行异常'
default:
return '未知状态'
}
}
// 料箱状态
export const vehicleStatusFormatter = (value) => {
switch (value) {
case 1:
return '入库中'
case 2:
return '在库中'
case 3:
return '出库中'
case 9:
return '锁定中'
default:
return '未知状态'
}
}
// 拣选任务状态
export const pickTaskStatusFormatter = (value) => {
switch (value) {
case -2:
return '入库用'
case -1:
return '暂存中'
case 0:
return '待下发'
case 1:
return '已下发'
case 2:
return '执行中'
case 3:
return '已到达'
case 4:
return '已离开'
case 5:
return '拣选取消'
default:
return '已取消'
}
}
// 出库单类型格式化
export const outTaskTypeFormatter = (value) => {
switch (value) {
case 1:
return '空箱出库'
case 2:
return '普通出库'
case 4:
return '完整出库'
case 5:
return '入库使用'
case 9:
return '紧急出库'
default:
return '未知类型'
}
}

View File

@ -0,0 +1,35 @@
import { toUnderScoreCase } from '@/utils/stringUtils.js'
// 构建table基本请求---带分页
export const genTableRequest = (baseTableQuery) => {
// 构建sortBy的集合
let sortBy = []
for (const [key, value] of baseTableQuery.sortBy) {
sortBy.push({
column: toUnderScoreCase(key),
asc: value
})
}
return {
pageNo: baseTableQuery.currentPage,
pageSize: baseTableQuery.pageSize,
sortBy: sortBy.reverse(),
standId: baseTableQuery.standId,
userName: baseTableQuery.userName
}
}
/**
* 向options中添加全部这个选项
* @param {*} options
* @param defaultValue
* @returns
*/
export const addAllOptionOfOptions = (options, defaultValue) => {
const allOption = [
{
value: defaultValue === undefined || defaultValue === null ? -99 : defaultValue,
label: '全部'
}
]
return allOption.concat(options)
}

View File

@ -0,0 +1,11 @@
import crypto from 'crypto'
export const base64URLEncode = (str) => {
return str.toString('base64')
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=/g, '');
}
export const getHashString = (obj) => {
return base64URLEncode(crypto.createHash('sha256').update(obj).digest())
}

View File

@ -0,0 +1,14 @@
import { ElLoading } from 'element-plus'
export const loading = {
loadingInstance: null,
open: function (text) {
this.loadingInstance = ElLoading.service({
lock: true,
text: text,
background: 'rgba(0, 0, 0, 0.7)'
})
},
close: function () {
this.loadingInstance.close()
}
}

View File

@ -0,0 +1,4 @@
// 语音播报
export const speak = (message) => {
window.speechSynthesis.speak(new SpeechSynthesisUtterance(message))
}

View File

@ -0,0 +1,69 @@
import { ElMessageBox } from 'element-plus'
export const errorBox = (msg) => {
ElMessageBox.alert(msg, '错误', {
autofocus: true,
confirmButtonText: '确认',
center: true,
type: 'error',
closeOnPressEscape: true,
showClose: false,
customStyle: {
whiteSpace: 'pre-wrap'
},
callback: (action) => {
}
})
}
export const successBox = (msg) => {
ElMessageBox.alert(msg, '成功', {
autofocus: true,
confirmButtonText: '确认',
center: true,
type: 'success',
closeOnPressEscape: true,
showClose: false,
customStyle: {
whiteSpace: 'pre-wrap'
},
callback: (action) => {
}
})
}
export const infoBox = (msg) => {
ElMessageBox.alert(msg, '提示', {
autofocus: true,
confirmButtonText: '确认',
center: true,
type: 'info',
closeOnPressEscape: true,
showClose: false,
customStyle: {
whiteSpace: 'pre-wrap'
},
callback: (action) => {
}
})
}
export const warningBox = (msg) => {
ElMessageBox.alert(msg, '警告', {
autofocus: true,
confirmButtonText: '确认',
center: true,
type: 'warning',
closeOnPressEscape: true,
showClose: false,
customStyle: {
whiteSpace: 'pre-wrap'
},
callback: (action) => {
}
})
}

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