You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
726 lines
19 KiB
726 lines
19 KiB
<template>
|
|
<!-- <div class="welcome-page">欢迎来到智慧水利水工程应用v24.3.0~</div>-->
|
|
|
|
<div class="statistics-page">
|
|
<div class="parent-page">
|
|
<div class="child-page">
|
|
<svg-icon icon-class="u10" style="padding-top: 15px"/>
|
|
<div class="font-page">
|
|
<p>全部</p>
|
|
<p>{{ total }}个</p>
|
|
</div>
|
|
|
|
<div class="right-font">
|
|
<p style="padding-bottom: 5px">施工中 {{acc["noAcc"]}}</p>
|
|
<p>已完工 {{acc["acc"]}}</p>
|
|
</div>
|
|
</div>
|
|
<div class="child-page">
|
|
<svg-icon icon-class="u18" style="padding-top: 15px"/>
|
|
<div class="font-page" >
|
|
<p>重大项目</p>
|
|
<p>{{ zdTotal }}个</p>
|
|
</div>
|
|
|
|
<div class="right-font">
|
|
<p v-for="([key,value]) in zdTwoKeys" >{{zdProjectTypeFormat(key)}} {{value}}个</p>
|
|
</div>
|
|
</div>
|
|
<div class="child-page">
|
|
<svg-icon icon-class="u23" style="padding-top: 15px"/>
|
|
<div class="font-page" >
|
|
<p>面上项目</p>
|
|
<p>{{ msTotal }}个</p>
|
|
</div>
|
|
|
|
<div class="right-font">
|
|
<p v-for="([key,value]) in msTwoKeys" >{{msProjectTypeFormat(key)}} {{value}}个</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="parent-2">
|
|
<div class="box_2">
|
|
<div class="top-title">项目类型</div>
|
|
<div ref="Ele" style="width: 100%; height: 60%;min-width: 350px"></div>
|
|
</div>
|
|
<div class="box_2">
|
|
<div class="top-title">投资完成</div>
|
|
<div ref="bar" style="width: 100%; height: 70%;margin-top: 20px"></div>
|
|
</div>
|
|
<div class="box_2">
|
|
<div class="top-title">施工中项目亮灯情况</div>
|
|
<div style="padding: 50px;padding-left: 70px">
|
|
<el-row style="margin-bottom: 60px">
|
|
<el-col :span="12">
|
|
<svg-icon icon-class="redLight"/>
|
|
<div class="font-light">
|
|
<p style="color: red">{{ this.forewarningNum.warn }}</p>
|
|
<p>预警</p>
|
|
</div>
|
|
</el-col>
|
|
<el-col :span="12" style="padding-left: 15px">
|
|
<svg-icon icon-class="yellowLight"/>
|
|
<div class="font-light">
|
|
<p style="color: yellow">{{ this.forewarningNum.forewarning }}</p>
|
|
<p>提醒</p>
|
|
</div>
|
|
</el-col>
|
|
</el-row>
|
|
<el-row>
|
|
<svg-icon icon-class="greenLight"/>
|
|
<div class="font-light">
|
|
<p style="color: green">{{ this.forewarningNum.normal }}</p>
|
|
<p>正常</p>
|
|
</div>
|
|
</el-row>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="parent-3" >
|
|
<el-form
|
|
:model="queryParams"
|
|
ref="queryForm"
|
|
:inline="true"
|
|
v-show="showSearch"
|
|
>
|
|
<el-form-item label="项目名称" prop="projectName">
|
|
<el-input
|
|
v-model="queryParams.data.projectName"
|
|
placeholder="请输入项目名称"
|
|
clearable
|
|
size="small"
|
|
@keyup.enter.native="handleQuery"
|
|
>
|
|
<el-button
|
|
type="primary"
|
|
slot="append"
|
|
icon="el-icon-search"
|
|
size="small"
|
|
@click="handleQuery"
|
|
></el-button>
|
|
</el-input>
|
|
</el-form-item>
|
|
|
|
<el-form-item>
|
|
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery"
|
|
>重置</el-button
|
|
>
|
|
</el-form-item>
|
|
</el-form>
|
|
<el-table v-loading="loading" :data="InfoList" style="background-image: linear-gradient(rgb(199, 243, 227), rgba(199, 243, 227, 0.3))"
|
|
>
|
|
<!-- <el-table-column type="selection" width="55" align="center" fixed /> -->
|
|
|
|
<el-table-column
|
|
label="序号"
|
|
type="index"
|
|
width="50"
|
|
align="center"
|
|
fixed
|
|
/>
|
|
<el-table-column
|
|
label="行政区划"
|
|
prop="adcd"
|
|
width="120"
|
|
align="center"
|
|
:formatter="$formatAdcd"
|
|
/>
|
|
<el-table-column
|
|
label="项目名称"
|
|
prop="projectName"
|
|
min-width="120"
|
|
align="center"
|
|
|
|
/>
|
|
<el-table-column
|
|
label="项目批复时间"
|
|
prop="appTime"
|
|
min-width="120"
|
|
align="center"
|
|
:formatter="formatDate"
|
|
/>
|
|
|
|
<el-table-column
|
|
label="计划总投资(万元)"
|
|
prop="planInvestment"
|
|
min-width="120"
|
|
align="center"
|
|
/>
|
|
|
|
<el-table-column
|
|
label="累计完成总投资(万元)"
|
|
prop="actInvestment"
|
|
min-width="120"
|
|
align="center"
|
|
/>
|
|
<el-table-column
|
|
label="亮灯状态"
|
|
align="center"
|
|
class-name="small-padding fixed-width"
|
|
min-width="120"
|
|
>
|
|
<template slot-scope="scope">
|
|
<svg-icon v-if="scope.row.type === '0'" icon-class="redLight"/>
|
|
<svg-icon v-else-if="scope.row.type === '1'" icon-class="yellowLight"/>
|
|
<svg-icon v-else-if="scope.row.type === '3'" icon-class="greenLight"/>
|
|
</template>
|
|
</el-table-column>
|
|
|
|
<el-table-column
|
|
label="操作"
|
|
align="center"
|
|
class-name="small-padding fixed-width"
|
|
width="180"
|
|
fixed="right"
|
|
>
|
|
<template slot-scope="scope">
|
|
<el-button
|
|
size="mini"
|
|
type="text"
|
|
icon="el-icon-view"
|
|
@click="viewInfo(scope.row)"
|
|
>查看详情</el-button
|
|
>
|
|
</template>
|
|
</el-table-column>
|
|
</el-table>
|
|
<pagination
|
|
v-show="pageTotal > 0"
|
|
:total="pageTotal"
|
|
:page.sync="queryParams.pageNum"
|
|
:limit.sync="queryParams.pageSize"
|
|
@pagination="getXMInfo"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import Div from '../build/div/index.vue'
|
|
import { getTypeNum,getForewarningNum } from "@/api/projectStatistics/sort";
|
|
import log from '../monitor/job/log.vue'
|
|
import { integer } from 'mockjs/src/mock/random/basic'
|
|
import index from '@vue/test-utils'
|
|
import * as echarts from 'echarts'
|
|
import { getInfo, getSourceFundsNum } from '../../api/projectStatistics/sort'
|
|
import { codeToText } from 'element-china-area-data'
|
|
|
|
export default {
|
|
components: { Div },
|
|
data(){
|
|
return{
|
|
loading:false,
|
|
InfoList:[],
|
|
zd_projectTypeOptions:[],
|
|
ms_projectTypeOptions:[],
|
|
sourceFound:{},
|
|
acc:{},
|
|
pageTotal:0,
|
|
TypeNum:{},
|
|
showSearch: true,
|
|
forewarningNum:[],
|
|
ms:{},
|
|
zd:{},
|
|
adcd:[],
|
|
year:"2024",
|
|
routeList: [
|
|
{
|
|
path: "/evaluationEarlyWarning/earlyWarningManage/warning",
|
|
routeName: "项目预警管理",
|
|
},
|
|
],
|
|
formattedZd:{},
|
|
formattedMs:{},
|
|
projectType:[],
|
|
zdTotal:0,
|
|
msTotal:0,
|
|
total:0,
|
|
|
|
queryParams: {
|
|
pageNum: 1,
|
|
pageSize: 10,
|
|
ids: null,
|
|
data: {
|
|
projectName: null,
|
|
projectType: null,
|
|
total: null,
|
|
projectPhase: null,
|
|
},
|
|
},
|
|
}
|
|
},
|
|
mounted(){
|
|
},
|
|
created() {
|
|
this.getDicts("major_project").then((response) => {
|
|
this.zd_projectTypeOptions = response.data;
|
|
});
|
|
this.getDicts("general_project").then((response) => {
|
|
this.ms_projectTypeOptions = response.data;
|
|
});
|
|
this.getXMInfo()
|
|
getSourceFundsNum(this.year).then(res=>{
|
|
this.sourceFound=res.data
|
|
this.adcd=Object.keys(this.sourceFound)
|
|
console.log(this.adcd)
|
|
this.barInit();
|
|
})
|
|
getForewarningNum().then(res=>
|
|
{
|
|
this.forewarningNum=res.data
|
|
console.log(this.forewarningNum)
|
|
})
|
|
|
|
getTypeNum(this.queryParams).then(
|
|
res=>{
|
|
this.zd=res.data.zd
|
|
this.ms=res.data.ms
|
|
this.acc=res.data.acc
|
|
Object.entries(this.zd).forEach(([key, value]) => {
|
|
this.zdTotal=this.zdTotal+Number(value)
|
|
let name=this.zdProjectTypeFormat(key)
|
|
let obj={
|
|
name:name,
|
|
value:Number(value)
|
|
}
|
|
this.projectType.push(obj)
|
|
});
|
|
|
|
Object.entries(this.ms).forEach(([key, value]) => {
|
|
this.msTotal=this.msTotal+Number(value)
|
|
let name=this.msProjectTypeFormat(key)
|
|
let obj={
|
|
name:name,
|
|
value:Number(value)
|
|
}
|
|
this.projectType.push(obj)
|
|
});
|
|
|
|
this.total=Number(this.acc["acc"])+Number(this.acc["noAcc"])
|
|
console.log(this.projectType)
|
|
this.eleInit();
|
|
}
|
|
)
|
|
|
|
},
|
|
computed: {
|
|
zdTwoKeys() {
|
|
// 将对象转换为数组,按值排序,取前两个
|
|
const sortedEntries = Object.entries(this.zd).sort(([, a], [, b]) => b - a);
|
|
return sortedEntries.slice(0, 2);
|
|
},
|
|
|
|
msTwoKeys() {
|
|
// 将对象转换为数组,按值排序,取前两个
|
|
const sortedEntries = Object.entries(this.ms).sort(([, a], [, b]) => b - a);
|
|
return sortedEntries.slice(0, 2);
|
|
},
|
|
},
|
|
|
|
methods:{
|
|
move(row){
|
|
console.log(row)
|
|
},
|
|
resetQuery() {
|
|
this.resetQueryForm();
|
|
this.getXMInfo()
|
|
},
|
|
resetQueryForm(){
|
|
this.queryParams={
|
|
pageNum: 1,
|
|
pageSize: 5,
|
|
ids: null,
|
|
data: {
|
|
projectName: null,
|
|
projectType: null,
|
|
total: null,
|
|
projectPhase: null
|
|
}
|
|
}
|
|
},
|
|
handleQuery() {
|
|
this.queryParams.pageNum = 1;
|
|
this.getXMInfo();
|
|
},
|
|
|
|
truncateName(name) {
|
|
if (name.length > 4) {
|
|
return name.substring(0, 4) + '..';
|
|
}
|
|
return name;
|
|
},
|
|
getXMInfo() {
|
|
getInfo(this.queryParams).then(
|
|
res=>
|
|
{this.InfoList=res.data.records
|
|
this.pageTotal=res.data.total
|
|
console.log(this.pageTotal)
|
|
}
|
|
)
|
|
},
|
|
formatDate(row, column, cellValue, index) {
|
|
if (!cellValue) return '';
|
|
|
|
// 解析日期
|
|
const date = new Date(cellValue);
|
|
|
|
// 格式化为 YYYY-MM-DD 格式
|
|
const year = date.getFullYear();
|
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
const day = String(date.getDate()).padStart(2, '0');
|
|
|
|
return `${year}-${month}-${day}`;
|
|
},
|
|
formatAdcd(row) {
|
|
if (row) {
|
|
return (
|
|
codeToText[row]
|
|
);
|
|
}
|
|
},
|
|
|
|
msProjectTypeFormat(key) {
|
|
return this.selectDictLabel(this.ms_projectTypeOptions, key);
|
|
},
|
|
zdProjectTypeFormat(key) {
|
|
return this.selectDictLabel(this.zd_projectTypeOptions, key);
|
|
},
|
|
viewInfo(row){
|
|
// console.log(row)
|
|
this.routeList[0].routeName = row.projectName;
|
|
this.routeList.push({
|
|
path: "/evaluationEarlyWarning/earlyWarningManage/warning/options",
|
|
routeName: row.proCode,
|
|
isEdit: true,
|
|
});
|
|
|
|
// 存储面包屑信息
|
|
this.$store.commit("setRouteList", JSON.stringify(this.routeList));
|
|
|
|
// 跳转到选项卡页面
|
|
this.$router.push({
|
|
path:
|
|
"/evaluationEarlyWarning/earlyWarningManage/warning/options?baseDataId=" +
|
|
row.id,
|
|
})
|
|
},
|
|
eleInit() {
|
|
let chartDom = this.$refs.Ele;
|
|
let myChart = echarts.init(chartDom);
|
|
let option = {
|
|
tooltip: {
|
|
trigger: 'item'
|
|
},
|
|
grid: {
|
|
top: '20%', // 控制图表上方的间距
|
|
bottom: '40%',// 控制图表下方的间距
|
|
left: '0%', // 控制图表左侧的间距
|
|
right: '70%' // 控制图表右侧的间距
|
|
},
|
|
legend: {
|
|
orient: 'vertical', // 图例竖向排列
|
|
right: 0, // 图例放置在图形右侧,右边距 10
|
|
top: 'center', // 图例垂直居中
|
|
itemWidth: 20, // 图例项的宽度
|
|
itemHeight: 14, // 图例项的高度
|
|
padding: [0, 10, 0, 10], // 图例四周的内边距,防止与图形重叠
|
|
textStyle: {
|
|
fontSize: 10, // 设置字体大小为12px
|
|
color: '#333' // 设置字体颜色,默认为#333(深灰色)
|
|
}
|
|
},
|
|
color: ['#2E8B57', '#66CDAA', '#20B2AA', '#3CB371', '#228B22'], // 设置绿色系颜色
|
|
series: [
|
|
{
|
|
type: 'pie',
|
|
radius: ['40%', '60%'],
|
|
center: ["30%", "50%"],
|
|
avoidLabelOverlap: true,
|
|
padAngle: 5,
|
|
itemStyle: {
|
|
borderRadius: 10
|
|
},
|
|
label: {
|
|
show: false,
|
|
position: 'center',
|
|
textStyle: {
|
|
fontSize: 12, // 设置字体大小为12px
|
|
color: '#333' // 设置字体颜色
|
|
}
|
|
},
|
|
emphasis: {
|
|
label: {
|
|
show: true,
|
|
fontSize: 20,
|
|
fontWeight: 'bold'
|
|
}
|
|
},
|
|
labelLine: {
|
|
show: false
|
|
},
|
|
data:this.projectType.map(item => ({
|
|
...item,
|
|
name: this.truncateName(item.name)
|
|
}))
|
|
// data:[{name:'2233',value:2},{name:'21',value:2},{name:'32',value:2},
|
|
// {name:'32',value:2},{name:'12',value:2},{name:'61',value:2},{name:'34',value:2}
|
|
// ,{name:'42',value:2},{name:'32',value:2},{name:'33',value:2},{name:'43',value:2}
|
|
// ,{name:'52',value:2},{name:'72',value:2},{name:'31',value:2},{name:'55',value:2},{name:'56',value:2}
|
|
// ,{name:'62',value:2}]
|
|
}
|
|
]
|
|
};
|
|
option && myChart.setOption(option);
|
|
window.addEventListener("resize", function () {
|
|
myChart.resize();
|
|
});
|
|
},
|
|
|
|
|
|
barInit(){
|
|
const progressPlanValues = Object.values(this.sourceFound).map(obj => obj.progressPlan);
|
|
const actualValues = Object.values(this.sourceFound).map(obj => obj.actual);
|
|
|
|
const maxProgressPlan = Math.max(...progressPlanValues);
|
|
const maxActual = Math.max(...actualValues);
|
|
|
|
// 过滤掉 undefined 的项,并获取有效数据的索引
|
|
const validIndices = this.adcd
|
|
.map((item, index) => codeToText[item] ? index : null)
|
|
.filter(index => index !== null);
|
|
|
|
// 根据有效索引过滤 xAxis 数据
|
|
const filteredData = this.adcd
|
|
.filter((item, index) => validIndices.includes(index))
|
|
.map(item => codeToText[item]);
|
|
|
|
// 根据有效索引过滤 series 数据
|
|
const filteredSourceFound = Object.values(this.sourceFound)
|
|
.filter((_, index) => validIndices.includes(index));
|
|
|
|
const indexedSourceFound = filteredSourceFound.map((obj, index) => ({ ...obj, index }));
|
|
const indexedActuals = indexedSourceFound.map(obj => obj.actual);
|
|
|
|
// 根据 actuals 从大到小排序
|
|
const sortedByActuals = indexedSourceFound
|
|
.map(obj => ({ ...obj, actual: indexedActuals[obj.index] }))
|
|
.sort((a, b) => b.actual - a.actual);
|
|
|
|
// 提取排序后的索引
|
|
const sortedIndices = sortedByActuals.map(obj => obj.index);
|
|
|
|
// 根据排序后的索引重新排列 filteredData 和 filteredSourceFound
|
|
const sortedFilteredData = sortedIndices.map(index => filteredData[index]);
|
|
const sortedFilteredSourceFound = sortedIndices.map(index => filteredSourceFound[index]);
|
|
|
|
const progressPlans = sortedFilteredSourceFound.map(obj => obj.progressPlan);
|
|
const actuals = sortedFilteredSourceFound.map(obj => obj.actual);
|
|
|
|
// 取两个最大值中的最大值作为 yAxis 的 max
|
|
const yAxisMax = Math.max(maxProgressPlan, maxActual);
|
|
let chartDom = this.$refs.bar;
|
|
let myChart = echarts.init(chartDom);
|
|
let option = {
|
|
grid: {
|
|
left: '18%',
|
|
right: '0%',
|
|
top: '15%',
|
|
bottom: '20%'
|
|
},
|
|
tooltip: {
|
|
trigger: 'axis',
|
|
axisPointer: {
|
|
type: 'cross',
|
|
crossStyle: {
|
|
color: '#999'
|
|
}
|
|
}
|
|
},
|
|
legend: {
|
|
data: ['年度计划', '实际完成'],
|
|
},
|
|
xAxis: [
|
|
{
|
|
axisLine: {
|
|
show: false // 隐藏 X 轴线
|
|
},
|
|
axisLabel: { interval: 0,rotate: 45 },
|
|
type: 'category',
|
|
data:sortedFilteredData,
|
|
axisPointer: {
|
|
type: 'shadow'
|
|
},
|
|
axisTick: {
|
|
alignWithLabel: true // 使刻度线与标签对齐
|
|
},
|
|
interval: 0,
|
|
fontSize: 2, // 设置字体大小
|
|
|
|
}
|
|
],
|
|
yAxis: [
|
|
{
|
|
axisLine: {
|
|
show: false // 隐藏 X 轴线
|
|
},
|
|
type: 'value',
|
|
name: '金额/万元',
|
|
min: 0,
|
|
max: yAxisMax,
|
|
interval: yAxisMax/10,
|
|
}
|
|
],
|
|
series: [
|
|
{
|
|
name: '年度计划',
|
|
type: 'bar',
|
|
color: '#2ecc71', // 绿色
|
|
tooltip: {
|
|
valueFormatter: function (value) {
|
|
return value ;
|
|
}
|
|
},
|
|
data: progressPlans
|
|
},
|
|
{
|
|
name: '实际完成',
|
|
type: 'bar',
|
|
color: '#27ae60', // 深绿色
|
|
tooltip: {
|
|
valueFormatter: function (value) {
|
|
return value;
|
|
}
|
|
},
|
|
data: actuals
|
|
}
|
|
],
|
|
|
|
};
|
|
option && myChart.setOption(option);
|
|
window.addEventListener("resize", function () {
|
|
myChart.resize();
|
|
});
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
.welcome-page {
|
|
padding: 24px;
|
|
font-weight: 700;
|
|
font-size: 20px;
|
|
color: #333;
|
|
}
|
|
.statistics-page{
|
|
background-color: white;
|
|
margin: 5px;
|
|
}
|
|
|
|
.parent-2{
|
|
display: flex;
|
|
background-color: white;
|
|
|
|
width: 100%;
|
|
height: 300px;
|
|
.box_3{
|
|
height: 400px;
|
|
width: 350px;
|
|
.svg-icon{
|
|
font-size: 60px;
|
|
line-height: 100%;
|
|
float: left;
|
|
}
|
|
.font-light{
|
|
line-height: 100%;
|
|
margin-top: 10px;
|
|
margin-left: 70px;
|
|
font-size: 24px;
|
|
}
|
|
.top-title{
|
|
margin-left: 30px;
|
|
font-family: 'PingFangSC-Semibold', 'PingFang SC Semibold', 'PingFang SC', sans-serif;
|
|
font-weight: 650;
|
|
font-style: normal;
|
|
font-size: 24px;
|
|
}
|
|
}
|
|
.box_2{
|
|
height: 400px;
|
|
flex: 1;
|
|
.svg-icon{
|
|
font-size: 60px;
|
|
line-height: 100%;
|
|
float: left;
|
|
}
|
|
.font-light{
|
|
line-height: 100%;
|
|
margin-top: 10px;
|
|
margin-left: 70px;
|
|
font-size: 24px;
|
|
}
|
|
.top-title{
|
|
margin-left: 30px;
|
|
font-family: 'PingFangSC-Semibold', 'PingFang SC Semibold', 'PingFang SC', sans-serif;
|
|
font-weight: 650;
|
|
font-style: normal;
|
|
font-size: 24px;
|
|
}
|
|
}
|
|
}
|
|
|
|
.parent-3{
|
|
width: 97%;
|
|
margin: 30px;
|
|
}
|
|
|
|
.parent-page{
|
|
padding-top:10px;
|
|
margin: 20px;
|
|
display: flex;
|
|
width: 100%;
|
|
.child-page{
|
|
position: relative;
|
|
flex: 1;
|
|
display: flex;
|
|
width: 587px;
|
|
height: 105px;
|
|
margin-right: 25px;
|
|
background-image: linear-gradient(rgb(199, 243, 227), rgba(199, 243, 227, 0.3));
|
|
border-radius: 10px;
|
|
line-height: 105px;
|
|
.svg-icon{
|
|
flex: 1;
|
|
color: black;
|
|
font-size: 70px;
|
|
}
|
|
.font-page{
|
|
flex: 1;
|
|
padding-top: 20px;
|
|
height: 50px;
|
|
line-height: 25px;
|
|
font-family: 'PingFangSC-Regular', 'PingFang SC', sans-serif;
|
|
font-weight: 200;
|
|
font-style: normal;
|
|
font-size: 20px;
|
|
}
|
|
.right-font{
|
|
right: 0px;
|
|
flex: 2;
|
|
padding-top: 20px;
|
|
height: 50px;
|
|
line-height: 25px;
|
|
margin-left: 5px;
|
|
font-family: 'PingFangSC-Regular', 'PingFang SC', sans-serif;
|
|
font-weight: 200;
|
|
font-style: normal;
|
|
font-size: 18px;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
</style>
|
|
|
|
|