更新精工车间生产计划和车间分配页面
This commit is contained in:
@@ -12,14 +12,18 @@
|
||||
<el-input v-model="orderNumberTypeValue" style="width:200px;margin-left: 10px" placeholder="订单编号" size="small" clearable/>
|
||||
<el-input v-model="partNameValue" style="width:150px;margin-left: 10px" placeholder="零件名称或图号" size="small" clearable/>
|
||||
<el-input v-model="productNameValue" style="width:150px;margin-left: 10px" placeholder="产品名称" size="small" clearable/>
|
||||
<el-select v-model="statusValue" style="width:100px;margin-left: 10px" placeholder="状态" size="small">
|
||||
<el-select v-model="statusValue" style="width:100px;margin-left: 10px" placeholder="状态" size="small" clearable>
|
||||
<el-option label="派工中" value="派工中"/>
|
||||
<el-option label="生产中" value="生产中"/>
|
||||
<el-option label="已完成" value="已完成"/>
|
||||
</el-select>
|
||||
<el-button icon="el-icon-search" type="primary" plain size="small" style="margin-left: 10px" @click="searchTable1()">查询</el-button>
|
||||
<el-button icon="el-icon-data-analysis" type="warning" plain size="small" style="margin-left: 10px" @click="openDashboard()">可视化看板</el-button>
|
||||
<span v-if="monthCompletionRate !== ''" style="margin-left: 20px; font-size: 14px; color: #606266">
|
||||
本月完成率:<el-tag :type="monthCompletionRateTag" size="medium" effect="dark">{{ monthCompletionRate }}</el-tag>
|
||||
</span>
|
||||
</div>
|
||||
<el-table :data="tableData2" height="750px" style="width: 2200px" size="mini" highlight-current-row border>
|
||||
<el-table :data="filteredTableData" height="750px" style="width: 2200px" size="mini" highlight-current-row border>
|
||||
<el-table-column width="50px" align="center" label="序号" show-overflow-tooltip fixed>
|
||||
<template slot-scope="scope">
|
||||
{{ scope.$index + 1 }}
|
||||
@@ -144,6 +148,72 @@
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
<el-dialog title="生产计划可视化看板" :visible.sync="dashboardVisible" width="1200px" top="30px" :close-on-click-modal="false" @close="closeDashboard">
|
||||
<el-row :gutter="10" style="margin-bottom: 15px">
|
||||
<el-col :span="6">
|
||||
<el-card shadow="hover" style="text-align: center; padding: 10px 0; cursor: pointer" @click.native="cardViewMode = cardViewMode === 'status' ? 'orderType' : 'status'">
|
||||
<div v-if="cardViewMode === 'status'" style="color: #909399; font-size: 12px">订单总数</div>
|
||||
<div v-else style="color: #909399; font-size: 12px">订单总数</div>
|
||||
<div v-if="cardViewMode === 'status'" style="color: #303133; font-size: 24px; font-weight: bold">{{ dashboardStats.total }}</div>
|
||||
<div v-else style="color: #303133; font-size: 24px; font-weight: bold">{{ dashboardStats.total }}</div>
|
||||
<div style="color: #C0C4CC; font-size: 10px; margin-top: 4px">点击切换</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-card shadow="hover" style="text-align: center; padding: 10px 0; cursor: pointer" @click.native="cardViewMode = cardViewMode === 'status' ? 'orderType' : 'status'">
|
||||
<template v-if="cardViewMode === 'status'">
|
||||
<div style="color: #909399; font-size: 12px">派工中</div>
|
||||
<div style="color: #409EFF; font-size: 24px; font-weight: bold">{{ dashboardStats.pending }}</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div style="color: #909399; font-size: 12px">销售 / 补货(派工中)</div>
|
||||
<div style="font-size: 24px; font-weight: bold"><span style="color: #409EFF">{{ orderTypeStats.salesPending }}</span><span style="color: #C0C4CC; font-size: 14px"> / </span><span style="color: #E6A23C">{{ orderTypeStats.restockPending }}</span></div>
|
||||
</template>
|
||||
<div style="color: #C0C4CC; font-size: 10px; margin-top: 4px">点击切换</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-card shadow="hover" style="text-align: center; padding: 10px 0; cursor: pointer" @click.native="cardViewMode = cardViewMode === 'status' ? 'orderType' : 'status'">
|
||||
<template v-if="cardViewMode === 'status'">
|
||||
<div style="color: #909399; font-size: 12px">生产中</div>
|
||||
<div style="color: #67C23A; font-size: 24px; font-weight: bold">{{ dashboardStats.producing }}</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div style="color: #909399; font-size: 12px">销售 / 补货(生产中)</div>
|
||||
<div style="font-size: 24px; font-weight: bold"><span style="color: #409EFF">{{ orderTypeStats.salesProducing }}</span><span style="color: #C0C4CC; font-size: 14px"> / </span><span style="color: #E6A23C">{{ orderTypeStats.restockProducing }}</span></div>
|
||||
</template>
|
||||
<div style="color: #C0C4CC; font-size: 10px; margin-top: 4px">点击切换</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-card shadow="hover" style="text-align: center; padding: 10px 0; cursor: pointer" @click.native="cardViewMode = cardViewMode === 'status' ? 'orderType' : 'status'">
|
||||
<template v-if="cardViewMode === 'status'">
|
||||
<div style="color: #909399; font-size: 12px">已完成</div>
|
||||
<div style="color: #909399; font-size: 24px; font-weight: bold">{{ dashboardStats.completed }}</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div style="color: #909399; font-size: 12px">销售 / 补货(已完成)</div>
|
||||
<div style="font-size: 24px; font-weight: bold"><span style="color: #409EFF">{{ orderTypeStats.salesCompleted }}</span><span style="color: #C0C4CC; font-size: 14px"> / </span><span style="color: #E6A23C">{{ orderTypeStats.restockCompleted }}</span></div>
|
||||
</template>
|
||||
<div style="color: #C0C4CC; font-size: 10px; margin-top: 4px">点击切换</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="10">
|
||||
<el-col :span="8">
|
||||
<div id="statusPieChart" style="width: 100%; height: 400px"/>
|
||||
</el-col>
|
||||
<el-col :span="16">
|
||||
<div id="completionBarChart" style="width: 100%; height: 400px"/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="10" style="margin-top: 15px">
|
||||
<el-col :span="24">
|
||||
<div id="processStackChart" style="width: 100%; height: 350px"/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -154,29 +224,97 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
monthValue: '',
|
||||
orderNumberTypeValue: '', // 订单编号
|
||||
partNameValue: '', // 零件名称或图号
|
||||
productNameValue: '', // 产品名称
|
||||
statusValue: '', // 状态
|
||||
orderNumberTypeValue: '',
|
||||
partNameValue: '',
|
||||
productNameValue: '',
|
||||
statusValue: '',
|
||||
loading: false,
|
||||
tableData2: []
|
||||
tableData2: [],
|
||||
dashboardVisible: false,
|
||||
statusPieChart: null,
|
||||
completionBarChart: null,
|
||||
processStackChart: null,
|
||||
pieViewMode: 'status',
|
||||
cardViewMode: 'status'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'id',
|
||||
'token'
|
||||
])
|
||||
]),
|
||||
monthCompletionRate() {
|
||||
if (!this.tableData2 || this.tableData2.length === 0) return ''
|
||||
var completed = 0
|
||||
this.tableData2.forEach(function(row) {
|
||||
if (row.状态 === '已完成') completed++
|
||||
})
|
||||
var avg = Math.round(completed / this.tableData2.length * 100)
|
||||
return avg + '%'
|
||||
},
|
||||
filteredTableData() {
|
||||
if (!this.statusValue) return this.tableData2
|
||||
var val = this.statusValue
|
||||
return this.tableData2.filter(function(row) {
|
||||
return row.状态 === val
|
||||
})
|
||||
},
|
||||
monthCompletionRateTag() {
|
||||
var rate = parseInt(this.monthCompletionRate) || 0
|
||||
if (rate === 100) return 'info'
|
||||
if (rate >= 50) return 'success'
|
||||
return 'warning'
|
||||
},
|
||||
dashboardStats() {
|
||||
var total = this.tableData2.length
|
||||
var pending = 0
|
||||
var producing = 0
|
||||
var completed = 0
|
||||
this.tableData2.forEach(function(row) {
|
||||
if (row.状态 === '已完成') completed++
|
||||
else if (row.状态 === '生产中') producing++
|
||||
else pending++
|
||||
})
|
||||
return { total: total, pending: pending, producing: producing, completed: completed }
|
||||
},
|
||||
orderTypeStats() {
|
||||
var salesTotal = 0
|
||||
var restockTotal = 0
|
||||
var salesPending = 0
|
||||
var restockPending = 0
|
||||
var salesProducing = 0
|
||||
var restockProducing = 0
|
||||
var salesCompleted = 0
|
||||
var restockCompleted = 0
|
||||
this.tableData2.forEach(function(row) {
|
||||
var isRestock = row.收货人 === null
|
||||
if (isRestock) {
|
||||
restockTotal++
|
||||
if (row.状态 === '已完成') restockCompleted++
|
||||
else if (row.状态 === '生产中') restockProducing++
|
||||
else restockPending++
|
||||
} else {
|
||||
salesTotal++
|
||||
if (row.状态 === '已完成') salesCompleted++
|
||||
else if (row.状态 === '生产中') salesProducing++
|
||||
else salesPending++
|
||||
}
|
||||
})
|
||||
return {
|
||||
salesTotal: salesTotal, restockTotal: restockTotal,
|
||||
salesPending: salesPending, restockPending: restockPending,
|
||||
salesProducing: salesProducing, restockProducing: restockProducing,
|
||||
salesCompleted: salesCompleted, restockCompleted: restockCompleted
|
||||
}
|
||||
}
|
||||
},
|
||||
// updated() {
|
||||
// this.$nextTick(() => {
|
||||
// this.$refs['table'].doLayout()
|
||||
// })
|
||||
// },
|
||||
created() {
|
||||
this.getNowMonth()
|
||||
this.searchTable1()
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.disposeCharts()
|
||||
},
|
||||
methods: {
|
||||
getNowMonth() {
|
||||
const nowDate = new Date()
|
||||
@@ -285,6 +423,295 @@ export default {
|
||||
delete group._completedProcesses
|
||||
})
|
||||
return Object.values(grouped)
|
||||
},
|
||||
openDashboard() {
|
||||
if (this.tableData2.length === 0) {
|
||||
this.$message.warning('暂无数据,请先查询')
|
||||
return
|
||||
}
|
||||
this.dashboardVisible = true
|
||||
this.$nextTick(function() {
|
||||
this.drawStatusPieChart()
|
||||
this.drawCompletionBarChart()
|
||||
this.drawProcessStackChart()
|
||||
})
|
||||
},
|
||||
closeDashboard() {
|
||||
this.dashboardVisible = false
|
||||
},
|
||||
disposeCharts() {
|
||||
if (this.statusPieChart) {
|
||||
this.statusPieChart.dispose()
|
||||
this.statusPieChart = null
|
||||
}
|
||||
if (this.completionBarChart) {
|
||||
this.completionBarChart.dispose()
|
||||
this.completionBarChart = null
|
||||
}
|
||||
if (this.processStackChart) {
|
||||
this.processStackChart.dispose()
|
||||
this.processStackChart = null
|
||||
}
|
||||
},
|
||||
drawStatusPieChart() {
|
||||
var self = this
|
||||
this.statusPieChart = this.$echarts.init(document.getElementById('statusPieChart'))
|
||||
this.statusPieChart.clear()
|
||||
this.statusPieChart.off('click')
|
||||
this.statusPieChart.on('click', function() {
|
||||
self.pieViewMode = self.pieViewMode === 'status' ? 'orderType' : 'status'
|
||||
self.updatePieChart()
|
||||
})
|
||||
this.updatePieChart()
|
||||
},
|
||||
updatePieChart() {
|
||||
if (!this.statusPieChart) return
|
||||
this.statusPieChart.clear()
|
||||
if (this.pieViewMode === 'status') {
|
||||
var stats = this.dashboardStats
|
||||
this.statusPieChart.setOption({
|
||||
title: {
|
||||
text: '订单状态分布(点击切换)',
|
||||
left: 'center',
|
||||
textStyle: { fontSize: 14 }
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: '{b}: {c}单 ({d}%)'
|
||||
},
|
||||
legend: {
|
||||
bottom: 10,
|
||||
data: ['派工中', '生产中', '已完成']
|
||||
},
|
||||
color: ['#409EFF', '#67C23A', '#909399'],
|
||||
series: [{
|
||||
type: 'pie',
|
||||
radius: ['40%', '65%'],
|
||||
center: ['50%', '45%'],
|
||||
avoidLabelOverlap: true,
|
||||
label: {
|
||||
show: true,
|
||||
formatter: '{b}\n{c}单'
|
||||
},
|
||||
data: [
|
||||
{ value: stats.pending, name: '派工中' },
|
||||
{ value: stats.producing, name: '生产中' },
|
||||
{ value: stats.completed, name: '已完成' }
|
||||
]
|
||||
}]
|
||||
})
|
||||
} else {
|
||||
var salesCount = 0
|
||||
var restockCount = 0
|
||||
this.tableData2.forEach(function(row) {
|
||||
if (row.收货人 === null) {
|
||||
restockCount++
|
||||
} else {
|
||||
salesCount++
|
||||
}
|
||||
})
|
||||
this.statusPieChart.setOption({
|
||||
title: {
|
||||
text: '订单类型分布(点击切换)',
|
||||
left: 'center',
|
||||
textStyle: { fontSize: 14 }
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: '{b}: {c}单 ({d}%)'
|
||||
},
|
||||
legend: {
|
||||
bottom: 10,
|
||||
data: ['销售订单', '补货订单']
|
||||
},
|
||||
color: ['#409EFF', '#E6A23C'],
|
||||
series: [{
|
||||
type: 'pie',
|
||||
radius: ['40%', '65%'],
|
||||
center: ['50%', '45%'],
|
||||
avoidLabelOverlap: true,
|
||||
label: {
|
||||
show: true,
|
||||
formatter: '{b}\n{c}单'
|
||||
},
|
||||
data: [
|
||||
{ value: salesCount, name: '销售订单' },
|
||||
{ value: restockCount, name: '补货订单' }
|
||||
]
|
||||
}]
|
||||
})
|
||||
}
|
||||
},
|
||||
drawCompletionBarChart() {
|
||||
var orderLabels = []
|
||||
var completionRates = []
|
||||
var planCounts = []
|
||||
this.tableData2.forEach(function(row) {
|
||||
var label = row.MK订单编号 || row.订单号 || ''
|
||||
if (label.length > 10) label = label.substring(0, 10) + '...'
|
||||
orderLabels.push(label)
|
||||
completionRates.push(parseInt(row.完成率) || 0)
|
||||
planCounts.push(row.计划数 || 0)
|
||||
})
|
||||
this.completionBarChart = this.$echarts.init(document.getElementById('completionBarChart'))
|
||||
this.completionBarChart.clear()
|
||||
this.completionBarChart.setOption({
|
||||
title: {
|
||||
text: '各订单完成率',
|
||||
left: 'center',
|
||||
textStyle: { fontSize: 14 }
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: { type: 'shadow' },
|
||||
formatter: function(params) {
|
||||
var tip = params[0].axisValue + '<br/>'
|
||||
params.forEach(function(p) {
|
||||
tip += p.marker + p.seriesName + ': ' + p.value + (p.seriesName === '完成率' ? '%' : '') + '<br/>'
|
||||
})
|
||||
return tip
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
bottom: 0,
|
||||
data: ['完成率', '计划数']
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
bottom: '15%',
|
||||
top: '15%',
|
||||
containLabel: true
|
||||
},
|
||||
dataZoom: [
|
||||
{ type: 'inside', start: 0, end: 100 },
|
||||
{ type: 'slider', start: 0, end: 100, height: 20, bottom: 30 }
|
||||
],
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: orderLabels,
|
||||
axisLabel: { rotate: 30, fontSize: 10 }
|
||||
},
|
||||
yAxis: [
|
||||
{
|
||||
type: 'value',
|
||||
name: '完成率(%)',
|
||||
max: 100,
|
||||
axisLabel: { formatter: '{value}%' }
|
||||
},
|
||||
{
|
||||
type: 'value',
|
||||
name: '计划数',
|
||||
axisLabel: { formatter: '{value}' }
|
||||
}
|
||||
],
|
||||
series: [
|
||||
{
|
||||
name: '完成率',
|
||||
type: 'bar',
|
||||
yAxisIndex: 0,
|
||||
data: completionRates,
|
||||
itemStyle: {
|
||||
color: function(params) {
|
||||
var val = params.value
|
||||
if (val === 100) return '#67C23A'
|
||||
if (val >= 50) return '#E6A23C'
|
||||
return '#F56C6C'
|
||||
}
|
||||
},
|
||||
label: {
|
||||
show: true,
|
||||
position: 'top',
|
||||
formatter: '{c}%'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '计划数',
|
||||
type: 'line',
|
||||
yAxisIndex: 1,
|
||||
data: planCounts,
|
||||
itemStyle: { color: '#409EFF' },
|
||||
lineStyle: { width: 2 },
|
||||
symbolSize: 6
|
||||
}
|
||||
]
|
||||
})
|
||||
},
|
||||
drawProcessStackChart() {
|
||||
var opKeys = ['OP010', 'OP020', 'OP030', 'OP040', 'OP050', 'OP060', 'OP070', 'OP080', 'OP090', 'OP100', 'OP110']
|
||||
var opLabels = []
|
||||
var hasProcess = []
|
||||
var noProcess = []
|
||||
var self = this
|
||||
opKeys.forEach(function(key) {
|
||||
opLabels.push(key)
|
||||
var count = 0
|
||||
var empty = 0
|
||||
self.tableData2.forEach(function(row) {
|
||||
if (row[key] && row[key] !== '') {
|
||||
count++
|
||||
} else {
|
||||
empty++
|
||||
}
|
||||
})
|
||||
hasProcess.push(count)
|
||||
noProcess.push(empty)
|
||||
})
|
||||
this.processStackChart = this.$echarts.init(document.getElementById('processStackChart'))
|
||||
this.processStackChart.clear()
|
||||
this.processStackChart.setOption({
|
||||
title: {
|
||||
text: '各工序覆盖情况',
|
||||
left: 'center',
|
||||
textStyle: { fontSize: 14 }
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: { type: 'shadow' },
|
||||
formatter: function(params) {
|
||||
var tip = params[0].axisValue + '<br/>'
|
||||
params.forEach(function(p) {
|
||||
tip += p.marker + p.seriesName + ': ' + p.value + '单<br/>'
|
||||
})
|
||||
return tip
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
bottom: 0,
|
||||
data: ['已安排工序', '未安排工序']
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
bottom: '12%',
|
||||
top: '15%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: opLabels
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
name: '订单数'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '已安排工序',
|
||||
type: 'bar',
|
||||
stack: 'total',
|
||||
data: hasProcess,
|
||||
itemStyle: { color: '#67C23A' }
|
||||
},
|
||||
{
|
||||
name: '未安排工序',
|
||||
type: 'bar',
|
||||
stack: 'total',
|
||||
data: noProcess,
|
||||
itemStyle: { color: '#E6E6E6' }
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,7 +262,7 @@
|
||||
@click="editData(scope.row)">编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
:disabled="Number(scope.row.是否加工中)===1 || Number(scope.row.完成数) > 0 || Number(scope.row.报废数量) > 0 || scope.row.姓名==='外协'"
|
||||
:disabled="Number(scope.row.是否加工中)===1 || Number(scope.row.完成数) > 0 || Number(scope.row.报废数量) > 0 "
|
||||
type="text"
|
||||
icon="el-icon-delete"
|
||||
size="mini"
|
||||
|
||||
Reference in New Issue
Block a user