装备台账
This commit is contained in:
parent
4f931ac21f
commit
5d01997d39
|
|
@ -77,4 +77,9 @@ export default {
|
|||
}
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'OpenSans-BoldItalic';
|
||||
src: url('~@/assets/font-family/OpenSans-BoldItalic.ttf');
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -368,3 +368,48 @@ export const getConfigApi = (data) => {
|
|||
method: 'GET',
|
||||
})
|
||||
}
|
||||
|
||||
// 总价值
|
||||
export const getTotalValueApi = (data = {}) => {
|
||||
return request({
|
||||
url: `/material-mall/device/getTotalValue`,
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 配置率
|
||||
export const getConfigurationRateApi = (data = {}) => {
|
||||
return request({
|
||||
url: `/material-mall/device/getConfigurationRate`,
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 装备状态分析
|
||||
export const getEquipmentStatusApi = (data = {}) => {
|
||||
return request({
|
||||
url: `/material-mall/device/getEquipmentStatus`,
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 装备数量分析-三大专业
|
||||
export const getThreeMajorApi = (data = {}) => {
|
||||
return request({
|
||||
url: `/material-mall/device/getThreeMajor`,
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 装备数量分析-十大工序
|
||||
export const getTenMajorApi = (data = {}) => {
|
||||
return request({
|
||||
url: `/material-mall/device/getTenMajor`,
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 190 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 288 KiB |
|
|
@ -0,0 +1,460 @@
|
|||
<template>
|
||||
<div class="warp">
|
||||
<div class="item df">
|
||||
<div>
|
||||
<div class="title">
|
||||
<div class="title-text">装备台账分析</div>
|
||||
<div class="tab" :class="{ active: activeTab1 == 1 }" @click="handleActiveTab(1)">总价值</div>
|
||||
<div class="tab" :class="{ active: activeTab1 == 2 }" @click="handleActiveTab(2)">配置率</div>
|
||||
</div>
|
||||
<div v-if="activeTab1 == 1" class="price">
|
||||
<div class="tab-title">装备资产总价值</div>
|
||||
<div style="margin-bottom: 35px">
|
||||
<span class="price-text">{{ priceData.total || 0 }}</span>
|
||||
<span class="unit-text">万元</span>
|
||||
</div>
|
||||
<div class="df" style="justify-content: space-between">
|
||||
<div>
|
||||
<div class="tab-title">线路装备</div>
|
||||
<div class="price-small-text p-df">
|
||||
<span>{{ priceData.line || 0 }}</span>
|
||||
<span class="unit-text">万元</span>
|
||||
</div>
|
||||
</div>
|
||||
<el-divider direction="vertical" class="tab-divider" />
|
||||
<div>
|
||||
<div class="tab-title">变电装备</div>
|
||||
<div class="price-small-text p-df">
|
||||
{{ priceData.substation || 0 }}
|
||||
<span class="unit-text">万元</span>
|
||||
</div>
|
||||
</div>
|
||||
<el-divider direction="vertical" class="tab-divider" />
|
||||
<div>
|
||||
<div class="tab-title">电缆装备</div>
|
||||
<div class="price-small-text p-df">
|
||||
{{ priceData.cable || 0 }}
|
||||
<span class="unit-text">万元</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="config">
|
||||
<div class="tab-title">装备配置率</div>
|
||||
<div style="margin-bottom: 35px">
|
||||
<span class="price-text config-color">{{ configData.total || 0 }}</span>
|
||||
<span class="unit-text">分</span>
|
||||
</div>
|
||||
<div class="df" style="justify-content: space-between">
|
||||
<div>
|
||||
<div class="tab-title">线路装备</div>
|
||||
<div class="price-small-text config-color">
|
||||
{{ configData.line || 0 }}
|
||||
<span class="unit-text">分</span>
|
||||
</div>
|
||||
</div>
|
||||
<el-divider direction="vertical" class="tab-divider" />
|
||||
<div>
|
||||
<div class="tab-title">变电装备</div>
|
||||
<div class="price-small-text config-color">
|
||||
{{ configData.substation || 0 }}
|
||||
<span class="unit-text">分</span>
|
||||
</div>
|
||||
</div>
|
||||
<el-divider direction="vertical" class="tab-divider" />
|
||||
<div>
|
||||
<div class="tab-title">电缆装备</div>
|
||||
<div class="price-small-text config-color">
|
||||
{{ configData.cable || 0 }}
|
||||
<span class="unit-text">分</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-divider direction="vertical" class="v-divider" />
|
||||
<div class="item-right">
|
||||
<div class="title">
|
||||
<div class="title-text">装备状态分析</div>
|
||||
</div>
|
||||
<div class="chart-wrapper">
|
||||
<div ref="chart" class="chart"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-divider direction="vertical" class="v-divider" />
|
||||
<div class="item">
|
||||
<div class="title">
|
||||
<div class="title-text">装备数量分析</div>
|
||||
<div class="tab" :class="{ active: activeTab2 == 'major' }" @click="handleActiveTab('major')">三大专业</div>
|
||||
<div class="tab" :class="{ active: activeTab2 == 'process' }" @click="handleActiveTab('process')">十大工序</div>
|
||||
</div>
|
||||
<div ref="barChart" class="barChart"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as echarts from 'echarts'
|
||||
import {
|
||||
getTotalValueApi,
|
||||
getConfigurationRateApi,
|
||||
getEquipmentStatusApi,
|
||||
getThreeMajorApi,
|
||||
getTenMajorApi,
|
||||
} from '@/api/EquipmentEntryApply'
|
||||
|
||||
export default {
|
||||
name: 'EquAnalysis',
|
||||
props: {
|
||||
queryParams: {
|
||||
type: Object,
|
||||
default: {},
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
priceData: {},
|
||||
configData: {},
|
||||
activeTab1: 1,
|
||||
activeTab2: 'major',
|
||||
total: 0,
|
||||
chartData: [
|
||||
{ name: '在库数量', value: 0 },
|
||||
{ name: '维修数量', value: 0 },
|
||||
{ name: '自用数量', value: 0 },
|
||||
{ name: '共享数量', value: 0 },
|
||||
{ name: '退役数量', value: 0 },
|
||||
],
|
||||
chart: null,
|
||||
dataMap: {
|
||||
major: [],
|
||||
process: [],
|
||||
},
|
||||
barChart: null,
|
||||
}
|
||||
},
|
||||
mounted() {},
|
||||
beforeDestroy() {
|
||||
window.removeEventListener('resize', this.resizeChart)
|
||||
this.chart && this.chart.dispose()
|
||||
window.removeEventListener('resize', this.resizeBarChart)
|
||||
this.barChart && this.barChart.dispose()
|
||||
},
|
||||
methods: {
|
||||
handleActiveTab(type) {
|
||||
if (this.activeTab1 == type || this.activeTab2 == type) return
|
||||
if (type == 1 || type == 2) {
|
||||
this.activeTab1 = type
|
||||
} else {
|
||||
this.activeTab2 = type
|
||||
this.renderBarChart()
|
||||
}
|
||||
},
|
||||
async init() {
|
||||
try {
|
||||
console.log('🚀 ~ this.queryParams:', this.queryParams)
|
||||
const res = await getTotalValueApi(this.queryParams)
|
||||
this.priceData = res.data
|
||||
const res2 = await getConfigurationRateApi(this.queryParams)
|
||||
this.configData = res2.data
|
||||
const res3 = await getEquipmentStatusApi(this.queryParams)
|
||||
this.total = res3.data.total
|
||||
const fieldMap = [
|
||||
{ name: '在库数量', key: 'availableNum' },
|
||||
{ name: '维修数量', key: 'repairNum' },
|
||||
{ name: '自用数量', key: 'inNum' },
|
||||
{ name: '共享数量', key: 'shareNum' },
|
||||
{ name: '退役数量', key: 'scrapNum' },
|
||||
]
|
||||
this.chartData = fieldMap.map((item) => ({
|
||||
name: item.name,
|
||||
value: res3.data[item.key] || 0,
|
||||
}))
|
||||
const res4 = await getThreeMajorApi(this.queryParams)
|
||||
|
||||
if (res4.data && res4.data.length > 0) {
|
||||
this.dataMap.major = res4.data.map((item) => ({
|
||||
name: item.type,
|
||||
value: item.total,
|
||||
}))
|
||||
}
|
||||
const res5 = await getTenMajorApi(this.queryParams)
|
||||
if (res5.data && res5.data.length > 0) {
|
||||
this.dataMap.process = res5.data.map((item) => ({
|
||||
name: item.type,
|
||||
value: item.total,
|
||||
}))
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('🚀 ~ error-->装备台账分析:', error)
|
||||
} finally {
|
||||
this.initChart()
|
||||
this.initBarChart()
|
||||
window.addEventListener('resize', this.resizeChart)
|
||||
window.addEventListener('resize', this.resizeBarChart)
|
||||
}
|
||||
},
|
||||
// 饼图
|
||||
resizeChart() {
|
||||
this.chart && this.chart.resize()
|
||||
},
|
||||
initChart() {
|
||||
this.chart = echarts.init(this.$refs.chart)
|
||||
|
||||
const option = {
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: (params) => {
|
||||
const percent = ((params.value / this.total) * 100).toFixed(2)
|
||||
return `${params.name}<br/>${percent}% / ${params.value}`
|
||||
},
|
||||
},
|
||||
legend: {
|
||||
orient: 'vertical',
|
||||
right: '5%',
|
||||
top: 'center',
|
||||
itemWidth: 10,
|
||||
itemHeight: 10,
|
||||
formatter: (name) => {
|
||||
const item = this.chartData.find((i) => i.name === name)
|
||||
const percent = item.value > 0 && this.total > 0 ? ((item.value / this.total) * 100).toFixed(2) : '0.00'
|
||||
return `${name} ${percent}% / ${item.value}`
|
||||
},
|
||||
},
|
||||
series: [
|
||||
{
|
||||
type: 'pie',
|
||||
radius: ['60%', '80%'],
|
||||
center: ['35%', '50%'],
|
||||
avoidLabelOverlap: false,
|
||||
label: { show: false },
|
||||
labelLine: { show: false },
|
||||
data: this.chartData,
|
||||
},
|
||||
],
|
||||
graphic: [
|
||||
{
|
||||
type: 'text',
|
||||
left: '27%',
|
||||
top: '40%',
|
||||
style: {
|
||||
text: `${this.total}台`,
|
||||
textAlign: 'center',
|
||||
fill: '#3F3F3F',
|
||||
fontSize: 22,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
left: '29%',
|
||||
top: '53%',
|
||||
style: {
|
||||
text: '装备台账',
|
||||
textAlign: 'center',
|
||||
fill: '#3F3F3F',
|
||||
fontSize: 14,
|
||||
},
|
||||
},
|
||||
],
|
||||
color: ['#33C3C8', '#FF6B6B', '#FFA940', '#FADB14', '#597EF7'],
|
||||
}
|
||||
|
||||
this.chart.setOption(option)
|
||||
},
|
||||
// 柱状图
|
||||
resizeBarChart() {
|
||||
this.barChart && this.barChart.resize()
|
||||
},
|
||||
initBarChart() {
|
||||
this.barChart = echarts.init(this.$refs.barChart)
|
||||
this.renderBarChart()
|
||||
},
|
||||
renderBarChart() {
|
||||
const list = this.dataMap[this.activeTab2]
|
||||
const xData = list.map((i) => i.name)
|
||||
const yData = list.map((i) => i.value)
|
||||
|
||||
const option = {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'shadow',
|
||||
},
|
||||
formatter: (params) => {
|
||||
const item = params[0]
|
||||
return `
|
||||
<div>
|
||||
<div>${item.name}</div>
|
||||
<div>数量:${item.value}</div>
|
||||
</div>
|
||||
`
|
||||
},
|
||||
},
|
||||
grid: {
|
||||
left: 40,
|
||||
right: 20,
|
||||
top: 30,
|
||||
bottom: 50,
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: xData,
|
||||
axisTick: { show: false },
|
||||
axisLine: { lineStyle: { color: '#E5E5E5' } },
|
||||
axisLabel: {
|
||||
color: '#666',
|
||||
interval: 0,
|
||||
},
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
axisLine: { show: false },
|
||||
axisTick: { show: false },
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
type: 'dashed',
|
||||
color: '#EAEAEA',
|
||||
},
|
||||
},
|
||||
},
|
||||
series: [
|
||||
{
|
||||
type: 'bar',
|
||||
data: yData,
|
||||
barWidth: 24,
|
||||
itemStyle: {
|
||||
borderRadius: [12, 12, 0, 0],
|
||||
color: (params) => {
|
||||
const colors = [
|
||||
['#5DA9FF', '#8EC5FF'],
|
||||
['#4ED6C8', '#7BE7D7'],
|
||||
['#FDBA4F', '#FFD78A'],
|
||||
]
|
||||
return new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{ offset: 0, color: colors[params.dataIndex % 3][0] },
|
||||
{ offset: 1, color: colors[params.dataIndex % 3][1] },
|
||||
])
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
this.barChart.setOption(option, true)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.warp {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.item {
|
||||
width: 50%;
|
||||
}
|
||||
.item-right {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.v-divider {
|
||||
height: 16rem;
|
||||
}
|
||||
.df {
|
||||
display: flex;
|
||||
}
|
||||
.title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 16px;
|
||||
color: #3f3f3f;
|
||||
line-height: 24px;
|
||||
margin-bottom: 20px;
|
||||
.title-text {
|
||||
font-weight: bold;
|
||||
}
|
||||
.tab {
|
||||
margin-left: 20px;
|
||||
font-weight: 400;
|
||||
cursor: pointer;
|
||||
}
|
||||
.active {
|
||||
color: #2cbab2;
|
||||
border-bottom: 2px solid #2cbab2;
|
||||
}
|
||||
}
|
||||
.price,
|
||||
.config {
|
||||
width: 260px;
|
||||
height: 206px;
|
||||
padding: 10px;
|
||||
}
|
||||
.price {
|
||||
background: url('~@/assets/images/equ-price.png');
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
.config {
|
||||
background: url('~@/assets/images/equ-config.png');
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
.tab-title {
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
color: #3f3f3f;
|
||||
line-height: 22px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.price-text {
|
||||
font-family: 'OpenSans-BoldItalic';
|
||||
font-weight: normal;
|
||||
font-size: 30px;
|
||||
color: #ffab29;
|
||||
line-height: 24px;
|
||||
}
|
||||
.price-small-text {
|
||||
font-family: 'OpenSans-BoldItalic';
|
||||
font-weight: normal;
|
||||
font-size: 18px;
|
||||
color: #ffab29;
|
||||
line-height: 24px;
|
||||
}
|
||||
.p-df {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.config-color {
|
||||
color: #2cbab2;
|
||||
}
|
||||
.unit-text {
|
||||
font-weight: 400;
|
||||
font-size: 12px;
|
||||
color: #808080;
|
||||
line-height: 18px;
|
||||
}
|
||||
.tab-divider {
|
||||
margin-top: 5px;
|
||||
height: 70px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
// 饼图
|
||||
.chart-wrapper {
|
||||
width: 80%;
|
||||
height: 220px;
|
||||
}
|
||||
|
||||
.chart {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
// 柱状图
|
||||
.barChart {
|
||||
width: 90%;
|
||||
height: 220px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -71,9 +71,8 @@
|
|||
</el-col>
|
||||
<!-- 右侧列表和查询区域 -->
|
||||
<el-col :span="collapsed ? 23 : 20" style="height: calc(100vh - 130px); transition: all 0.3s ease">
|
||||
<div class="card-container">
|
||||
<!-- <div class="card-container">
|
||||
<div class="card-header">
|
||||
<!-- 搜索区域展开/收起按钮 -->
|
||||
<div class="status-stats">
|
||||
<div class="stat-card">
|
||||
<div class="stat-content">
|
||||
|
|
@ -133,7 +132,7 @@
|
|||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<div class="status-operation-bar" style="margin-top: 15px;margin-bottom: 2px;">
|
||||
<el-form
|
||||
|
|
@ -360,6 +359,11 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="status-operation-bar" style="margin: 15px 0">
|
||||
<!-- 分析 -->
|
||||
<EquAnalysis ref="equAnalysis" :queryParams="queryParams" />
|
||||
</div>
|
||||
|
||||
<!-- 装备列表表格 -->
|
||||
<div class="card-container content-box">
|
||||
<el-row :gutter="10" class="mb8" style="display: flex; align-items: center;border-bottom: 1px solid #e4e7ed;">
|
||||
|
|
@ -903,11 +907,12 @@ import { firstLevel, secondAndThirdLevel } from '@/api/EquipmentEntryApply'
|
|||
import { getMaxFeatureAPI, getProvinceListAPI } from '@/api/EquipmentLedger/equ-out.js'
|
||||
import { deptTreeSelect } from '@/api/system/user'
|
||||
import AddEquip from '@/views/stockManagement/entryApply/components/AddEquip'
|
||||
import EquAnalysis from '@/views/EquipmentLedger/components/EquAnalysis'
|
||||
|
||||
export default {
|
||||
name: 'EquipmentLedger',
|
||||
dicts: ['user_year_type'],
|
||||
components: { AddEquip, QrcodeGenerator },
|
||||
components: { AddEquip, QrcodeGenerator, EquAnalysis },
|
||||
data() {
|
||||
return {
|
||||
treeSearchKey: '', //用于存储左侧树搜索框内容
|
||||
|
|
@ -1207,6 +1212,9 @@ export default {
|
|||
toggleCollapse() {
|
||||
this.collapsed = !this.collapsed
|
||||
// 可以在这里添加折叠/展开的动画效果或其他逻辑
|
||||
this.$nextTick(() => {
|
||||
this.$refs.equAnalysis.init()
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 切换搜索区域展开/收起状态
|
||||
|
|
@ -1547,6 +1555,8 @@ export default {
|
|||
this.tableData = listResult.data?.rows || []
|
||||
this.total = listResult.data?.total || 0
|
||||
|
||||
this.$refs.equAnalysis.init()
|
||||
|
||||
let maxLength = 0
|
||||
this.tableData.forEach((item) => {
|
||||
if (item.propertyVoList && item.propertyVoList.length > maxLength) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue