工单看板大屏BI
This commit is contained in:
31
src/api/BI/productionBoard.js
Normal file
31
src/api/BI/productionBoard.js
Normal file
@@ -0,0 +1,31 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
/**
|
||||
* 查询今日未开始的生产工单
|
||||
*/
|
||||
export function todayNoStartProWorkorder() {
|
||||
return request({
|
||||
url: 'BI/productionDashboard/todayNoStartProWorkorder',
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询今日正在生产的工单
|
||||
*/
|
||||
export function todayProductiongProWorkorder() {
|
||||
return request({
|
||||
url: 'BI/productionDashboard/todayProductiongProWorkorder',
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询今日已完成的生产工单
|
||||
*/
|
||||
export function todayFinishProductionProWorkorder() {
|
||||
return request({
|
||||
url: 'BI/productionDashboard/todayFinishProductionProWorkorder',
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
@@ -130,6 +130,11 @@ export const constantRoutes = [
|
||||
component: (resolve) => require(['@/views/kanbanManagement/FqcQualityDataBoard/index.vue'], resolve),
|
||||
hidden: true,
|
||||
},
|
||||
{
|
||||
path: '/kanbanManagement/productionBoard',
|
||||
component: (resolve) => require(['@/views/kanbanManagement/productionBoard/index.vue'], resolve),
|
||||
hidden: true,
|
||||
},
|
||||
{
|
||||
path: '/gp12Management/touchScreen',
|
||||
component: (resolve) => require(['@/views/qualityManagement/gp12/touchScreen/main/index.vue'], resolve),
|
||||
|
||||
359
src/views/kanbanManagement/productionBoard/index.vue
Normal file
359
src/views/kanbanManagement/productionBoard/index.vue
Normal file
@@ -0,0 +1,359 @@
|
||||
<template>
|
||||
<div class="dark-screen">
|
||||
<!-- 看板标题 -->
|
||||
<div class="board-header fixed-top">
|
||||
<div class="left-section">
|
||||
<el-button class="back-button" icon="el-icon-back" @click="goBack" circle></el-button>
|
||||
<div class="company-name">上海干巷车镜实业有限公司</div>
|
||||
</div>
|
||||
<h1 class="center-title">生产工单看板</h1>
|
||||
<div class="current-time">{{ currentTime }}</div>
|
||||
</div>
|
||||
|
||||
<!-- 工单模块 -->
|
||||
<div class="order-modules">
|
||||
<div class="order-module" v-for="(module, index) in orderModules" :key="index">
|
||||
<h2>{{ module.title }}</h2>
|
||||
<div class="scroll-list">
|
||||
<ul>
|
||||
<li v-for="order in module.orders" :key="order.id">
|
||||
<el-card :class="getOrderClass(module.title)" class="order-card">
|
||||
<div class="order-info">
|
||||
<!-- 显示客户工单号,适配后端首字母小写 -->
|
||||
<p class="order-id">工单号: {{ order.clientWorkorder }}</p>
|
||||
<p>成品零件号: {{ order.finishedPartNumber }}</p>
|
||||
<p>产品描述: {{ order.productDescription }}</p>
|
||||
</div>
|
||||
</el-card>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import dayjs from 'dayjs'
|
||||
import { todayNoStartProWorkorder, todayProductiongProWorkorder, todayFinishProductionProWorkorder } from '@/api/BI/productionBoard'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
currentTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
||||
orderModules: [
|
||||
{
|
||||
title: '未完成工单',
|
||||
orders: [],
|
||||
},
|
||||
{
|
||||
title: '进行中工单',
|
||||
orders: [],
|
||||
},
|
||||
{
|
||||
title: '已完成工单',
|
||||
orders: [],
|
||||
},
|
||||
],
|
||||
refreshInterval: null,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.updateTime()
|
||||
this.fetchOrders()
|
||||
this.refreshInterval = setInterval(() => {
|
||||
this.fetchOrders()
|
||||
}, 5 * 60 * 1000)
|
||||
},
|
||||
beforeUnmount() {
|
||||
// 使用更现代的生命周期钩子
|
||||
clearInterval(this.refreshInterval)
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 更新当前时间
|
||||
*/
|
||||
updateTime() {
|
||||
setInterval(() => {
|
||||
this.currentTime = dayjs().format('YYYY-MM-DD HH:mm:ss')
|
||||
}, 1000)
|
||||
},
|
||||
/**
|
||||
* 异步获取工单数据
|
||||
*/
|
||||
async fetchOrders() {
|
||||
try {
|
||||
const [noStartOrders, inProgressOrders, finishedOrders] = await Promise.all([
|
||||
todayNoStartProWorkorder(),
|
||||
todayProductiongProWorkorder(),
|
||||
todayFinishProductionProWorkorder(),
|
||||
])
|
||||
|
||||
this.orderModules[0].orders = noStartOrders.data
|
||||
this.orderModules[1].orders = inProgressOrders.data
|
||||
this.orderModules[2].orders = finishedOrders.data
|
||||
} catch (error) {
|
||||
console.error('获取工单数据失败:', error)
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 返回主路由
|
||||
*/
|
||||
goBack() {
|
||||
this.$router.push('/')
|
||||
},
|
||||
/**
|
||||
* 生成模拟工单数据
|
||||
* @param {number} count - 模拟工单数量
|
||||
* @param {number} status - 工单状态
|
||||
* @returns {Array} 模拟工单数据数组
|
||||
*/
|
||||
generateMockOrders(count, status) {
|
||||
const mockOrders = []
|
||||
for (let i = 0; i < count; i++) {
|
||||
mockOrders.push({
|
||||
id: `WO2024030100${i + 1}`,
|
||||
blankNumber: `BN00${i + 1}`,
|
||||
finishedPartNumber: `FPN00${i + 1}`,
|
||||
productDescription: `产品描述 ${i + 1}`,
|
||||
colour: '红色',
|
||||
specifications: '标准规格',
|
||||
codeNumber: `CN00${i + 1}`,
|
||||
vehicleNumber: i + 1,
|
||||
hangNumber: i + 1,
|
||||
previousNumber: i + 1,
|
||||
cylinderNumber: `CYL00${i + 1}`,
|
||||
remark1: '备注1',
|
||||
remark2: '备注2',
|
||||
status,
|
||||
clientWorkorder: `ClientWO2024030100${i + 1}`,
|
||||
})
|
||||
}
|
||||
return mockOrders
|
||||
},
|
||||
/**
|
||||
* 根据工单类别返回对应的类名
|
||||
* @param {string} title - 工单类别标题
|
||||
* @returns {string} 对应的类名
|
||||
*/
|
||||
getOrderClass(title) {
|
||||
if (title === '未完成工单') {
|
||||
return 'unfinished-order'
|
||||
}
|
||||
if (title === '进行中工单') {
|
||||
return 'in-progress-order'
|
||||
}
|
||||
if (title === '已完成工单') {
|
||||
return 'completed-order'
|
||||
}
|
||||
return ''
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.dark-screen {
|
||||
background-color: #1a1a1a;
|
||||
color: #ffffff;
|
||||
min-height: 100vh;
|
||||
padding-top: 80px;
|
||||
}
|
||||
|
||||
.fixed-top {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: #2d2d2d;
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.left-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.back-button {
|
||||
background-color: #444;
|
||||
border-color: #666;
|
||||
color: #fff;
|
||||
margin-right: 10px;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.back-button:hover {
|
||||
background-color: #666;
|
||||
border-color: #888;
|
||||
}
|
||||
|
||||
.company-name {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.center-title {
|
||||
margin: 0;
|
||||
font-size: 24px;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
.current-time {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.order-modules {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
padding: 20px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.order-module {
|
||||
background-color: #2d2d2d;
|
||||
border-radius: 16px; /* 增大圆角 */
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3); /* 增强阴影 */
|
||||
padding: 24px;
|
||||
margin: 16px;
|
||||
flex: 1 1 calc(33.333% - 32px);
|
||||
min-width: 320px;
|
||||
transition: transform 0.3s ease; /* 添加过渡效果 */
|
||||
}
|
||||
|
||||
.order-module:hover {
|
||||
transform: translateY(-8px); /* 悬停时上移 */
|
||||
}
|
||||
|
||||
.order-module h2 {
|
||||
text-align: center;
|
||||
margin-bottom: 24px;
|
||||
color: #409eff; /* 标题添加主题色 */
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.scroll-list {
|
||||
height: 420px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.scroll-list ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 100%; /* 让 ul 宽度撑满容器 */
|
||||
animation: scroll 30s linear infinite;
|
||||
}
|
||||
|
||||
.scroll-list li {
|
||||
text-align: center;
|
||||
padding: 16px 0;
|
||||
border-bottom: 1px solid #3d3d3d; /* 添加分隔线 */
|
||||
width: 100%; /* 让 li 宽度撑满容器 */
|
||||
}
|
||||
|
||||
.scroll-list li:last-child {
|
||||
border-bottom: none; /* 最后一项去掉分隔线 */
|
||||
}
|
||||
|
||||
.order-info p {
|
||||
margin: 8px 0;
|
||||
font-size: 16px;
|
||||
color: #e0e0e0; /* 调整文字颜色 */
|
||||
}
|
||||
|
||||
.order-info p:first-child {
|
||||
font-size: 18px;
|
||||
font-weight: 500;
|
||||
color: #ffffff; /* 工单号加粗加亮 */
|
||||
}
|
||||
|
||||
.order-card {
|
||||
width: 100%; /* 宽度撑满容器 */
|
||||
margin-bottom: 10px; /* 每个工单卡片之间的间距 */
|
||||
background-color: rgba(255, 255, 255, 0.1); /* 半透明背景 */
|
||||
border: 1px solid rgba(255, 255, 255, 0.2); /* 半透明边框 */
|
||||
border-radius: 8px; /* 圆角 */
|
||||
transition: all 0.3s ease; /* 过渡效果 */
|
||||
}
|
||||
|
||||
.order-card:hover {
|
||||
background-color: rgba(255, 255, 255, 0.15); /* 悬停时加深背景 */
|
||||
transform: translateY(-2px); /* 悬停时上移 */
|
||||
}
|
||||
|
||||
.unfinished-order {
|
||||
border-left: 4px solid #ff4d4f; /* 未完成工单左侧边框 */
|
||||
}
|
||||
|
||||
.in-progress-order {
|
||||
border-left: 4px solid #faad14; /* 进行中工单左侧边框 */
|
||||
}
|
||||
|
||||
.completed-order {
|
||||
border-left: 4px solid #52c41a; /* 已完成工单左侧边框 */
|
||||
}
|
||||
|
||||
.order-info {
|
||||
display: flex; /* 使用 Flexbox 布局 */
|
||||
flex-wrap: wrap; /* 允许内容换行 */
|
||||
align-items: center; /* 垂直居中对齐 */
|
||||
padding: 8px 12px; /* 调整内边距 */
|
||||
gap: 8px; /* 设置子元素之间的间距 */
|
||||
}
|
||||
|
||||
.order-info p {
|
||||
margin: 0; /* 移除段落的上下外边距 */
|
||||
font-size: 14px; /* 调整字体大小 */
|
||||
min-width: 120px; /* 设置最小宽度,保证信息有足够空间显示 */
|
||||
flex: 1 1 auto; /* 允许子元素根据内容自动伸缩 */
|
||||
}
|
||||
|
||||
.order-info p.order-id {
|
||||
font-size: 16px; /* 工单号字体稍大 */
|
||||
flex-basis: 100%; /* 工单号独占一行 */
|
||||
margin-bottom: 8px; /* 与下方信息保持间距 */
|
||||
}
|
||||
|
||||
.order-id {
|
||||
font-weight: bold; /* 工单号加粗 */
|
||||
color: #1890ff; /* 工单号颜色 */
|
||||
}
|
||||
|
||||
@keyframes scroll {
|
||||
0% {
|
||||
top: 0;
|
||||
}
|
||||
100% {
|
||||
top: -100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
.order-module {
|
||||
flex: 1 1 calc(50% - 32px);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.order-module {
|
||||
flex: 1 1 100%;
|
||||
}
|
||||
.center-title {
|
||||
font-size: 20px;
|
||||
}
|
||||
.company-name,
|
||||
.current-time {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user