装备配置率配置
This commit is contained in:
parent
b7597e8f8a
commit
3e78f2c738
|
|
@ -10,6 +10,30 @@ export function listUser(query) {
|
|||
})
|
||||
}
|
||||
|
||||
export function getOwnEquipmentList(query) {
|
||||
return request({
|
||||
url: '/material-mall/deptConfig/getOwnEquipmentList',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
export function getSharingEquipmentList(query) {
|
||||
return request({
|
||||
url: '/material-mall/deptConfig/getSharingEquipmentList',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
export function getRentalEquipmentList(query) {
|
||||
return request({
|
||||
url: '/material-mall/deptConfig/getRentalEquipmentList',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
export function selectResourceList(query) {
|
||||
return request({
|
||||
url: '/material-mall/deptConfig/selectResourceList',
|
||||
|
|
@ -26,6 +50,41 @@ export function selectInventoryList(query) {
|
|||
})
|
||||
}
|
||||
|
||||
export function saveInstanceSelection(data) {
|
||||
return request({
|
||||
url: '/material-mall/deptConfig/saveInstanceSelection',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
export function getConfigurationTotal() {
|
||||
return request({
|
||||
url: '/material-mall/deptConfig/getConfigurationTotal',
|
||||
method: 'post'
|
||||
})
|
||||
}
|
||||
|
||||
export function getConfigurationDetails(data) {
|
||||
return request({
|
||||
url: '/material-mall/deptConfig/getConfigurationDetails',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
export function exportStatsData() {
|
||||
return request({
|
||||
url: '/material-mall/deptConfig/exportStatsData',
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
export function insertResource(data) {
|
||||
return request({
|
||||
url: '/material-mall/deptConfig/insertResource',
|
||||
|
|
|
|||
|
|
@ -1,227 +1,389 @@
|
|||
<template>
|
||||
<div class="equipment-table">
|
||||
<h2 class="title" v-if="!showSecondPage">机械化机械化施工装备配置率 </h2>
|
||||
<el-card class="content-box" style="height: 800px" v-if="!showSecondPage">
|
||||
<div v-if="!showSecondPage">
|
||||
<el-table
|
||||
:data="tableData"
|
||||
border
|
||||
stripe
|
||||
:header-cell-style="headerCellStyle"
|
||||
show-overflow-tooltip
|
||||
:cell-style="{ textAlign: 'center' }"
|
||||
class="custom-table"
|
||||
height="800"
|
||||
>
|
||||
<el-table-column width="240" align="center">
|
||||
<template slot="header">
|
||||
<div class="diagonal-header">
|
||||
<div class="diagonal-line"></div>
|
||||
<div class="header-top">指标项</div>
|
||||
<div class="header-bottom">公司</div>
|
||||
</div>
|
||||
</template>
|
||||
<template slot-scope="scope">
|
||||
<div>{{ scope.row.companyName }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="valueA" label="线路设备配置率">
|
||||
<template slot-scope="scope">
|
||||
<span class="link" @click="handleDrill(scope.row, 0)">{{ scope.row.valueA + scope.row.newValueA }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="valueB" label="电缆设备配置率">
|
||||
<template slot-scope="scope">
|
||||
<span class="link" @click="handleDrill(scope.row, 1)">{{ scope.row.valueB+scope.row.newValueB }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="valueC" label="变电设备配置率">
|
||||
<template slot-scope="scope">
|
||||
<span class="link" @click="handleDrill(scope.row, 2)">{{ scope.row.valueC+scope.row.newValueC }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="app-container">
|
||||
<!-- 图表卡片:纯div布局,保留核心ref和样式类 -->
|
||||
<div class="chart-card">
|
||||
<div class="chart-container" ref="chartContainer">
|
||||
<div ref="chartRef" class="echarts echarts-box"></div>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
<LineDetail
|
||||
v-if="showSecondPage"
|
||||
:key="secondPageTitleId + '_' + secondPageTitle"
|
||||
:title="secondPageTitle"
|
||||
:secondPageTitleId="secondPageTitleId"
|
||||
:table-data="detailTableData"
|
||||
@back="handleBack"
|
||||
/>
|
||||
<div class="table-card">
|
||||
<div class="table-header">
|
||||
<el-button
|
||||
type="primary"
|
||||
style="float: right"
|
||||
icon="el-icon-download"
|
||||
@click="exportTableData"
|
||||
>
|
||||
导出数据
|
||||
</el-button>
|
||||
</div>
|
||||
<el-table
|
||||
:data="tableData"
|
||||
border
|
||||
stripe
|
||||
:fit="true"
|
||||
class="stats-table"
|
||||
v-loading="tableLoading"
|
||||
>
|
||||
<el-table-column label="序号" type="index" width="60" align="center"/>
|
||||
<el-table-column label="公司" prop="deptName" min-width="150" align="center"/>
|
||||
<el-table-column
|
||||
label="线路设备配置率"
|
||||
prop="lineNum"
|
||||
min-width="120"
|
||||
align="center"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span class="link" @click="handleCellClick(scope.row.deptId, 0)">{{ scope.row.lineNum }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="电缆设备配置率"
|
||||
prop="cableNum"
|
||||
min-width="120"
|
||||
align="center"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span class="link" @click="handleCellClick(scope.row.deptId, 2)">{{ scope.row.cableNum }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="变电设备配置率"
|
||||
prop="substationNum"
|
||||
min-width="120"
|
||||
align="center"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span class="link" @click="handleCellClick(scope.row.deptId, 1)">{{ scope.row.substationNum }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="总配置率" prop="num" min-width="100" align="center"/>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<!-- 配置率详情弹窗 -->
|
||||
<el-dialog
|
||||
title="装备配置率明细"
|
||||
:visible.sync="detailDialogVisible"
|
||||
width="90%"
|
||||
top="20px"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<el-table
|
||||
:data="detailTableData"
|
||||
border
|
||||
stripe
|
||||
|
||||
v-loading="detailTableLoading"
|
||||
max-height="600px"
|
||||
>
|
||||
<!-- 明细表格列(匹配用户提供的表格结构) -->
|
||||
<el-table-column label="序号" type="index" width="60" align="center"/>
|
||||
<el-table-column label="装备名称" prop="typeName" min-width="120" align="center"/>
|
||||
<el-table-column label="电压等级" prop="vol" min-width="100" align="center"/>
|
||||
<el-table-column label="地理特征" prop="type" min-width="100" align="center"/>
|
||||
<el-table-column label="配置标准(台)" prop="configValue" min-width="100" align="center"/>
|
||||
<el-table-column label="装备种类" prop="jijuType" min-width="100" align="center"/>
|
||||
<el-table-column label="配置说明" prop="configDescription" min-width="120" align="center"/>
|
||||
<el-table-column label="装备配置率赋值" prop="configRate" min-width="120" align="center"/>
|
||||
<el-table-column label="自有装配数量" prop="ownNum" min-width="120" align="center"/>
|
||||
<el-table-column label="共享装备数量" prop="shareNum" min-width="120" align="center"/>
|
||||
<el-table-column label="外租装备数量" prop="rentOutNum" min-width="120" align="center"/>
|
||||
<el-table-column label="装备实际配置率" prop="baseAddNum" min-width="120" align="center"/>
|
||||
<el-table-column label="特殊装备配备原因" prop="remark" min-width="150" align="center"/>
|
||||
</el-table>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="detailDialogVisible = false">关闭</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listRate, getDetailList } from '@/api/rent-facility/index'
|
||||
import LineDetail from '@/views/rent-facility/line.vue'
|
||||
import * as echarts from 'echarts'
|
||||
import { getConfigurationTotal, exportStatsData, getConfigurationDetails } from '@/api/system/equipmentNew'
|
||||
|
||||
export default {
|
||||
components: { LineDetail },
|
||||
|
||||
name: 'ConfigStatsPage',
|
||||
data() {
|
||||
return {
|
||||
// 表格数据
|
||||
showSearch: true,
|
||||
searchForm: {
|
||||
companyName: '',
|
||||
voltageLevel: '',
|
||||
terrainType: ''
|
||||
},
|
||||
tableData: [],
|
||||
showSecondPage: false,
|
||||
secondPageTitle: '',
|
||||
secondPageTitleId: '',
|
||||
detailTableData: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 表头样式
|
||||
headerCellStyle() {
|
||||
return {
|
||||
background: '#2CBAB2 !important',
|
||||
color: '#fff',
|
||||
textAlign: 'center'
|
||||
}
|
||||
tableLoading: false,
|
||||
tableHeight: 'auto',
|
||||
chartInstance: null,
|
||||
chartOption: {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: { type: 'shadow' },
|
||||
formatter: function(params) {
|
||||
let res = params[0].name
|
||||
params.forEach((item) => {
|
||||
const nameMap = {
|
||||
xianlu: '线路配置率',
|
||||
dianlan: '电缆配置率',
|
||||
biandian: '变电配置率'
|
||||
}
|
||||
res += `<br/>${nameMap[item.seriesName] || item.seriesName}:${item.value}`
|
||||
})
|
||||
return res
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
data: ['xianlu', 'dianlan', 'biandian'],
|
||||
formatter: function(name) {
|
||||
const nameMap = { xianlu: '线路', dianlan: '电缆', biandian: '变电' }
|
||||
return nameMap[name] || name
|
||||
},
|
||||
right: '10%'
|
||||
},
|
||||
grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true },
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: [],
|
||||
axisLabel: {
|
||||
rotate: 0,
|
||||
fontSize: 12,
|
||||
interval: 0,
|
||||
width: 80,
|
||||
lineHeight: 20,
|
||||
align: 'center',
|
||||
formatter: function(value) {
|
||||
let str = ''
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
str += value[i]
|
||||
if ((i + 1) % 6 === 0) str += '\n'
|
||||
}
|
||||
return str
|
||||
}
|
||||
}
|
||||
},
|
||||
yAxis: { type: 'value', axisLabel: { formatter: '{value}' } },
|
||||
series: [
|
||||
{ name: 'xianlu', type: 'bar', data: [], itemStyle: { color: '#409EFF' } },
|
||||
{ name: 'dianlan', type: 'bar', data: [], itemStyle: { color: '#67C23A' } },
|
||||
{ name: 'biandian', type: 'bar', data: [], itemStyle: { color: '#E6A23C' } }
|
||||
]
|
||||
},
|
||||
resizeTimer: null,
|
||||
// 新增:弹窗相关数据
|
||||
detailDialogVisible: false,
|
||||
detailTableData: [],
|
||||
detailTableLoading: false,
|
||||
// 记录当前点击的行数据和列类型
|
||||
currentClickRow: null,
|
||||
currentClickType: '' // line(线路)/cable(电缆)/substation(变电)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.fetchData()
|
||||
this.$nextTick(async() => {
|
||||
await this.initPage()
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
// 获取数据函数
|
||||
async fetchData() {
|
||||
// 初始化页面数据:请求成功后再初始化图表
|
||||
async initPage() {
|
||||
this.tableLoading = true
|
||||
try {
|
||||
const response = await listRate()
|
||||
if (response.code === 200 && response.rows) {
|
||||
this.tableData = response.rows || []
|
||||
} else {
|
||||
console.error('API返回数据格式错误:', response)
|
||||
const res = await getConfigurationTotal(this.searchForm)
|
||||
if (res.code === 200) {
|
||||
const statsData = res.data || []
|
||||
this.tableData = statsData
|
||||
this.$nextTick(() => {
|
||||
this.initChart()
|
||||
this.updateChartData(statsData)
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取数据失败:', error)
|
||||
} catch (err) {
|
||||
console.error('获取统计数据失败:', err)
|
||||
this.$message.error('获取统计数据失败,请稍后重试')
|
||||
} finally {
|
||||
this.tableLoading = false
|
||||
}
|
||||
},
|
||||
|
||||
// 钻取详情
|
||||
async handleDrill(row, type) {
|
||||
// 1. 先清空旧数据并隐藏旧页面,避免组件未刷新
|
||||
this.showSecondPage = true
|
||||
this.detailTableData = []
|
||||
// 初始化ECharts:增加DOM宽高校验+兜底
|
||||
initChart() {
|
||||
const chartDom = this.$refs.chartRef
|
||||
if (!chartDom || this.chartInstance) return
|
||||
|
||||
// 2. 调接口拿到详情数据
|
||||
const res = await getDetailList({ companyId: row.companyId, configType: type })
|
||||
if (res.code === 200) {
|
||||
this.secondPageTitle = `${row.companyName}详情页面`
|
||||
this.secondPageTitleId = row.companyId
|
||||
this.detailTableData = res.rows
|
||||
const clientWidth = chartDom.clientWidth || 800
|
||||
const clientHeight = chartDom.clientHeight || 400
|
||||
if (clientWidth === 0 || clientHeight === 0) {
|
||||
chartDom.style.width = '100%'
|
||||
chartDom.style.height = '450px'
|
||||
}
|
||||
|
||||
// 3. 等组件清理完后再显示
|
||||
this.$nextTick(() => {
|
||||
this.showSecondPage = true
|
||||
})
|
||||
if (this.chartInstance) {
|
||||
this.chartInstance.dispose()
|
||||
this.chartInstance = null
|
||||
}
|
||||
|
||||
this.chartInstance = echarts.init(chartDom)
|
||||
this.chartInstance.setOption(this.chartOption, true)
|
||||
},
|
||||
|
||||
// 更新图表数据:数据同步后强制重绘
|
||||
updateChartData(data) {
|
||||
if (!this.chartInstance || !Array.isArray(data) || data.length === 0) return
|
||||
|
||||
const xAxisData = []
|
||||
const xianluData = []
|
||||
const dianlanData = []
|
||||
const biandianData = []
|
||||
|
||||
data.forEach((item) => {
|
||||
xAxisData.push(item.deptName || '')
|
||||
xianluData.push(item.lineNum || 0)
|
||||
dianlanData.push(item.cableNum || 0)
|
||||
biandianData.push(item.substationNum || 0)
|
||||
})
|
||||
|
||||
const allData = [...xianluData, ...dianlanData, ...biandianData]
|
||||
const maxValue = Math.max(...allData)
|
||||
const dynamicYmax = Math.ceil(maxValue * 1.1)
|
||||
|
||||
this.chartInstance.setOption({
|
||||
xAxis: { data: xAxisData },
|
||||
yAxis: { max: dynamicYmax },
|
||||
series: [
|
||||
{ name: 'xianlu', data: xianluData },
|
||||
{ name: 'dianlan', data: dianlanData },
|
||||
{ name: 'biandian', data: biandianData }
|
||||
]
|
||||
})
|
||||
|
||||
this.chartInstance.resize()
|
||||
},
|
||||
|
||||
// 导出数据:保持原有逻辑,增加loading
|
||||
async exportTableData() {
|
||||
this.$loading({ text: '正在导出,请稍候...' })
|
||||
try {
|
||||
let fileName = `装备配置率统计_${new Date().getTime()}.xLsx`
|
||||
let url = '/material-mall/deptConfig/exportStatsData'
|
||||
this.download(url, {}, fileName)
|
||||
this.$message.success('导出成功')
|
||||
} catch (err) {
|
||||
console.error('导出失败:', err)
|
||||
this.$message.error('导出失败,请稍后重试')
|
||||
} finally {
|
||||
this.$loading().close()
|
||||
}
|
||||
},
|
||||
|
||||
// 返回主页面
|
||||
handleBack() {
|
||||
this.showSecondPage = false
|
||||
// 新增:单元格点击事件处理
|
||||
handleCellClick(deptId, configType) {
|
||||
// 打开弹窗并加载明细数据
|
||||
this.detailDialogVisible = true
|
||||
this.loadConfigDetail(deptId, configType)
|
||||
},
|
||||
|
||||
// 新增:加载配置率明细数据
|
||||
async loadConfigDetail(deptId, configType) {
|
||||
this.detailTableLoading = true
|
||||
try {
|
||||
// 构造请求参数(公司名称+配置类型+搜索条件)
|
||||
const params = {
|
||||
deptId: deptId,
|
||||
configType: configType
|
||||
}
|
||||
const res = await getConfigurationDetails(params)
|
||||
if (res.code === 200) {
|
||||
this.detailTableData = res.data || []
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('获取配置率明细失败:', err)
|
||||
this.$message.error('获取配置率明细失败,请稍后重试')
|
||||
this.detailTableData = []
|
||||
} finally {
|
||||
this.detailTableLoading = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.equipment-table {
|
||||
padding: 20px;
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
|
||||
<!-- 非scoped样式:ECharts容器+全局滚动条(保留) -->
|
||||
<style lang="scss">
|
||||
.echarts-box {
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
min-width: 300px;
|
||||
min-height: 300px;
|
||||
}
|
||||
|
||||
.title {
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
font-size: 18px;
|
||||
margin-bottom: 20px;
|
||||
color: #2CBAB2;
|
||||
::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
}
|
||||
|
||||
.diagonal-header {
|
||||
::-webkit-scrollbar-thumb {
|
||||
border-radius: 3px;
|
||||
background: #dcdfe6;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: #f5f7fa;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- scoped样式:核心调整,适配纯div布局 -->
|
||||
<style scoped lang="scss">
|
||||
.app-container {
|
||||
width: 100%;
|
||||
// background-color: #00a288;
|
||||
// color: white;
|
||||
position: relative;
|
||||
height: 40px;
|
||||
font-size: 12px;
|
||||
height: calc(99vh - 84px);
|
||||
padding: 16px;
|
||||
box-sizing: border-box;
|
||||
background: #f5f7fa;
|
||||
overflow: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.diagonal-line {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
.chart-card {
|
||||
background: #fff;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||
padding: 16px;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
height: 450px;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.chart-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(
|
||||
to top right,
|
||||
transparent 49.5%,
|
||||
white 49.5%,
|
||||
white 50.5%,
|
||||
transparent 50.5%
|
||||
);
|
||||
}
|
||||
|
||||
.header-top {
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
right: 6px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.header-bottom {
|
||||
position: absolute;
|
||||
bottom: 4px;
|
||||
left: 8px;
|
||||
z-index: 1;
|
||||
.table-card {
|
||||
background: #fff;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||
padding: 16px;
|
||||
height: 99vh;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.link {
|
||||
color: #2CBAB2 ;
|
||||
color: #2CBAB2;
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.link:hover {
|
||||
color: #23b8b1;
|
||||
}
|
||||
|
||||
.custom-table :deep(th),
|
||||
.custom-table :deep(td) {
|
||||
border: 1px solid #ebeef5;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
::v-deep .el-table {
|
||||
// 启用斑马纹
|
||||
&.el-table--striped .el-table__body {
|
||||
tr.el-table__row--striped td {
|
||||
background-color: #F6FBFA !important; // 浅紫色
|
||||
}
|
||||
}
|
||||
|
||||
.el-table__header {
|
||||
background: #E9F0EE;
|
||||
|
||||
th {
|
||||
background: #E9F0EE !important;
|
||||
color: #606266;
|
||||
font-weight: 600;
|
||||
height: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
&.el-table--striped .el-table__body tr.el-table__row:hover > td.el-table__cell {
|
||||
background-color: #CCF1E9 !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue