新增看板代码以及配套的电视机浏览器apk
This commit is contained in:
parent
8567c728ca
commit
e6789f9d91
8
.idea/.gitignore
vendored
Normal file
8
.idea/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
# 默认忽略的文件
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# 基于编辑器的 HTTP 客户端请求
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
23
board/CODE/.gitignore
vendored
Normal file
23
board/CODE/.gitignore
vendored
Normal 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?
|
||||
19
board/CODE/README.md
Normal file
19
board/CODE/README.md
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# wms_stand
|
||||
|
||||
## Project setup
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
### Compiles and hot-reloads for development
|
||||
```
|
||||
npm run serve
|
||||
```
|
||||
|
||||
### Compiles and minifies for production
|
||||
```
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Customize configuration
|
||||
See [Configuration Reference](https://cli.vuejs.org/config/).
|
||||
5
board/CODE/babel.config.js
Normal file
5
board/CODE/babel.config.js
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
module.exports = {
|
||||
presets: [
|
||||
'@vue/cli-plugin-babel/preset'
|
||||
]
|
||||
}
|
||||
19
board/CODE/jsconfig.json
Normal file
19
board/CODE/jsconfig.json
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"module": "esnext",
|
||||
"baseUrl": "./",
|
||||
"moduleResolution": "node",
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"src/*"
|
||||
]
|
||||
},
|
||||
"lib": [
|
||||
"esnext",
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"scripthost"
|
||||
]
|
||||
}
|
||||
}
|
||||
10813
board/CODE/package-lock.json
generated
Normal file
10813
board/CODE/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
32
board/CODE/package.json
Normal file
32
board/CODE/package.json
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"name": "wms_stand",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.7.9",
|
||||
"core-js": "^3.8.3",
|
||||
"element-plus": "^2.9.4",
|
||||
"fullscreen": "^1.1.1",
|
||||
"vue": "^3.2.13",
|
||||
"vue-router": "^4.0.3",
|
||||
"vuex": "^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@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.32.7",
|
||||
"sass-loader": "^12.0.0"
|
||||
},
|
||||
"browserslist": [
|
||||
"> 1%",
|
||||
"last 2 versions",
|
||||
"not dead",
|
||||
"not ie 11"
|
||||
]
|
||||
}
|
||||
BIN
board/CODE/public/favicon.ico
Normal file
BIN
board/CODE/public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
17
board/CODE/public/index.html
Normal file
17
board/CODE/public/index.html
Normal 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>丰尚立库状态一览表</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>
|
||||
214
board/CODE/src/App.vue
Normal file
214
board/CODE/src/App.vue
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
<template>
|
||||
<div class="layout">
|
||||
<header class="navbar">
|
||||
<div class="brand">{{ dynamicTitle }}</div>
|
||||
<div class="control-buttons">
|
||||
<button
|
||||
v-show="!isFullscreenState"
|
||||
@click="enterFullscreen"
|
||||
class="hidBtn fullscreen-btn"
|
||||
>
|
||||
全屏
|
||||
</button>
|
||||
<button
|
||||
v-show="isFullscreenState"
|
||||
@click="exitFullscreen"
|
||||
class="hidBtn exit-btn"
|
||||
>
|
||||
退出
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
<main class="content">
|
||||
<component :is="currentComponent" />
|
||||
</main>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref, onMounted, onUnmounted, computed } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import Inbound from './views/Inbound.vue';
|
||||
import Outbound from './views/Outbound.vue';
|
||||
import Pick from './views/Pick.vue';
|
||||
|
||||
// 使用传统函数语法替换箭头函数,并添加浏览器兼容性检查
|
||||
function debounce(fn, delay) {
|
||||
var timer = null;
|
||||
return function () {
|
||||
var context = this;
|
||||
var args = arguments;
|
||||
clearTimeout(timer);
|
||||
timer = setTimeout(function () {
|
||||
fn.apply(context, args);
|
||||
}, delay);
|
||||
};
|
||||
}
|
||||
|
||||
// 条件性使用 ResizeObserver 以避免低版本浏览器报错
|
||||
if (window.ResizeObserver) {
|
||||
var _ResizeObserver = window.ResizeObserver;
|
||||
window.ResizeObserver = function ResizeObserver(callback) {
|
||||
callback = debounce(callback, 16);
|
||||
_ResizeObserver.call(this, callback);
|
||||
};
|
||||
window.ResizeObserver.prototype = Object.create(_ResizeObserver.prototype);
|
||||
window.ResizeObserver.prototype.constructor = window.ResizeObserver;
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'App',
|
||||
components: {
|
||||
Inbound,
|
||||
Outbound,
|
||||
Pick
|
||||
},
|
||||
setup() {
|
||||
const route = useRoute();
|
||||
const isFullscreenState = ref(false);
|
||||
|
||||
// 获取当前standId - 使用更兼容的参数解析方式
|
||||
const currentStandId = computed(() => {
|
||||
// 为不支持 URLSearchParams 的浏览器提供备选方案
|
||||
if (window.URLSearchParams) {
|
||||
var params = new URLSearchParams(window.location.search);
|
||||
return params.get('standId');
|
||||
} else {
|
||||
// 手动解析查询参数
|
||||
var match = window.location.search.match(/[?&]standId=([^&]*)/);
|
||||
return match ? decodeURIComponent(match[1]) : null;
|
||||
}
|
||||
});
|
||||
|
||||
// 动态标题映射
|
||||
const titleMapping = {
|
||||
'1': '入库',
|
||||
'2': '出库',
|
||||
'3': '拣选'
|
||||
};
|
||||
|
||||
// 动态标题
|
||||
const dynamicTitle = computed(() => {
|
||||
var standId = currentStandId.value;
|
||||
if (!standId) {
|
||||
// 没有standId时,显示默认标题,立库和状态之间留出两个字空格空间
|
||||
return '丰尚立库 状态一览表';
|
||||
}
|
||||
var operation = titleMapping[standId];
|
||||
if (operation) {
|
||||
return '丰尚立库 ' + operation + ' 状态一览表';
|
||||
}
|
||||
// 如果standId不在映射中,显示默认标题
|
||||
return '丰尚立库 状态一览表';
|
||||
});
|
||||
|
||||
// 根据standId动态选择组件
|
||||
const currentComponent = computed(() => {
|
||||
var standId = currentStandId.value;
|
||||
if (standId === '2') return 'Outbound';
|
||||
if (standId === '3') return 'Pick';
|
||||
return 'Inbound'; // 默认显示入库组件
|
||||
});
|
||||
|
||||
// 全屏功能相关函数 - 使用传统函数语法
|
||||
function isFullscreen() {
|
||||
return !!(document.fullscreenElement ||
|
||||
document.webkitFullscreenElement ||
|
||||
document.mozFullScreenElement ||
|
||||
document.msFullscreenElement);
|
||||
}
|
||||
|
||||
function requestFS(el) {
|
||||
if (el.requestFullscreen) return el.requestFullscreen();
|
||||
if (el.webkitRequestFullscreen) return el.webkitRequestFullscreen();
|
||||
if (el.mozRequestFullScreen) return el.mozRequestFullScreen();
|
||||
if (el.msRequestFullscreen) return el.msRequestFullscreen();
|
||||
}
|
||||
|
||||
function exitFS() {
|
||||
if (document.exitFullscreen) return document.exitFullscreen();
|
||||
if (document.webkitExitFullscreen) return document.webkitExitFullscreen();
|
||||
if (document.mozCancelFullScreen) return document.mozCancelFullScreen();
|
||||
if (document.msExitFullscreen) return document.msExitFullscreen();
|
||||
}
|
||||
|
||||
// 添加更完善的检测和错误处理
|
||||
function enterFullscreen() {
|
||||
try {
|
||||
// 检查是否支持任何全屏 API
|
||||
var supportsFullscreen = !!(document.fullscreenEnabled ||
|
||||
document.webkitFullscreenEnabled ||
|
||||
document.mozFullScreenEnabled ||
|
||||
document.msFullscreenEnabled);
|
||||
|
||||
if (!supportsFullscreen) {
|
||||
console.warn('Fullscreen not supported');
|
||||
return;
|
||||
}
|
||||
|
||||
requestFS(document.documentElement);
|
||||
isFullscreenState.value = true;
|
||||
} catch (err) {
|
||||
console.error('Error attempting to enable full-screen mode:', err);
|
||||
}
|
||||
}
|
||||
|
||||
function exitFullscreen() {
|
||||
try {
|
||||
exitFS();
|
||||
isFullscreenState.value = false;
|
||||
} catch (err) {
|
||||
console.error('Error attempting to exit full-screen mode:', err);
|
||||
}
|
||||
}
|
||||
|
||||
function handleFullscreenChange() {
|
||||
isFullscreenState.value = isFullscreen();
|
||||
}
|
||||
|
||||
// 使用传统事件绑定方式以提高兼容性
|
||||
function addEventListenerCompat(element, event, handler) {
|
||||
if (element.addEventListener) {
|
||||
element.addEventListener(event, handler);
|
||||
} else if (element.attachEvent) {
|
||||
element.attachEvent('on' + event, handler);
|
||||
}
|
||||
}
|
||||
|
||||
function removeEventListenerCompat(element, event, handler) {
|
||||
if (element.removeEventListener) {
|
||||
element.removeEventListener(event, handler);
|
||||
} else if (element.detachEvent) {
|
||||
element.detachEvent('on' + event, handler);
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
isFullscreenState.value = isFullscreen();
|
||||
addEventListenerCompat(document, 'fullscreenchange', handleFullscreenChange);
|
||||
addEventListenerCompat(document, 'webkitfullscreenchange', handleFullscreenChange);
|
||||
addEventListenerCompat(document, 'mozfullscreenchange', handleFullscreenChange);
|
||||
addEventListenerCompat(document, 'MSFullscreenChange', handleFullscreenChange);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
removeEventListenerCompat(document, 'fullscreenchange', handleFullscreenChange);
|
||||
removeEventListenerCompat(document, 'webkitfullscreenchange', handleFullscreenChange);
|
||||
removeEventListenerCompat(document, 'mozfullscreenchange', handleFullscreenChange);
|
||||
removeEventListenerCompat(document, 'MSFullscreenChange', handleFullscreenChange);
|
||||
});
|
||||
|
||||
return {
|
||||
dynamicTitle,
|
||||
currentComponent,
|
||||
isFullscreenState,
|
||||
enterFullscreen: enterFullscreen,
|
||||
exitFullscreen: exitFullscreen
|
||||
};
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@import './assets/board-styles.css';
|
||||
</style>
|
||||
161
board/CODE/src/assets/board-styles.css
Normal file
161
board/CODE/src/assets/board-styles.css
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
:root {
|
||||
--bg: #ffffff;
|
||||
--text: #141a29;
|
||||
--muted: #5b6b8a;
|
||||
--brand: #3756b5;
|
||||
--header: #142357;
|
||||
--border: #20315e;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html, body, #app {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
background: var(--bg);
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.board-title {
|
||||
font-size: 22px;
|
||||
margin: 0 0 12px 4px;
|
||||
color: var(--brand);
|
||||
}
|
||||
|
||||
.table-wrapper {
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--border);
|
||||
box-shadow: 0 4px 16px rgba(0,0,0,.35);
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
thead th {
|
||||
background: var(--header);
|
||||
color: #fff;
|
||||
padding: 12px 10px;
|
||||
font-weight: 700;
|
||||
font-size: 18px;
|
||||
text-align: center;
|
||||
border-right: 2px solid rgba(255,255,255,0.3);
|
||||
}
|
||||
|
||||
thead th:last-child {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
tbody td {
|
||||
padding: 12px 10px;
|
||||
text-align: center;
|
||||
border-top: 1px solid #e0e6f3;
|
||||
border-right: 2px solid #d2d9eb;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
tbody td:last-child {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.empty-row td {
|
||||
color: #8fa3d6;
|
||||
padding: 24px 0;
|
||||
}
|
||||
|
||||
.muted {
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.legend {
|
||||
margin: 10px 4px 0;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.layout {
|
||||
background: var(--bg);
|
||||
min-height: 100vh;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.navbar {
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 12px 20px 22px;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.navbar::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: -14px;
|
||||
border-bottom: 1px dashed #e0e6f3;
|
||||
}
|
||||
|
||||
.brand {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 10px;
|
||||
transform: translateX(-50%);
|
||||
font-weight: 700;
|
||||
color: var(--brand);
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
.control-buttons {
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
top: 8px;
|
||||
}
|
||||
|
||||
.hidBtn {
|
||||
width: 60px;
|
||||
height: 30px;
|
||||
border: transparent;
|
||||
background: white;
|
||||
color: transparent;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.hidBtn:hover {
|
||||
background: #30f1e6;
|
||||
border: #2c3e50 solid 2px;
|
||||
color: #2c3e50;
|
||||
}
|
||||
|
||||
.fullscreen-btn {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.exit-btn {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.links a {
|
||||
color: #3552a8;
|
||||
margin-left: 16px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.links a.router-link-active {
|
||||
color: #0f1f57;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 24px 24px 40px;
|
||||
}
|
||||
BIN
board/CODE/src/assets/img.png
Normal file
BIN
board/CODE/src/assets/img.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
BIN
board/CODE/src/assets/logo.png
Normal file
BIN
board/CODE/src/assets/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.7 KiB |
83
board/CODE/src/components/DataTable.vue
Normal file
83
board/CODE/src/components/DataTable.vue
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
<template>
|
||||
<div class="table-wrapper">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th v-for="col in columns" :key="col.key">{{ col.title }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-if="!data?.length" class="empty-row"><td :colspan="columns.length">暂无数据</td></tr>
|
||||
<tr v-for="(row, idx) in data" :key="idx">
|
||||
<td v-for="col in columns" :key="col.key">{{ formatCell(row, col) }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {compileToFunction} from "vue";
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
columns: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
});
|
||||
|
||||
function formatCell(row, col){
|
||||
const v = row?.[col.key];
|
||||
return col.formatter ? col.formatter(v, row) : (v ?? '');
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.table-wrapper {
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
border: 1px solid #20315e;
|
||||
box-shadow: 0 4px 16px rgba(0,0,0,.35);
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
thead th {
|
||||
background: #142357;
|
||||
color: #fff;
|
||||
padding: 12px 10px;
|
||||
font-weight: 700;
|
||||
font-size: 18px;
|
||||
text-align: center;
|
||||
border-right: 2px solid rgba(255,255,255,0.3);
|
||||
}
|
||||
|
||||
thead th:last-child {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
tbody td {
|
||||
padding: 12px 10px;
|
||||
text-align: center;
|
||||
border-top: 1px solid #e0e6f3;
|
||||
border-right: 2px solid #d2d9eb;
|
||||
color: #141a29;
|
||||
}
|
||||
|
||||
tbody td:last-child {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.empty-row td {
|
||||
color: #8fa3d6;
|
||||
padding: 24px 0;
|
||||
}
|
||||
</style>
|
||||
20
board/CODE/src/http/base.js
Normal file
20
board/CODE/src/http/base.js
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
import axios from "axios";
|
||||
|
||||
if(process.env.NODE_ENV === 'development') {
|
||||
axios.defaults.baseURL = 'http://localhost:9980';
|
||||
}else {
|
||||
axios.defaults.baseURL = 'http://172.18.222.253:12315';
|
||||
}
|
||||
//axios.defaults.headers.post['Content-Type'] = 'application/json';
|
||||
//axios.defaults.responseType = 'application/json'
|
||||
axios.defaults.timeout = 10000
|
||||
|
||||
axios.interceptors.request.use(function (config) {
|
||||
// 在发送请求之前做些什么
|
||||
config.headers.set('Content-Type', 'application/json');
|
||||
return config;
|
||||
}, function (error) {
|
||||
// 对请求错误做些什么
|
||||
return Promise.reject(error);
|
||||
});
|
||||
export default axios;
|
||||
8
board/CODE/src/http/get-data.js
Normal file
8
board/CODE/src/http/get-data.js
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
import axios from "@/http/base";
|
||||
|
||||
export default {
|
||||
|
||||
getData(data) {
|
||||
return axios.post("/api/wms/GetCkTaskList", data);
|
||||
}
|
||||
};
|
||||
9
board/CODE/src/main.js
Normal file
9
board/CODE/src/main.js
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
import store from './store'
|
||||
import installElementPlus from './plugins/element'
|
||||
|
||||
const app = createApp(App)
|
||||
installElementPlus(app);
|
||||
app.use(store).use(router).mount('#app')
|
||||
7
board/CODE/src/plugins/element.js
Normal file
7
board/CODE/src/plugins/element.js
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
import ElementPlus from 'element-plus'
|
||||
import 'element-plus/theme-chalk/index.css'
|
||||
import locale from 'element-plus/es/locale/lang/zh-cn'
|
||||
|
||||
export default (app) => {
|
||||
app.use(ElementPlus, { locale })
|
||||
}
|
||||
21
board/CODE/src/router/index.js
Normal file
21
board/CODE/src/router/index.js
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
import { createRouter, createWebHashHistory } from 'vue-router'
|
||||
import HomeView from '../views/HomeView.vue'
|
||||
|
||||
const routes = [
|
||||
{
|
||||
path: '/',
|
||||
redirect: '/home',
|
||||
},
|
||||
{
|
||||
path: '/home',
|
||||
name: 'home',
|
||||
component: HomeView
|
||||
},
|
||||
]
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHashHistory(),
|
||||
routes
|
||||
})
|
||||
|
||||
export default router
|
||||
52
board/CODE/src/services/api.js
Normal file
52
board/CODE/src/services/api.js
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
import axios from 'axios';
|
||||
|
||||
// 生产环境默认同源,开发可由 .env 覆盖
|
||||
const baseURL = process.env.VUE_APP_API_BASE_URL || (typeof window !== 'undefined' ? `${window.location.protocol}//${window.location.hostname}:12315` : '');
|
||||
|
||||
export const http = axios.create({ baseURL, timeout: 15000 });
|
||||
|
||||
export async function queryTasksByPage(params) {
|
||||
const { data } = await http.post('/wms/taskQuery/queryTasksByPage', params);
|
||||
return data?.data;
|
||||
}
|
||||
|
||||
export async function queryPickTasksByPage(params) {
|
||||
const { data } = await http.post('/wms/taskQuery/queryPickTasksByPage', params);
|
||||
return data?.data;
|
||||
}
|
||||
|
||||
export async function queryPickPlansByPage(params) {
|
||||
const { data } = await http.post('/wms/pickPlan/queryPickPlansByPage', params);
|
||||
return data?.data;
|
||||
}
|
||||
|
||||
export async function getGoodsInfoByGoodsId(goodsId) {
|
||||
const { data } = await http.get('/wms/goods/getGoodsInfoByGoodsId', { params: { goodsId } });
|
||||
return data?.data;
|
||||
}
|
||||
|
||||
export async function queryOutsByPage(params) {
|
||||
const { data } = await http.post('/wms/taskQuery/queryOutsByPage', params);
|
||||
return data?.data;
|
||||
}
|
||||
|
||||
export async function queryStocks(params) {
|
||||
const { data } = await http.post('/wms/stock/queryStocks', params);
|
||||
return data?.data;
|
||||
}
|
||||
|
||||
// 新增的看板数据接口
|
||||
export async function getTaskTypInData(params = {}) {
|
||||
const { data } = await http.get('/wms/board/getTaskTypInData', { params });
|
||||
return data;
|
||||
}
|
||||
|
||||
export async function getOutsData(params = {}) {
|
||||
const { data } = await http.get('/wms/board/getOutsData', { params });
|
||||
return data;
|
||||
}
|
||||
|
||||
export async function getPickTaskData(params = {}) {
|
||||
const { data } = await http.get('/wms/board/getPickTaskData', { params });
|
||||
return data;
|
||||
}
|
||||
14
board/CODE/src/store/index.js
Normal file
14
board/CODE/src/store/index.js
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import { createStore } from 'vuex'
|
||||
|
||||
export default createStore({
|
||||
state: {
|
||||
},
|
||||
getters: {
|
||||
},
|
||||
mutations: {
|
||||
},
|
||||
actions: {
|
||||
},
|
||||
modules: {
|
||||
}
|
||||
})
|
||||
100
board/CODE/src/views/HomeView.vue
Normal file
100
board/CODE/src/views/HomeView.vue
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
<template>
|
||||
<div class="home">
|
||||
<el-row style="width: 100%">
|
||||
<h1 style="margin-left: auto; margin-right: auto">成品仓智能仓 {{route.query.standId}} 号线出库状态一览表</h1>
|
||||
</el-row>
|
||||
<el-divider style="margin-top: 0" />
|
||||
<el-row style="margin-right: 20px;margin-left: 20px;">
|
||||
<el-table :data="tableData" :border="true" :header-cell-style="headerStyle" :row-style="dataStyle">
|
||||
<el-table-column prop="plcid" label="任务号" width="150" align="center"></el-table-column>
|
||||
<el-table-column prop="customer_id" label="客户代码" align="center"></el-table-column>
|
||||
<el-table-column prop="good_id" label="产品编号" align="center"></el-table-column>
|
||||
<el-table-column prop="loc_id" label="库位" align="center"></el-table-column>
|
||||
<el-table-column prop="docctnumber" label="周期" align="center"></el-table-column>
|
||||
<el-table-column prop="mistock_num" label="数量" align="center"></el-table-column>
|
||||
<el-table-column prop="status" label="出库状态位置" align="center"></el-table-column>
|
||||
</el-table>
|
||||
</el-row>
|
||||
<div style="font-size: 1.5rem; color: #ab0a07;position: fixed;left: 10px; bottom:10px">精心·精品</div>
|
||||
<img src="@/assets/img.png" alt="logo" style="position: fixed;bottom: 10px; right: 10px"/>
|
||||
<img src="@/assets/img.png" alt="logo" style="position: fixed;top: 20px; left: 10px"/>
|
||||
<button class="hidBtn" style="position: fixed;top: 10px; right: 10px;" @click="fullScreenFuc">全屏</button>
|
||||
<button class="hidBtn" style="position: fixed;top: 10px; right: 70px;" @click="outScreenFuc">退出</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
|
||||
import {onMounted, ref} from "vue";
|
||||
import {useRoute} from 'vue-router';
|
||||
import getData from "@/http/get-data";
|
||||
|
||||
// 获取路由对象
|
||||
const route = useRoute();
|
||||
|
||||
const standId = ref("50");
|
||||
let tableData = ref([]);
|
||||
const headerStyle = ref((row, index) => {
|
||||
return {
|
||||
fontSize: "1.5rem",
|
||||
color: "#fff",
|
||||
backgroundColor: "#1f2964",
|
||||
marginTop: "10px",
|
||||
paddingTop: "10px",
|
||||
paddingBottom: "10px",
|
||||
textAlign: "center",
|
||||
}
|
||||
});
|
||||
|
||||
const dataStyle = ref((row, index) => {
|
||||
return {
|
||||
fontSize: "1.5rem",
|
||||
color: "#454444",
|
||||
}
|
||||
});
|
||||
|
||||
const fullScreenFuc = () => {
|
||||
document.documentElement.requestFullscreen();
|
||||
}
|
||||
const outScreenFuc = () => {
|
||||
document.exitFullscreen();
|
||||
}
|
||||
// 解析url获取站台
|
||||
const resolveStand = () => {
|
||||
standId.value = route.query.standId.toString();
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
tableData.value = [];
|
||||
//resolveStand();
|
||||
setInterval(() => {
|
||||
getData.getData({ PORT: route.query.standId }).then(res => {
|
||||
const response = res.data;
|
||||
if(response.code === 0) {
|
||||
tableData.value = response.data;
|
||||
return;
|
||||
}
|
||||
console.log(response);
|
||||
}).catch(err => {
|
||||
console.log(err);
|
||||
})
|
||||
}, 5000)
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.hidBtn {
|
||||
width: 60px;height: 30px;
|
||||
border: transparent;
|
||||
background: white;
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
.hidBtn:hover {
|
||||
background: #30f1e6;
|
||||
border: #2c3e50 solid 2px;
|
||||
color: #2c3e50;
|
||||
}
|
||||
</style>
|
||||
84
board/CODE/src/views/Inbound.vue
Normal file
84
board/CODE/src/views/Inbound.vue
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
<template>
|
||||
<div>
|
||||
<DataTable :columns="columns" :data="rows" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, onUnmounted } from 'vue';
|
||||
import DataTable from '../components/DataTable.vue';
|
||||
import { getTaskTypInData } from '../services/api';
|
||||
|
||||
// 入库字段
|
||||
const columns = [
|
||||
{ key: 'vehicleId', title: '料箱号' },
|
||||
{ key: 'origin', title: '起点' },
|
||||
{ key: 'destination', title: '终点' },
|
||||
{ key: 'taskPriority', title: '优先级' },
|
||||
{ key: 'taskStatus', title: '状态' },
|
||||
];
|
||||
|
||||
const rows = ref([]);
|
||||
let timer = null;
|
||||
|
||||
function mapStatus(status) {
|
||||
const code = Number(status);
|
||||
// 对齐后端 WmsStackerTaskStatusEnums
|
||||
switch (code) {
|
||||
case -2: return '定时器用';
|
||||
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 String(status ?? '');
|
||||
}
|
||||
}
|
||||
|
||||
async function load() {
|
||||
// 参考 HomeView.vue 的写法,使用 .then().catch() 方式处理异步请求
|
||||
getTaskTypInData({ pageNum: 1, pageSize: 200 }).then(res => {
|
||||
// 检查响应结构,类似 HomeView.vue 中的处理方式
|
||||
if (res && res.code === 0) {
|
||||
const list = res.data || [];
|
||||
rows.value = list.map((t) => ({
|
||||
vehicleId: t?.vehicleId ?? '',
|
||||
origin: t?.origin ?? t?.startPoint ?? '',
|
||||
destination: t?.destination ?? t?.endPoint ?? '',
|
||||
taskPriority: (
|
||||
t?.task_priority ??
|
||||
t?.taskPriority ??
|
||||
t?.priority ??
|
||||
t?.priorityLevel ??
|
||||
''
|
||||
),
|
||||
taskStatus: mapStatus(t?.taskStatus ?? t?.status),
|
||||
}));
|
||||
} else {
|
||||
console.log('API response:', res);
|
||||
}
|
||||
}).catch(error => {
|
||||
console.error('加载入库数据失败:', error);
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
load();
|
||||
timer = setInterval(load, 5000);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
if (timer) {
|
||||
clearInterval(timer);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.title-center {
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
56
board/CODE/src/views/Outbound.vue
Normal file
56
board/CODE/src/views/Outbound.vue
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
<template>
|
||||
<div>
|
||||
<DataTable :columns="columns" :data="rows" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, onUnmounted } from 'vue';
|
||||
import DataTable from '../components/DataTable.vue';
|
||||
import { getOutsData } from '../services/api';
|
||||
|
||||
// 出库字段(与数据库一致:物料号、需求数量、分配数量、拣选数量、原因)
|
||||
const columns = [
|
||||
{ key: 'goodsId', title: '物料号' },
|
||||
{ key: 'needNum', title: '需求数量' },
|
||||
{ key: 'distributeNum', title: '分配数量' },
|
||||
{ key: 'pickNum', title: '拣选数量' },
|
||||
{ key: 'reason', title: '原因' },
|
||||
];
|
||||
|
||||
const rows = ref([]);
|
||||
let timer = null;
|
||||
|
||||
async function load() {
|
||||
try {
|
||||
const outsData = await getOutsData({ pageNum: 1, pageSize: 500 });
|
||||
const outs = outsData || [];
|
||||
rows.value = outs.map((o) => ({
|
||||
goodsId: o?.goodsId ?? '',
|
||||
needNum: Number(o?.needNum ?? 0),
|
||||
distributeNum: Number(o?.distribute_num ?? o?.distributeNum ?? o?.allocNum ?? o?.allocateNum ?? 0),
|
||||
pickNum: Number(o?.pick_num ?? o?.pickNum ?? 0),
|
||||
reason: o?.reason ?? o?.reasonDesc ?? '',
|
||||
}));
|
||||
} catch (error) {
|
||||
console.error('加载出库数据失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
load();
|
||||
timer = setInterval(load, 5000);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
if (timer) {
|
||||
clearInterval(timer);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.title-center {
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
72
board/CODE/src/views/Pick.vue
Normal file
72
board/CODE/src/views/Pick.vue
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
<template>
|
||||
<div>
|
||||
<DataTable :columns="columns" :data="rows" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, onUnmounted } from 'vue';
|
||||
import DataTable from '../components/DataTable.vue';
|
||||
import { getPickTaskData } from '../services/api';
|
||||
|
||||
// 拣选字段
|
||||
const columns = [
|
||||
{ key: 'vehicleId', title: '料箱号' },
|
||||
{ key: 'pickStand', title: '拣选站台' },
|
||||
{ key: 'createTime', title: '创建时间' },
|
||||
{ key: 'arriveTime', title: '到达时间' },
|
||||
{ key: 'pickStatus', title: '状态' },
|
||||
];
|
||||
|
||||
const rows = ref([]);
|
||||
let timer = null;
|
||||
|
||||
function mapStatus(status) {
|
||||
const code = Number(status);
|
||||
// 对齐后端 WmsPickTaskStatusEnum
|
||||
switch (code) {
|
||||
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 String(status ?? '');
|
||||
}
|
||||
}
|
||||
|
||||
async function load() {
|
||||
try {
|
||||
const tasksData = await getPickTaskData({ pageNum: 1, pageSize: 1000 });
|
||||
const tasks = tasksData || [];
|
||||
rows.value = tasks.map((t) => ({
|
||||
vehicleId: t?.vehicleId ?? '',
|
||||
pickStand: t?.pickStand ?? t?.pick_stand ?? t?.pickStation ?? t?.station ?? '',
|
||||
createTime: t?.createTime ?? t?.gmtCreate ?? '',
|
||||
arriveTime: t?.arriveTime ?? t?.reachTime ?? '',
|
||||
pickStatus: mapStatus(t?.pickStatus ?? t?.pick_status ?? t?.taskStatus ?? t?.status),
|
||||
}));
|
||||
} catch (error) {
|
||||
console.error('加载拣选数据失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
load();
|
||||
timer = setInterval(load, 5000);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
if (timer) {
|
||||
clearInterval(timer);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.title-center {
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
14
board/CODE/vue.config.js
Normal file
14
board/CODE/vue.config.js
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
const { defineConfig } = require('@vue/cli-service')
|
||||
module.exports = defineConfig({
|
||||
transpileDependencies: true,
|
||||
chainWebpack: (config) => {
|
||||
config.plugin('define').tap((defineConfig) => {
|
||||
Object.assign(defineConfig[0], {
|
||||
__VUE_OPTIONS_API__: 'true',
|
||||
__VUE_PROD_DEVTOOLS__: false,
|
||||
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: false
|
||||
})
|
||||
return defineConfig
|
||||
})
|
||||
}
|
||||
})
|
||||
BIN
board/电视APK/BrowseHere.apk
Normal file
BIN
board/电视APK/BrowseHere.apk
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user