Browse Source

平均生产周期

master
han\hanst 3 weeks ago
parent
commit
788871a5b3
  1. 207
      src/views/modules/longtron/screen-factory-overview.vue

207
src/views/modules/longtron/screen-factory-overview.vue

@ -47,7 +47,7 @@
<div id="overviewPieChart" class="chart-box"></div> <div id="overviewPieChart" class="chart-box"></div>
</div> </div>
<div class="panel wide"> <div class="panel wide">
<div class="panel-title">最近 7 天完工趋势</div>
<div class="panel-title">平均生产周期</div>
<div id="overviewLineChart" class="chart-box line-box"></div> <div id="overviewLineChart" class="chart-box line-box"></div>
</div> </div>
<div class="panel"> <div class="panel">
@ -91,6 +91,16 @@ const NODE_DISPLAY_NAME_ALIAS = {
线缆生产: '线缆/COP', 线缆生产: '线缆/COP',
COP生产: '线缆/COP' COP生产: '线缆/COP'
} }
const AVERAGE_CYCLE_CATEGORY_LIST = [
{ key: 'VW', name: 'VW', orderType: 'HOME_LIFT' },
{ key: 'VC', name: 'VC', orderType: 'HOME_LIFT' },
{ key: 'Y18', name: 'Y18', orderType: 'HOME_LIFT' },
{ key: 'VL3.0', name: 'VL3.0', orderType: 'HOME_LIFT' },
{ key: 'VC2.0', name: 'VC2.0', orderType: 'HOME_LIFT' },
{ key: 'Y18 2.0', name: 'Y18 2.0', orderType: 'HOME_LIFT' },
{ key: 'VL2.5', name: 'VL2.5', orderType: 'RENOVATION' },
{ key: '机加工', name: '机加工', orderType: 'MACHINING' }
]
export default { export default {
name: 'ScreenFactoryOverview', name: 'ScreenFactoryOverview',
@ -164,6 +174,10 @@ export default {
return (sourceList || []) return (sourceList || [])
.filter(item => STATUS_ALLOW_LIST.includes(item.status)) .filter(item => STATUS_ALLOW_LIST.includes(item.status))
.map(item => ({ .map(item => ({
orderNo: item.orderNo || '',
taskNo: item.taskNo || '',
projectNo: item.projectNo || '',
modelNo: item.modelNo || '',
status: item.status || '', status: item.status || '',
planDeliveryDate: item.planDeliveryDate || '', planDeliveryDate: item.planDeliveryDate || '',
planFinishDate: item.planFinishDate || '', planFinishDate: item.planFinishDate || '',
@ -213,7 +227,7 @@ export default {
this.$nextTick(() => { this.$nextTick(() => {
this.renderBarChart() this.renderBarChart()
this.renderPieChart() this.renderPieChart()
this.renderLineChart()
this.renderCycleChart()
}) })
}, },
countByMonth(list, monthStart) { countByMonth(list, monthStart) {
@ -416,44 +430,175 @@ export default {
}] }]
}, true) }, true)
}, },
renderLineChart() {
renderCycleChart() {
const el = document.getElementById('overviewLineChart') const el = document.getElementById('overviewLineChart')
if (!el) return if (!el) return
if (!this.chartLine) this.chartLine = echarts.init(el) if (!this.chartLine) this.chartLine = echarts.init(el)
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))
}
const cycleCategoryList = this.buildAverageCycleCategoryList()
this.chartLine.setOption({ this.chartLine.setOption({
animation: false, animation: false,
color: ['#6cc7ff', '#74e0b3', '#7fa6d9', '#f5c15e'],
grid: { left: 35, right: 20, top: 34, bottom: 20, containLabel: true },
tooltip: { trigger: 'axis' },
legend: { textStyle: { color: '#cbe7ff', fontSize: 13 }, data: ['整梯完工', 'VL2.5升级完工', '线缆/COP完工', '机加工完工'] },
xAxis: { type: 'category', axisLabel: { color: '#cbe7ff', fontSize: 13 }, data: xAxis },
yAxis: { type: 'value', axisLabel: { color: '#cbe7ff', fontSize: 13 }, splitLine: { lineStyle: { color: 'rgba(160,200,240,0.15)' } } },
color: ['#4f73bd'],
grid: { left: 35, right: 20, top: 34, bottom: 26, containLabel: true },
tooltip: {
trigger: 'axis',
formatter: (params) => {
const point = (params && params[0]) || {}
return `${point.axisValue}<br/>平均生产周期:${point.value || 0}`
}
},
xAxis: {
type: 'category',
axisTick: { alignWithLabel: true },
axisLabel: { color: '#cbe7ff', fontSize: 13, interval: 0 },
axisLine: { lineStyle: { color: 'rgba(160,200,240,0.35)' } },
data: cycleCategoryList.map(item => item.name)
},
yAxis: {
type: 'value',
min: 0,
minInterval: 1,
max: (value) => {
const maxValue = Number(value && value.max ? value.max : 0)
if (maxValue <= 0) {
return 5
}
return maxValue + Math.max(1, Math.ceil(maxValue * 0.15))
},
axisLabel: { color: '#cbe7ff', fontSize: 13 },
splitLine: { lineStyle: { color: 'rgba(160,200,240,0.15)' } }
},
series: [ 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: '线缆/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)' } }
{
name: '平均生产周期',
type: 'bar',
barWidth: 26,
data: cycleCategoryList.map(item => item.value),
itemStyle: { color: '#4f73bd' },
label: {
normal: {
show: true,
position: 'top',
distance: 6,
color: '#d4ebff',
fontSize: 20,
formatter: ({ value }) => this.formatCycleLabel(value)
}
}
}
] ]
}, true) }, true)
}, },
countFinishByDay(list, day) {
return list.filter(item => {
const finishDate = this.toDayjs(item.finishDate)
return finishDate && finishDate.format('YYYY-MM-DD') === day.format('YYYY-MM-DD')
}).length
buildAverageCycleCategoryList() {
const wholeCategoryList = this.buildWholeLiftAverageCycleMap()
const renovationAverageCycle = this.calcAverageCycleByList(this.renovationList)
const machiningAverageCycle = this.calcAverageCycleByList(this.machiningList)
return AVERAGE_CYCLE_CATEGORY_LIST.map((item) => {
if (item.orderType === 'HOME_LIFT') {
return {
...item,
value: this.formatCycleValue(wholeCategoryList[item.key])
}
}
if (item.key === 'VL2.5') {
return {
...item,
value: this.formatCycleValue(renovationAverageCycle)
}
}
return {
...item,
value: this.formatCycleValue(machiningAverageCycle)
}
})
},
buildWholeLiftAverageCycleMap() {
const sumMap = {}
const countMap = {}
AVERAGE_CYCLE_CATEGORY_LIST
.filter(item => item.orderType === 'HOME_LIFT')
.forEach(item => {
sumMap[item.key] = 0
countMap[item.key] = 0
})
this.wholeList.forEach(item => {
if (!item || item.status !== '已完成') return
const categoryKey = this.resolveWholeLiftCategoryKey(item)
if (!categoryKey || !Object.prototype.hasOwnProperty.call(sumMap, categoryKey)) return
const cycleDays = this.resolveCycleDays(item)
if (cycleDays <= 0) return
sumMap[categoryKey] += cycleDays
countMap[categoryKey] += 1
})
const avgMap = {}
Object.keys(sumMap).forEach((key) => {
avgMap[key] = countMap[key] > 0 ? sumMap[key] / countMap[key] : 0
})
return avgMap
},
resolveWholeLiftCategoryKey(item) {
const identity = this.normalizeModelIdentity(
item && (item.modelNo || item.projectNo || item.taskNo || item.orderNo)
)
if (!identity) {
return ''
}
if (identity.indexOf('VL3.0') === 0 || identity.indexOf('VL30') === 0) {
return 'VL3.0'
}
if (identity.indexOf('VC2.0') === 0 || identity.indexOf('VC20') === 0) {
return 'VC2.0'
}
if (identity.indexOf('Y18 2.0') === 0 || identity.indexOf('Y182.0') === 0 || identity.indexOf('Y1820') === 0) {
return 'Y18 2.0'
}
if (identity.indexOf('Y18') === 0) {
return 'Y18'
}
if (identity.indexOf('C') === 0) {
return 'VC'
}
if (/^V\d+/.test(identity) || identity.indexOf('V') === 0) {
return 'VW'
}
return ''
},
normalizeModelIdentity(identityValue) {
return String(identityValue || '')
.toUpperCase()
.replace(/[((].*?[))]/g, '')
.replace(/[-_/]/g, ' ')
.replace(/\s+/g, ' ')
.trim()
},
calcAverageCycleByList(list) {
let sum = 0
let count = 0
;(list || []).forEach(item => {
if (!item || item.status !== '已完成') return
const cycleDays = this.resolveCycleDays(item)
if (cycleDays <= 0) return
sum += cycleDays
count += 1
})
return count > 0 ? (sum / count) : 0
},
resolveCycleDays(item) {
if (!item) return 0
const finishDate = this.toDayjs(item.finishDate || item.planDeliveryDate || item.planFinishDate)
const startDate = this.toDayjs(item.createTime || item.planFinishDate || item.planDeliveryDate)
if (!finishDate || !startDate) return 0
const diffDays = finishDate.diff(startDate, 'day', true)
return diffDays > 0 ? diffDays : 0
},
formatCycleValue(value) {
const numericValue = Number(value || 0)
if (!Number.isFinite(numericValue) || numericValue <= 0) return 0
return Math.ceil(numericValue)
},
formatCycleLabel(value) {
const numericValue = Number(value || 0)
if (!Number.isFinite(numericValue)) return '0'
return String(Math.ceil(numericValue))
}, },
updateTime() { updateTime() {
const now = new Date() const now = new Date()

Loading…
Cancel
Save