|
|
|
@ -12,19 +12,23 @@ |
|
|
|
|
|
|
|
<div class="kpi-grid"> |
|
|
|
<div class="kpi-card"> |
|
|
|
<div class="kpi-label">本月整梯排产</div> |
|
|
|
<div class="kpi-label">近一月整梯排产</div> |
|
|
|
<div class="kpi-value">{{ kpi.monthWhole }}</div> |
|
|
|
</div> |
|
|
|
<div class="kpi-card"> |
|
|
|
<div class="kpi-label">本月VL2.5升级排产</div> |
|
|
|
<div class="kpi-label">近一月VL2.5升级排产</div> |
|
|
|
<div class="kpi-value">{{ kpi.monthRenovation }}</div> |
|
|
|
</div> |
|
|
|
<div class="kpi-card"> |
|
|
|
<div class="kpi-label">本月线缆/COP任务</div> |
|
|
|
<div class="kpi-label">近一月线缆/COP任务</div> |
|
|
|
<div class="kpi-value">{{ kpi.monthTask }}</div> |
|
|
|
</div> |
|
|
|
<div class="kpi-card"> |
|
|
|
<div class="kpi-label">本月完工达成率</div> |
|
|
|
<div class="kpi-label">近一月机加工任务</div> |
|
|
|
<div class="kpi-value">{{ kpi.monthMachining }}</div> |
|
|
|
</div> |
|
|
|
<div class="kpi-card"> |
|
|
|
<div class="kpi-label">近一月完工达成率</div> |
|
|
|
<div class="kpi-value highlight">{{ kpi.finishRate }}%</div> |
|
|
|
</div> |
|
|
|
<div class="kpi-card"> |
|
|
|
@ -39,7 +43,7 @@ |
|
|
|
|
|
|
|
<div class="chart-grid"> |
|
|
|
<div class="panel"> |
|
|
|
<div class="panel-title">本月排产/完工对比</div> |
|
|
|
<div class="panel-title">近一月排产/完工对比</div> |
|
|
|
<div id="overviewBarChart" class="chart-box"></div> |
|
|
|
</div> |
|
|
|
<div class="panel"> |
|
|
|
@ -68,6 +72,9 @@ |
|
|
|
|
|
|
|
<script> |
|
|
|
import echarts from 'echarts' |
|
|
|
import { getFactoryOverviewBoardData } from '@/api/longchuang/productionPlan' |
|
|
|
|
|
|
|
const STATUS_ALLOW_LIST = ['已排产', '进行中', '已完成'] |
|
|
|
|
|
|
|
export default { |
|
|
|
name: 'ScreenFactoryOverview', |
|
|
|
@ -75,16 +82,20 @@ export default { |
|
|
|
return { |
|
|
|
currentTime: '', |
|
|
|
timerId: null, |
|
|
|
boardTimerId: null, |
|
|
|
loading: false, |
|
|
|
chartBar: null, |
|
|
|
chartPie: null, |
|
|
|
chartLine: null, |
|
|
|
wholeList: [], |
|
|
|
taskList: [], |
|
|
|
renovationList: [], |
|
|
|
machiningList: [], |
|
|
|
kpi: { |
|
|
|
monthWhole: 0, |
|
|
|
monthRenovation: 0, |
|
|
|
monthTask: 0, |
|
|
|
monthMachining: 0, |
|
|
|
finishRate: 0, |
|
|
|
wipTotal: 0, |
|
|
|
onTimeRate: 0 |
|
|
|
@ -96,56 +107,69 @@ export default { |
|
|
|
this.loadBoardData() |
|
|
|
this.updateTime() |
|
|
|
this.timerId = setInterval(this.updateTime, 1000) |
|
|
|
this.boardTimerId = setInterval(() => { |
|
|
|
this.loadBoardData() |
|
|
|
}, 60000) |
|
|
|
window.addEventListener('resize', this.resizeCharts) |
|
|
|
}, |
|
|
|
beforeDestroy() { |
|
|
|
if (this.timerId) clearInterval(this.timerId) |
|
|
|
if (this.boardTimerId) clearInterval(this.boardTimerId) |
|
|
|
window.removeEventListener('resize', this.resizeCharts) |
|
|
|
this.disposeCharts() |
|
|
|
}, |
|
|
|
methods: { |
|
|
|
loadBoardData() { |
|
|
|
// 综合大屏当前采用固定演示数据,确保页面始终可视化展示 |
|
|
|
this.wholeList = this.getWholeMock() |
|
|
|
this.taskList = this.getTaskMock() |
|
|
|
this.renovationList = this.getRenovationMock() |
|
|
|
this.buildDashboard() |
|
|
|
this.$nextTick(() => { |
|
|
|
setTimeout(() => { |
|
|
|
this.resizeCharts() |
|
|
|
}, 120) |
|
|
|
if (this.loading) return |
|
|
|
this.loading = true |
|
|
|
getFactoryOverviewBoardData({ page: 1, limit: 500, statusList: STATUS_ALLOW_LIST }).then(({ data }) => { |
|
|
|
this.loading = false |
|
|
|
const boardData = data && data.code === 0 && data.boardData ? data.boardData : {} |
|
|
|
this.wholeList = this.normalizeBoardList(boardData.homeLiftList) |
|
|
|
this.taskList = this.normalizeBoardList(boardData.cableCopTaskList) |
|
|
|
this.renovationList = this.normalizeBoardList(boardData.renovationOrderList) |
|
|
|
this.machiningList = this.normalizeBoardList(boardData.machiningTaskList) |
|
|
|
this.buildDashboard() |
|
|
|
this.$nextTick(() => { |
|
|
|
setTimeout(() => { |
|
|
|
this.resizeCharts() |
|
|
|
}, 120) |
|
|
|
}) |
|
|
|
}).catch(() => { |
|
|
|
this.loading = false |
|
|
|
this.wholeList = [] |
|
|
|
this.taskList = [] |
|
|
|
this.renovationList = [] |
|
|
|
this.machiningList = [] |
|
|
|
this.buildDashboard() |
|
|
|
}) |
|
|
|
}, |
|
|
|
extractList(res, fallback) { |
|
|
|
const data = res && res.data |
|
|
|
if (data && data.code === 0 && data.page && data.page.list) { |
|
|
|
if (data.page.list.length > 0) return data.page.list |
|
|
|
} |
|
|
|
return fallback |
|
|
|
}, |
|
|
|
ensureValidBoardData() { |
|
|
|
const validStatus = ['已排产', '进行中', '已完成'] |
|
|
|
const all = this.wholeList.concat(this.taskList).concat(this.renovationList) |
|
|
|
const validCount = all.filter(item => validStatus.includes(item.status)).length |
|
|
|
// 后端返回空结构或状态值不匹配时,强制回退到本地演示数据 |
|
|
|
if (validCount === 0) { |
|
|
|
this.wholeList = this.getWholeMock() |
|
|
|
this.taskList = this.getTaskMock() |
|
|
|
this.renovationList = this.getRenovationMock() |
|
|
|
} |
|
|
|
normalizeBoardList(sourceList) { |
|
|
|
return (sourceList || []) |
|
|
|
.filter(item => STATUS_ALLOW_LIST.includes(item.status)) |
|
|
|
.map(item => ({ |
|
|
|
...item, |
|
|
|
nodeList: item.nodeList || [] |
|
|
|
})) |
|
|
|
}, |
|
|
|
buildDashboard() { |
|
|
|
const monthStart = this.dayjs().startOf('month') |
|
|
|
const allOrderList = this.wholeList.concat(this.renovationList) |
|
|
|
const finishedAll = allOrderList.filter(item => item.status === '已完成').length |
|
|
|
const inScheduleAll = allOrderList.filter(item => ['已排产', '进行中', '已完成'].includes(item.status)).length |
|
|
|
const periodStart = this.dayjs().subtract(1, 'month').startOf('day') |
|
|
|
const allOrderList = this.wholeList |
|
|
|
.concat(this.renovationList) |
|
|
|
.concat(this.taskList) |
|
|
|
.concat(this.machiningList) |
|
|
|
const recentOrderList = this.filterByDateRange(allOrderList, periodStart) |
|
|
|
const finishedAll = recentOrderList.filter(item => item.status === '已完成').length |
|
|
|
const inScheduleAll = recentOrderList.filter(item => STATUS_ALLOW_LIST.includes(item.status)).length |
|
|
|
const wipTotal = this.wholeList.filter(item => item.status === '进行中').length + |
|
|
|
this.taskList.filter(item => item.status === '进行中').length + |
|
|
|
this.renovationList.filter(item => item.status === '进行中').length |
|
|
|
this.renovationList.filter(item => item.status === '进行中').length + |
|
|
|
this.machiningList.filter(item => item.status === '进行中').length |
|
|
|
|
|
|
|
const monthWhole = this.countByMonth(this.wholeList, monthStart) |
|
|
|
const monthRenovation = this.countByMonth(this.renovationList, monthStart) |
|
|
|
const monthTask = this.countByMonth(this.taskList, monthStart) |
|
|
|
const monthWhole = this.countByMonth(this.wholeList, periodStart) |
|
|
|
const monthRenovation = this.countByMonth(this.renovationList, periodStart) |
|
|
|
const monthTask = this.countByMonth(this.taskList, periodStart) |
|
|
|
const monthMachining = this.countByMonth(this.machiningList, periodStart) |
|
|
|
|
|
|
|
const onTimeTotal = allOrderList.filter(item => item.status === '已完成').length |
|
|
|
const onTimeCount = allOrderList.filter(item => item.status === '已完成' && this.isOnTime(item)).length |
|
|
|
@ -153,6 +177,7 @@ export default { |
|
|
|
this.kpi.monthWhole = monthWhole |
|
|
|
this.kpi.monthRenovation = monthRenovation |
|
|
|
this.kpi.monthTask = monthTask |
|
|
|
this.kpi.monthMachining = monthMachining |
|
|
|
this.kpi.finishRate = inScheduleAll ? Math.round((finishedAll / inScheduleAll) * 100) : 0 |
|
|
|
this.kpi.wipTotal = wipTotal |
|
|
|
this.kpi.onTimeRate = onTimeTotal ? Math.round((onTimeCount / onTimeTotal) * 100) : 0 |
|
|
|
@ -165,11 +190,26 @@ export default { |
|
|
|
}) |
|
|
|
}, |
|
|
|
countByMonth(list, monthStart) { |
|
|
|
const startValue = monthStart.subtract(1, 'day').valueOf() |
|
|
|
const startValue = monthStart.valueOf() |
|
|
|
return list.filter(item => { |
|
|
|
const dateVal = item.planDeliveryDate || item.planFinishDate || item.createTime |
|
|
|
const dateObj = this.toDayjs(dateVal) |
|
|
|
return dateObj && dateObj.valueOf() > startValue |
|
|
|
return dateObj && dateObj.valueOf() >= startValue |
|
|
|
}).length |
|
|
|
}, |
|
|
|
filterByDateRange(list, startDate) { |
|
|
|
return (list || []).filter(item => { |
|
|
|
const dateVal = item.planDeliveryDate || item.planFinishDate || item.createTime |
|
|
|
const dateObj = this.toDayjs(dateVal) |
|
|
|
return dateObj && dateObj.valueOf() >= startDate.valueOf() |
|
|
|
}) |
|
|
|
}, |
|
|
|
countFinishedInRange(list, startDate) { |
|
|
|
return (list || []).filter(item => { |
|
|
|
if (item.status !== '已完成') return false |
|
|
|
const dateVal = item.finishDate || item.planDeliveryDate || item.planFinishDate || item.createTime |
|
|
|
const dateObj = this.toDayjs(dateVal) |
|
|
|
return dateObj && dateObj.valueOf() >= startDate.valueOf() |
|
|
|
}).length |
|
|
|
}, |
|
|
|
isOnTime(item) { |
|
|
|
@ -185,7 +225,7 @@ export default { |
|
|
|
}, |
|
|
|
buildNodeRates() { |
|
|
|
const nodeMap = {} |
|
|
|
const all = this.wholeList.concat(this.taskList).concat(this.renovationList) |
|
|
|
const all = this.wholeList.concat(this.taskList).concat(this.renovationList).concat(this.machiningList) |
|
|
|
all.forEach(item => { |
|
|
|
const list = item.nodeList || [] |
|
|
|
list.forEach(node => { |
|
|
|
@ -214,22 +254,55 @@ export default { |
|
|
|
const el = document.getElementById('overviewBarChart') |
|
|
|
if (!el) return |
|
|
|
if (!this.chartBar) this.chartBar = echarts.init(el) |
|
|
|
const scheduledWhole = this.wholeList.filter(item => ['已排产', '进行中', '已完成'].includes(item.status)).length |
|
|
|
const scheduledRenovation = this.renovationList.filter(item => ['已排产', '进行中', '已完成'].includes(item.status)).length |
|
|
|
const scheduledTask = this.taskList.filter(item => ['已排产', '进行中', '已完成'].includes(item.status)).length |
|
|
|
const finishedWhole = this.wholeList.filter(item => item.status === '已完成').length |
|
|
|
const finishedRenovation = this.renovationList.filter(item => item.status === '已完成').length |
|
|
|
const finishedTask = this.taskList.filter(item => item.status === '已完成').length |
|
|
|
const periodStart = this.dayjs().subtract(1, 'month').startOf('day') |
|
|
|
const scheduledWhole = this.countByMonth(this.wholeList.filter(item => STATUS_ALLOW_LIST.includes(item.status)), periodStart) |
|
|
|
const scheduledRenovation = this.countByMonth(this.renovationList.filter(item => STATUS_ALLOW_LIST.includes(item.status)), periodStart) |
|
|
|
const scheduledTask = this.countByMonth(this.taskList.filter(item => STATUS_ALLOW_LIST.includes(item.status)), periodStart) |
|
|
|
const scheduledMachining = this.countByMonth(this.machiningList.filter(item => STATUS_ALLOW_LIST.includes(item.status)), periodStart) |
|
|
|
const finishedWhole = this.countFinishedInRange(this.wholeList, periodStart) |
|
|
|
const finishedRenovation = this.countFinishedInRange(this.renovationList, periodStart) |
|
|
|
const finishedTask = this.countFinishedInRange(this.taskList, periodStart) |
|
|
|
const finishedMachining = this.countFinishedInRange(this.machiningList, periodStart) |
|
|
|
this.chartBar.setOption({ |
|
|
|
color: ['#4fa8ff', '#6ed3a6'], |
|
|
|
grid: { left: 30, right: 20, top: 40, bottom: 20, containLabel: true }, |
|
|
|
tooltip: { trigger: 'axis' }, |
|
|
|
legend: { textStyle: { color: '#cbe7ff' }, data: ['排产量', '完工量'] }, |
|
|
|
xAxis: { type: 'category', axisLabel: { color: '#cbe7ff' }, data: ['整梯', 'VL2.5升级', '线缆/COP'] }, |
|
|
|
xAxis: { type: 'category', axisLabel: { color: '#cbe7ff' }, data: ['整梯', 'VL2.5升级', '线缆/COP', '机加工'] }, |
|
|
|
yAxis: { type: 'value', axisLabel: { color: '#cbe7ff' }, splitLine: { lineStyle: { color: 'rgba(160,200,240,0.15)' } } }, |
|
|
|
series: [ |
|
|
|
{ name: '排产量', type: 'bar', barWidth: 24, data: [scheduledWhole, scheduledRenovation, scheduledTask], itemStyle: { color: '#4fa8ff' } }, |
|
|
|
{ name: '完工量', type: 'bar', barWidth: 24, data: [finishedWhole, finishedRenovation, finishedTask], itemStyle: { color: '#6ed3a6' } } |
|
|
|
{ |
|
|
|
name: '排产量', |
|
|
|
type: 'bar', |
|
|
|
barWidth: 24, |
|
|
|
data: [scheduledWhole, scheduledRenovation, scheduledTask, scheduledMachining], |
|
|
|
itemStyle: { color: '#4fa8ff' }, |
|
|
|
label: { |
|
|
|
normal: { |
|
|
|
show: true, |
|
|
|
position: 'top', |
|
|
|
color: '#d4ebff', |
|
|
|
fontSize: 12, |
|
|
|
formatter: '{c}' |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
{ |
|
|
|
name: '完工量', |
|
|
|
type: 'bar', |
|
|
|
barWidth: 24, |
|
|
|
data: [finishedWhole, finishedRenovation, finishedTask, finishedMachining], |
|
|
|
itemStyle: { color: '#6ed3a6' }, |
|
|
|
label: { |
|
|
|
normal: { |
|
|
|
show: true, |
|
|
|
position: 'top', |
|
|
|
color: '#d4ebff', |
|
|
|
fontSize: 12, |
|
|
|
formatter: '{c}' |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
] |
|
|
|
}, true) |
|
|
|
}, |
|
|
|
@ -240,20 +313,50 @@ export default { |
|
|
|
const wholeCount = this.wholeList.length |
|
|
|
const renovationCount = this.renovationList.length |
|
|
|
const taskCount = this.taskList.length |
|
|
|
const machiningCount = this.machiningList.length |
|
|
|
const pieData = [ |
|
|
|
{ value: wholeCount, name: '整梯订单' }, |
|
|
|
{ value: renovationCount, name: 'VL2.5升级订单' }, |
|
|
|
{ value: taskCount, name: '线缆/COP任务' }, |
|
|
|
{ value: machiningCount, name: '机加工任务' } |
|
|
|
] |
|
|
|
this.chartPie.setOption({ |
|
|
|
color: ['#57b8ff', '#5dd4b0', '#7fa6d9'], |
|
|
|
tooltip: { trigger: 'item' }, |
|
|
|
color: ['#57b8ff', '#5dd4b0', '#7fa6d9', '#f5c15e'], |
|
|
|
tooltip: { |
|
|
|
trigger: 'item', |
|
|
|
formatter: (params) => `${params.name}<br/>数量:${params.value}<br/>占比:${params.percent || 0}%` |
|
|
|
}, |
|
|
|
legend: { bottom: 2, textStyle: { color: '#cbe7ff' } }, |
|
|
|
series: [{ |
|
|
|
type: 'pie', |
|
|
|
radius: ['42%', '72%'], |
|
|
|
center: ['50%', '45%'], |
|
|
|
label: { color: '#d4ebff' }, |
|
|
|
data: [ |
|
|
|
{ value: wholeCount, name: '整梯订单' }, |
|
|
|
{ value: renovationCount, name: 'VL2.5升级订单' }, |
|
|
|
{ value: taskCount, name: '线缆/COP任务' } |
|
|
|
] |
|
|
|
avoidLabelOverlap: false, |
|
|
|
minShowLabelAngle: 0, |
|
|
|
label: { |
|
|
|
normal: { |
|
|
|
show: true, |
|
|
|
position: 'outside', |
|
|
|
color: '#d4ebff', |
|
|
|
fontSize: 14, |
|
|
|
formatter: '{b} {d}%' |
|
|
|
}, |
|
|
|
emphasis: { |
|
|
|
show: true, |
|
|
|
formatter: '{b} {d}%' |
|
|
|
} |
|
|
|
}, |
|
|
|
labelLine: { |
|
|
|
normal: { |
|
|
|
show: true, |
|
|
|
length: 14, |
|
|
|
length2: 10, |
|
|
|
lineStyle: { |
|
|
|
color: '#7fb4de' |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
data: pieData |
|
|
|
}] |
|
|
|
}, true) |
|
|
|
}, |
|
|
|
@ -264,22 +367,28 @@ export default { |
|
|
|
const xAxis = [] |
|
|
|
const wholeSeries = [] |
|
|
|
const renovationSeries = [] |
|
|
|
const taskSeries = [] |
|
|
|
const machiningSeries = [] |
|
|
|
for (let i = 6; i >= 0; i--) { |
|
|
|
const day = this.dayjs().subtract(i, 'day') |
|
|
|
xAxis.push(day.format('MM-DD')) |
|
|
|
wholeSeries.push(this.countFinishByDay(this.wholeList, day)) |
|
|
|
renovationSeries.push(this.countFinishByDay(this.renovationList, day)) |
|
|
|
taskSeries.push(this.countFinishByDay(this.taskList, day)) |
|
|
|
machiningSeries.push(this.countFinishByDay(this.machiningList, day)) |
|
|
|
} |
|
|
|
this.chartLine.setOption({ |
|
|
|
color: ['#6cc7ff', '#74e0b3'], |
|
|
|
color: ['#6cc7ff', '#74e0b3', '#7fa6d9', '#f5c15e'], |
|
|
|
grid: { left: 35, right: 20, top: 34, bottom: 20, containLabel: true }, |
|
|
|
tooltip: { trigger: 'axis' }, |
|
|
|
legend: { textStyle: { color: '#cbe7ff' }, data: ['整梯完工', 'VL2.5升级完工'] }, |
|
|
|
legend: { textStyle: { color: '#cbe7ff' }, data: ['整梯完工', 'VL2.5升级完工', '线缆/COP完工', '机加工完工'] }, |
|
|
|
xAxis: { type: 'category', axisLabel: { color: '#cbe7ff' }, data: xAxis }, |
|
|
|
yAxis: { type: 'value', axisLabel: { color: '#cbe7ff' }, splitLine: { lineStyle: { color: 'rgba(160,200,240,0.15)' } } }, |
|
|
|
series: [ |
|
|
|
{ name: '整梯完工', type: 'line', smooth: true, symbol: 'circle', symbolSize: 7, data: wholeSeries, itemStyle: { color: '#6cc7ff' }, lineStyle: { color: '#6cc7ff' }, areaStyle: { color: 'rgba(108,199,255,0.18)' } }, |
|
|
|
{ name: 'VL2.5升级完工', type: 'line', smooth: true, symbol: 'circle', symbolSize: 7, data: renovationSeries, itemStyle: { color: '#74e0b3' }, lineStyle: { color: '#74e0b3' }, areaStyle: { color: 'rgba(116,224,179,0.18)' } } |
|
|
|
{ name: 'VL2.5升级完工', type: 'line', smooth: true, symbol: 'circle', symbolSize: 7, data: renovationSeries, itemStyle: { color: '#74e0b3' }, lineStyle: { color: '#74e0b3' }, areaStyle: { color: 'rgba(116,224,179,0.18)' } }, |
|
|
|
{ name: '线缆/COP完工', type: 'line', smooth: true, symbol: 'circle', symbolSize: 7, data: taskSeries, itemStyle: { color: '#7fa6d9' }, lineStyle: { color: '#7fa6d9' }, areaStyle: { color: 'rgba(127,166,217,0.16)' } }, |
|
|
|
{ name: '机加工完工', type: 'line', smooth: true, symbol: 'circle', symbolSize: 7, data: machiningSeries, itemStyle: { color: '#f5c15e' }, lineStyle: { color: '#f5c15e' }, areaStyle: { color: 'rgba(245,193,94,0.15)' } } |
|
|
|
] |
|
|
|
}, true) |
|
|
|
}, |
|
|
|
@ -304,44 +413,6 @@ export default { |
|
|
|
if (this.chartBar) { this.chartBar.dispose(); this.chartBar = null } |
|
|
|
if (this.chartPie) { this.chartPie.dispose(); this.chartPie = null } |
|
|
|
if (this.chartLine) { this.chartLine.dispose(); this.chartLine = null } |
|
|
|
}, |
|
|
|
getWholeMock() { |
|
|
|
return [ |
|
|
|
{ status: '进行中', planDeliveryDate: '2026-04-25', finishDate: '', nodeList: [{ nodeName: '仓库配料', status: '已完成' }, { nodeName: '平台组装/调试', status: '进行中' }, { nodeName: '背景墙/吊顶组装', status: '未开始' }] }, |
|
|
|
{ status: '已完成', planDeliveryDate: '2026-04-12', finishDate: '2026-04-11', nodeList: [{ nodeName: '仓库配料', status: '已完成' }, { nodeName: '平台组装/调试', status: '已完成' }, { nodeName: '背景墙/吊顶组装', status: '已完成' }, { nodeName: '门组装', status: '已完成' }, { nodeName: '打包', status: '已完成' }] }, |
|
|
|
{ status: '已排产', planDeliveryDate: '2026-04-30', finishDate: '', nodeList: [{ nodeName: '仓库配料', status: '未开始' }] }, |
|
|
|
{ status: '进行中', planDeliveryDate: '2026-04-22', finishDate: '', nodeList: [{ nodeName: '仓库配料', status: '已完成' }, { nodeName: '平台组装/调试', status: '已完成' }, { nodeName: '背景墙/吊顶组装', status: '进行中' }] }, |
|
|
|
{ status: '已完成', planDeliveryDate: '2026-04-14', finishDate: '2026-04-14', nodeList: [{ nodeName: '仓库配料', status: '已完成' }, { nodeName: '平台组装/调试', status: '已完成' }, { nodeName: '门组装', status: '已完成' }, { nodeName: '打包', status: '已完成' }] }, |
|
|
|
{ status: '进行中', planDeliveryDate: '2026-04-27', finishDate: '', nodeList: [{ nodeName: '仓库配料', status: '进行中' }, { nodeName: '平台组装/调试', status: '未开始' }] }, |
|
|
|
{ status: '已完成', planDeliveryDate: '2026-04-16', finishDate: '2026-04-15', nodeList: [{ nodeName: '仓库配料', status: '已完成' }, { nodeName: '平台组装/调试', status: '已完成' }, { nodeName: '背景墙/吊顶组装', status: '已完成' }, { nodeName: '打包', status: '已完成' }] }, |
|
|
|
{ status: '已排产', planDeliveryDate: '2026-04-29', finishDate: '', nodeList: [{ nodeName: '仓库配料', status: '未开始' }, { nodeName: '平台组装/调试', status: '未开始' }] }, |
|
|
|
{ status: '已完成', planDeliveryDate: '2026-04-13', finishDate: '2026-04-12', nodeList: [{ nodeName: '仓库配料', status: '已完成' }, { nodeName: '平台组装/调试', status: '已完成' }, { nodeName: '门组装', status: '已完成' }, { nodeName: '打包', status: '已完成' }] } |
|
|
|
] |
|
|
|
}, |
|
|
|
getTaskMock() { |
|
|
|
return [ |
|
|
|
{ status: '进行中', planFinishDate: '2026-04-20', nodeList: [{ nodeName: '线缆生产', status: '已完成' }, { nodeName: 'COP生产', status: '进行中' }] }, |
|
|
|
{ status: '已排产', planFinishDate: '2026-04-21', nodeList: [{ nodeName: '线缆生产', status: '未开始' }, { nodeName: 'COP生产', status: '未开始' }] }, |
|
|
|
{ status: '已完成', planFinishDate: '2026-04-19', nodeList: [{ nodeName: '线缆生产', status: '已完成' }, { nodeName: 'COP生产', status: '已完成' }] }, |
|
|
|
{ status: '进行中', planFinishDate: '2026-04-22', nodeList: [{ nodeName: '线缆生产', status: '进行中' }, { nodeName: 'COP生产', status: '未开始' }] }, |
|
|
|
{ status: '已完成', planFinishDate: '2026-04-15', nodeList: [{ nodeName: '线缆生产', status: '已完成' }, { nodeName: 'COP生产', status: '已完成' }] }, |
|
|
|
{ status: '已排产', planFinishDate: '2026-04-25', nodeList: [{ nodeName: '线缆生产', status: '未开始' }, { nodeName: 'COP生产', status: '未开始' }] }, |
|
|
|
{ status: '进行中', planFinishDate: '2026-04-23', nodeList: [{ nodeName: '线缆生产', status: '已完成' }, { nodeName: 'COP生产', status: '进行中' }] }, |
|
|
|
{ status: '已完成', planFinishDate: '2026-04-18', nodeList: [{ nodeName: '线缆生产', status: '已完成' }, { nodeName: 'COP生产', status: '已完成' }] }, |
|
|
|
{ status: '已排产', planFinishDate: '2026-04-28', nodeList: [{ nodeName: '线缆生产', status: '未开始' }, { nodeName: 'COP生产', status: '未开始' }] } |
|
|
|
] |
|
|
|
}, |
|
|
|
getRenovationMock() { |
|
|
|
return [ |
|
|
|
{ status: '进行中', planDeliveryDate: '2026-04-26', finishDate: '', nodeList: [{ nodeName: '仓库配料', status: '已完成' }, { nodeName: '组装', status: '进行中' }, { nodeName: '检验', status: '未开始' }] }, |
|
|
|
{ status: '已完成', planDeliveryDate: '2026-04-15', finishDate: '2026-04-15', nodeList: [{ nodeName: '仓库配料', status: '已完成' }, { nodeName: '组装', status: '已完成' }, { nodeName: '检验', status: '已完成' }, { nodeName: '打包', status: '已完成' }] }, |
|
|
|
{ status: '已排产', planDeliveryDate: '2026-04-28', finishDate: '', nodeList: [{ nodeName: '仓库配料', status: '未开始' }, { nodeName: '组装', status: '未开始' }] }, |
|
|
|
{ status: '进行中', planDeliveryDate: '2026-04-23', finishDate: '', nodeList: [{ nodeName: '仓库配料', status: '已完成' }, { nodeName: '组装', status: '已完成' }, { nodeName: '检验', status: '进行中' }] }, |
|
|
|
{ status: '已完成', planDeliveryDate: '2026-04-13', finishDate: '2026-04-12', nodeList: [{ nodeName: '仓库配料', status: '已完成' }, { nodeName: '组装', status: '已完成' }, { nodeName: '检验', status: '已完成' }, { nodeName: '打包', status: '已完成' }] }, |
|
|
|
{ status: '进行中', planDeliveryDate: '2026-04-27', finishDate: '', nodeList: [{ nodeName: '仓库配料', status: '进行中' }, { nodeName: '组装', status: '未开始' }] }, |
|
|
|
{ status: '已排产', planDeliveryDate: '2026-04-29', finishDate: '', nodeList: [{ nodeName: '仓库配料', status: '未开始' }] }, |
|
|
|
{ status: '已完成', planDeliveryDate: '2026-04-17', finishDate: '2026-04-16', nodeList: [{ nodeName: '仓库配料', status: '已完成' }, { nodeName: '组装', status: '已完成' }, { nodeName: '检验', status: '已完成' }, { nodeName: '打包', status: '已完成' }] } |
|
|
|
] |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@ -462,7 +533,7 @@ export default { |
|
|
|
|
|
|
|
.kpi-grid { |
|
|
|
display: grid; |
|
|
|
grid-template-columns: repeat(6, minmax(120px, 1fr)); |
|
|
|
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); |
|
|
|
gap: 10px; |
|
|
|
margin-bottom: 14px; |
|
|
|
} |
|
|
|
|