|
@@ -4,6 +4,7 @@
|
|
|
<a-tabs v-model="activeTab" @change="handleTabChange">
|
|
<a-tabs v-model="activeTab" @change="handleTabChange">
|
|
|
<a-tab-pane tab="按维修人统计" key="user"></a-tab-pane>
|
|
<a-tab-pane tab="按维修人统计" key="user"></a-tab-pane>
|
|
|
<a-tab-pane tab="按设备统计" key="sb"></a-tab-pane>
|
|
<a-tab-pane tab="按设备统计" key="sb"></a-tab-pane>
|
|
|
|
|
+ <a-tab-pane tab="按月度统计(设备平均维修工时)" key="month"></a-tab-pane>
|
|
|
</a-tabs>
|
|
</a-tabs>
|
|
|
|
|
|
|
|
<div class="table-page-search-wrapper" @keyup.enter="handleSearch">
|
|
<div class="table-page-search-wrapper" @keyup.enter="handleSearch">
|
|
@@ -19,7 +20,7 @@
|
|
|
<a-input v-model="queryParam.keyword" placeholder="请输入设备名称/编号" allow-clear/>
|
|
<a-input v-model="queryParam.keyword" placeholder="请输入设备名称/编号" allow-clear/>
|
|
|
</a-form-item>
|
|
</a-form-item>
|
|
|
</a-col>
|
|
</a-col>
|
|
|
- <a-col :md="10" :sm="24">
|
|
|
|
|
|
|
+ <a-col :md="10" :sm="24" v-if="activeTab !== 'month'">
|
|
|
<a-form-item label="维修开始时间">
|
|
<a-form-item label="维修开始时间">
|
|
|
<a-range-picker
|
|
<a-range-picker
|
|
|
v-model="dateRange"
|
|
v-model="dateRange"
|
|
@@ -28,6 +29,15 @@
|
|
|
:placeholder="['开始日期', '结束日期']"/>
|
|
:placeholder="['开始日期', '结束日期']"/>
|
|
|
</a-form-item>
|
|
</a-form-item>
|
|
|
</a-col>
|
|
</a-col>
|
|
|
|
|
+ <a-col :md="10" :sm="24" v-else>
|
|
|
|
|
+ <a-form-item label="统计月份">
|
|
|
|
|
+ <a-month-picker
|
|
|
|
|
+ v-model="queryParam.yearMonth"
|
|
|
|
|
+ format="YYYY-MM"
|
|
|
|
|
+ placeholder="选择月份"
|
|
|
|
|
+ style="width: 100%"/>
|
|
|
|
|
+ </a-form-item>
|
|
|
|
|
+ </a-col>
|
|
|
<a-col :md="6" :sm="24">
|
|
<a-col :md="6" :sm="24">
|
|
|
<span class="table-page-search-submitButtons">
|
|
<span class="table-page-search-submitButtons">
|
|
|
<a-button type="primary" @click="handleSearch">查询</a-button>
|
|
<a-button type="primary" @click="handleSearch">查询</a-button>
|
|
@@ -43,7 +53,7 @@
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px">
|
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px">
|
|
|
- <span style="font-weight: 600">{{ chartTitle }}(按总维修工时降序)</span>
|
|
|
|
|
|
|
+ <span style="font-weight: 600">{{ chartTitle }}(按平均工时降序)</span>
|
|
|
<span>
|
|
<span>
|
|
|
<a-radio-group v-if="activeTab === 'sb'" v-model="chartDim" size="small" style="margin-right: 8px" @change="doRenderChart">
|
|
<a-radio-group v-if="activeTab === 'sb'" v-model="chartDim" size="small" style="margin-right: 8px" @change="doRenderChart">
|
|
|
<a-radio-button value="sb">按设备</a-radio-button>
|
|
<a-radio-button value="sb">按设备</a-radio-button>
|
|
@@ -90,8 +100,11 @@ import DetailModal from './modules/DetailModal'
|
|
|
import {
|
|
import {
|
|
|
getWorkHourByUser,
|
|
getWorkHourByUser,
|
|
|
getWorkHourBySb,
|
|
getWorkHourBySb,
|
|
|
|
|
+ getWorkHourByMonth,
|
|
|
exportWorkHourUser,
|
|
exportWorkHourUser,
|
|
|
exportWorkHourSb,
|
|
exportWorkHourSb,
|
|
|
|
|
+ exportWorkHourMonth,
|
|
|
|
|
+ exportWorkHourMonthDetail,
|
|
|
exportWorkHourDetail
|
|
exportWorkHourDetail
|
|
|
} from '@/api/report/application-form'
|
|
} from '@/api/report/application-form'
|
|
|
|
|
|
|
@@ -103,12 +116,14 @@ export default {
|
|
|
},
|
|
},
|
|
|
data () {
|
|
data () {
|
|
|
return {
|
|
return {
|
|
|
- // 当前统计维度:user-按维修人,sb-按设备
|
|
|
|
|
|
|
+ // 当前统计维度:user-按维修人,sb-按设备,month-按月度统计
|
|
|
activeTab: 'user',
|
|
activeTab: 'user',
|
|
|
// 查询参数
|
|
// 查询参数
|
|
|
queryParam: {
|
|
queryParam: {
|
|
|
repairUserName: null,
|
|
repairUserName: null,
|
|
|
- keyword: null
|
|
|
|
|
|
|
+ keyword: null,
|
|
|
|
|
+ // 月度统计 Tab 使用:a-month-picker 的 moment 值
|
|
|
|
|
+ yearMonth: moment()
|
|
|
},
|
|
},
|
|
|
// 维修开始时间范围 默认本月,避免一次性拉取全部历史数据
|
|
// 维修开始时间范围 默认本月,避免一次性拉取全部历史数据
|
|
|
dateRange: [moment().startOf('month'), moment().endOf('month')],
|
|
dateRange: [moment().startOf('month'), moment().endOf('month')],
|
|
@@ -129,7 +144,7 @@ export default {
|
|
|
...parameter,
|
|
...parameter,
|
|
|
...query
|
|
...query
|
|
|
}
|
|
}
|
|
|
- const fetchFn = this.activeTab === 'user' ? getWorkHourByUser : getWorkHourBySb
|
|
|
|
|
|
|
+ const fetchFn = this.activeTab === 'user' ? getWorkHourByUser : (this.activeTab === 'month' ? getWorkHourByMonth : getWorkHourBySb)
|
|
|
return fetchFn(parameter)
|
|
return fetchFn(parameter)
|
|
|
.then(res => {
|
|
.then(res => {
|
|
|
return res.data
|
|
return res.data
|
|
@@ -140,9 +155,12 @@ export default {
|
|
|
computed: {
|
|
computed: {
|
|
|
chartTitle () {
|
|
chartTitle () {
|
|
|
if (this.activeTab === 'user') {
|
|
if (this.activeTab === 'user') {
|
|
|
- return '维修人工时统计图'
|
|
|
|
|
|
|
+ return '维修人平均工时统计图'
|
|
|
|
|
+ }
|
|
|
|
|
+ if (this.activeTab === 'month') {
|
|
|
|
|
+ return this.chartDim === 'type' ? '设备类型月度平均工时统计图' : '设备月度平均工时统计图'
|
|
|
}
|
|
}
|
|
|
- return this.chartDim === 'type' ? '设备类型工时统计图' : '设备工时统计图'
|
|
|
|
|
|
|
+ return this.chartDim === 'type' ? '设备类型平均工时统计图' : '设备平均工时统计图'
|
|
|
},
|
|
},
|
|
|
rowKey () {
|
|
rowKey () {
|
|
|
return this.activeTab === 'user' ? 'repairUserId' : 'sbId'
|
|
return this.activeTab === 'user' ? 'repairUserId' : 'sbId'
|
|
@@ -208,7 +226,7 @@ export default {
|
|
|
...commonColumns
|
|
...commonColumns
|
|
|
]
|
|
]
|
|
|
}
|
|
}
|
|
|
- return [
|
|
|
|
|
|
|
+ const sbColumns = [
|
|
|
indexColumn,
|
|
indexColumn,
|
|
|
{
|
|
{
|
|
|
title: '设备编号',
|
|
title: '设备编号',
|
|
@@ -227,6 +245,11 @@ export default {
|
|
|
},
|
|
},
|
|
|
...commonColumns
|
|
...commonColumns
|
|
|
]
|
|
]
|
|
|
|
|
+ // 月度统计不展示总停机修复时长
|
|
|
|
|
+ if (this.activeTab === 'month') {
|
|
|
|
|
+ return sbColumns.filter(c => c.dataIndex !== 'totalDealHours')
|
|
|
|
|
+ }
|
|
|
|
|
+ return sbColumns
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
mounted () {
|
|
mounted () {
|
|
@@ -241,7 +264,7 @@ export default {
|
|
|
methods: {
|
|
methods: {
|
|
|
loadChartData () {
|
|
loadChartData () {
|
|
|
this.chartLoading = true
|
|
this.chartLoading = true
|
|
|
- const fetchFn = this.activeTab === 'user' ? getWorkHourByUser : getWorkHourBySb
|
|
|
|
|
|
|
+ const fetchFn = this.activeTab === 'user' ? getWorkHourByUser : (this.activeTab === 'month' ? getWorkHourByMonth : getWorkHourBySb)
|
|
|
const parameter = {
|
|
const parameter = {
|
|
|
pageNum: 1,
|
|
pageNum: 1,
|
|
|
pageSize: 500,
|
|
pageSize: 500,
|
|
@@ -263,8 +286,7 @@ export default {
|
|
|
if (this.activeTab === 'user') {
|
|
if (this.activeTab === 'user') {
|
|
|
data = this.chartRows.map(r => ({
|
|
data = this.chartRows.map(r => ({
|
|
|
name: r.repairUserName || '-',
|
|
name: r.repairUserName || '-',
|
|
|
- totalRepairHours: Number(r.totalRepairHours || 0),
|
|
|
|
|
- num: Number(r.num || 0)
|
|
|
|
|
|
|
+ avgRepairHours: Number(r.avgRepairHours || 0)
|
|
|
}))
|
|
}))
|
|
|
} else if (this.chartDim === 'type') {
|
|
} else if (this.chartDim === 'type') {
|
|
|
// 按设备类型:前端对按设备全量数据分组汇总,次数/总工时求和,不重复请求后端
|
|
// 按设备类型:前端对按设备全量数据分组汇总,次数/总工时求和,不重复请求后端
|
|
@@ -279,18 +301,19 @@ export default {
|
|
|
})
|
|
})
|
|
|
data = Object.keys(groupMap).map(key => {
|
|
data = Object.keys(groupMap).map(key => {
|
|
|
const item = groupMap[key]
|
|
const item = groupMap[key]
|
|
|
- item.totalRepairHours = Math.round(item.totalRepairHours * 100) / 100
|
|
|
|
|
- return item
|
|
|
|
|
|
|
+ // 分组平均工时 = 组内总工时 / 组内次数(保留2位)
|
|
|
|
|
+ const avg = item.num ? Math.round((item.totalRepairHours / item.num) * 100) / 100 : 0
|
|
|
|
|
+ return { name: item.name, avgRepairHours: avg }
|
|
|
})
|
|
})
|
|
|
- data.sort((a, b) => b.totalRepairHours - a.totalRepairHours)
|
|
|
|
|
} else {
|
|
} else {
|
|
|
// 设备维度用名称(编号)区分同名设备
|
|
// 设备维度用名称(编号)区分同名设备
|
|
|
data = this.chartRows.map(r => ({
|
|
data = this.chartRows.map(r => ({
|
|
|
name: (r.sbName || '-') + '(' + (r.sbNo || '-') + ')',
|
|
name: (r.sbName || '-') + '(' + (r.sbNo || '-') + ')',
|
|
|
- totalRepairHours: Number(r.totalRepairHours || 0),
|
|
|
|
|
- num: Number(r.num || 0)
|
|
|
|
|
|
|
+ avgRepairHours: Number(r.avgRepairHours || 0)
|
|
|
}))
|
|
}))
|
|
|
}
|
|
}
|
|
|
|
|
+ // 柱状图为平均工时,统一按平均工时降序
|
|
|
|
|
+ data.sort((a, b) => b.avgRepairHours - a.avgRepairHours)
|
|
|
if (this.chartTop === 'top20' && data.length > 20) {
|
|
if (this.chartTop === 'top20' && data.length > 20) {
|
|
|
data = data.slice(0, 20)
|
|
data = data.slice(0, 20)
|
|
|
}
|
|
}
|
|
@@ -307,17 +330,14 @@ export default {
|
|
|
})
|
|
})
|
|
|
this.chart.data(data)
|
|
this.chart.data(data)
|
|
|
this.chart.scale({
|
|
this.chart.scale({
|
|
|
- totalRepairHours: { alias: '总维修工时(小时)', nice: true },
|
|
|
|
|
- num: { alias: '维修次数', nice: true }
|
|
|
|
|
|
|
+ avgRepairHours: { alias: '平均工时(小时)', nice: true }
|
|
|
})
|
|
})
|
|
|
this.chart.axis('name', { label: { autoRotate: true, autoHide: false } })
|
|
this.chart.axis('name', { label: { autoRotate: true, autoHide: false } })
|
|
|
- this.chart.axis('totalRepairHours', { title: { offset: 40 } })
|
|
|
|
|
- this.chart.axis('num', { title: { offset: 40 }, grid: null })
|
|
|
|
|
|
|
+ this.chart.axis('avgRepairHours', { title: { offset: 40 } })
|
|
|
this.chart.tooltip({ shared: true, showCrosshairs: false })
|
|
this.chart.tooltip({ shared: true, showCrosshairs: false })
|
|
|
this.chart.legend({ position: 'top-right' })
|
|
this.chart.legend({ position: 'top-right' })
|
|
|
- this.chart.interval().position('name*totalRepairHours')
|
|
|
|
|
- this.chart.line().position('name*num').color('#faad14').size(2)
|
|
|
|
|
- this.chart.point().position('name*num').color('#faad14').size(3).shape('circle')
|
|
|
|
|
|
|
+ // 仅平均工时柱状图
|
|
|
|
|
+ this.chart.interval().position('name*avgRepairHours')
|
|
|
this.chart.interaction('active-region')
|
|
this.chart.interaction('active-region')
|
|
|
// 全部模式下分类过多时出现横向滚动条,避免柱子过细、标签重叠
|
|
// 全部模式下分类过多时出现横向滚动条,避免柱子过细、标签重叠
|
|
|
this.chart.option('scrollbar', {
|
|
this.chart.option('scrollbar', {
|
|
@@ -332,12 +352,20 @@ export default {
|
|
|
if (this.BaseTool.String.isNotBlank(this.queryParam.repairUserName)) {
|
|
if (this.BaseTool.String.isNotBlank(this.queryParam.repairUserName)) {
|
|
|
query.repairUserName = this.queryParam.repairUserName
|
|
query.repairUserName = this.queryParam.repairUserName
|
|
|
}
|
|
}
|
|
|
|
|
+ } else if (this.activeTab === 'month') {
|
|
|
|
|
+ // 月度统计:后端按 yearMonth(YYYY-MM) 转当月起止时间
|
|
|
|
|
+ if (this.queryParam.yearMonth) {
|
|
|
|
|
+ query.yearMonth = this.queryParam.yearMonth.format('YYYY-MM')
|
|
|
|
|
+ }
|
|
|
|
|
+ if (this.BaseTool.String.isNotBlank(this.queryParam.keyword)) {
|
|
|
|
|
+ query.keyword = this.queryParam.keyword
|
|
|
|
|
+ }
|
|
|
} else {
|
|
} else {
|
|
|
if (this.BaseTool.String.isNotBlank(this.queryParam.keyword)) {
|
|
if (this.BaseTool.String.isNotBlank(this.queryParam.keyword)) {
|
|
|
query.keyword = this.queryParam.keyword
|
|
query.keyword = this.queryParam.keyword
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- if (this.dateRange && this.dateRange.length === 2) {
|
|
|
|
|
|
|
+ if (this.activeTab !== 'month' && this.dateRange && this.dateRange.length === 2) {
|
|
|
query.searchRepairStartTime = this.dateRange[0].format('YYYY-MM-DD') + ' 00:00:00'
|
|
query.searchRepairStartTime = this.dateRange[0].format('YYYY-MM-DD') + ' 00:00:00'
|
|
|
query.searchRepairEndTime = this.dateRange[1].format('YYYY-MM-DD') + ' 23:59:59'
|
|
query.searchRepairEndTime = this.dateRange[1].format('YYYY-MM-DD') + ' 23:59:59'
|
|
|
}
|
|
}
|
|
@@ -358,7 +386,8 @@ export default {
|
|
|
resetSearchForm () {
|
|
resetSearchForm () {
|
|
|
this.queryParam = {
|
|
this.queryParam = {
|
|
|
repairUserName: null,
|
|
repairUserName: null,
|
|
|
- keyword: null
|
|
|
|
|
|
|
+ keyword: null,
|
|
|
|
|
+ yearMonth: moment()
|
|
|
}
|
|
}
|
|
|
// 重置后仍默认统计本月
|
|
// 重置后仍默认统计本月
|
|
|
this.dateRange = [moment().startOf('month'), moment().endOf('month')]
|
|
this.dateRange = [moment().startOf('month'), moment().endOf('month')]
|
|
@@ -367,23 +396,26 @@ export default {
|
|
|
},
|
|
},
|
|
|
doExport () {
|
|
doExport () {
|
|
|
const parameter = this.buildQuery()
|
|
const parameter = this.buildQuery()
|
|
|
- const exportFn = this.activeTab === 'user' ? exportWorkHourUser : exportWorkHourSb
|
|
|
|
|
|
|
+ const exportFn = this.activeTab === 'user' ? exportWorkHourUser : (this.activeTab === 'month' ? exportWorkHourMonth : exportWorkHourSb)
|
|
|
exportFn(parameter).then(file => {
|
|
exportFn(parameter).then(file => {
|
|
|
this.BaseTool.UPLOAD.downLoadExportExcel(file)
|
|
this.BaseTool.UPLOAD.downLoadExportExcel(file)
|
|
|
})
|
|
})
|
|
|
},
|
|
},
|
|
|
handleDetail (record) {
|
|
handleDetail (record) {
|
|
|
const modal = this.$refs.detailModal
|
|
const modal = this.$refs.detailModal
|
|
|
|
|
+ const query = this.buildQuery()
|
|
|
modal.base({
|
|
modal.base({
|
|
|
type: this.activeTab,
|
|
type: this.activeTab,
|
|
|
record: record,
|
|
record: record,
|
|
|
- searchRepairStartTime: this.buildQuery().searchRepairStartTime,
|
|
|
|
|
- searchRepairEndTime: this.buildQuery().searchRepairEndTime
|
|
|
|
|
|
|
+ yearMonth: query.yearMonth,
|
|
|
|
|
+ searchRepairStartTime: query.searchRepairStartTime,
|
|
|
|
|
+ searchRepairEndTime: query.searchRepairEndTime
|
|
|
})
|
|
})
|
|
|
},
|
|
},
|
|
|
doExportDetail (record) {
|
|
doExportDetail (record) {
|
|
|
const parameter = this.buildDetailQuery(record)
|
|
const parameter = this.buildDetailQuery(record)
|
|
|
- exportWorkHourDetail(parameter).then(file => {
|
|
|
|
|
|
|
+ const exportFn = this.activeTab === 'month' ? exportWorkHourMonthDetail : exportWorkHourDetail
|
|
|
|
|
+ exportFn(parameter).then(file => {
|
|
|
this.BaseTool.UPLOAD.downLoadExportExcel(file)
|
|
this.BaseTool.UPLOAD.downLoadExportExcel(file)
|
|
|
})
|
|
})
|
|
|
},
|
|
},
|
|
@@ -395,6 +427,13 @@ export default {
|
|
|
parameter.sbId = record.sbId
|
|
parameter.sbId = record.sbId
|
|
|
}
|
|
}
|
|
|
const timeQuery = this.buildQuery()
|
|
const timeQuery = this.buildQuery()
|
|
|
|
|
+ if (this.activeTab === 'month') {
|
|
|
|
|
+ // 月度明细导出:传 yearMonth(YYYY-MM),后端转当月起止时间
|
|
|
|
|
+ if (timeQuery.yearMonth) {
|
|
|
|
|
+ parameter.yearMonth = timeQuery.yearMonth
|
|
|
|
|
+ }
|
|
|
|
|
+ return parameter
|
|
|
|
|
+ }
|
|
|
if (timeQuery.searchRepairStartTime) {
|
|
if (timeQuery.searchRepairStartTime) {
|
|
|
parameter.searchRepairStartTime = timeQuery.searchRepairStartTime
|
|
parameter.searchRepairStartTime = timeQuery.searchRepairStartTime
|
|
|
}
|
|
}
|