zmc
2023-11-23 0825e9e96a6f2d4b71a51d32dae1302f2496c4d1
src/views/risk_assessment/DataRiskModel.vue
@@ -1,732 +1,27 @@
<!-- 日均值 -->
<script>
import InputSearch from '@/sfc/InputSearch.vue'
import AreaAndmonitorType from '@/sfc/AreaAndmonitorType.vue'
import DustRadarChart from './components/DustRadarChart.vue'
import exceptionApi from '@/api/exceptionApi.js'
import LineChart from './components/LineChart.vue'
import index from '@/utils/risk_estimate_common_function/index.js'
import ButtonClick from '@/sfc/ButtonClick.vue'
import dayjs from 'dayjs'
import MonthSelect from '@/sfc/MonthSelect.vue'
import riskApi from '@/api/risk/riskApi.js'
import riskValue from '@/utils/risk_estimate_common_function/riskValue.js'
import lineChart from '@/utils/chartFunction/lineChart.js'
import siteInfo from '@/api/site/siteInfo.js'
export default {
  components: {
    LineChart,
    InputSearch,
    AreaAndmonitorType,
    DustRadarChart,
    ButtonClick,
    MonthSelect
  },
  data() {
    return {
      isNoData: false,
      loading: false,
      screenLoading: false,
      parentDataFlag: false,
      chartData: [],
      chartData1: {}, //保存查询的结果
      chartData2: {},
      chartData3: {},
      chartData4: {},
      begin: '', //开始时间
      end: '', //结束时间
      form: {
        // 站点名称
        name: '',
        // 设备编号
        number: '3234',
        // 开始时间
        beginTime: '',
        // 结束时间
        endTime: ''
      },
      month: '',
      // 折线图配置项
      option: {},
      // 数据清单
      bill: {
        min: '',
        max: '',
        avg: '',
        online: 100,
        valid: 100,
        exceeding: 0,
        //  典型异常复现率
        exceptionRecurrence: 0,
        // 异常类型据聚集度
        exceptionTypeAggregation: 0
      },
      // 查询按钮加载效果
      queryButton: false,
      // 风险值排名前十的站点
      top_10_sites_with_risk_values: [{ name: '', riskValue: 0.2 }],
      // 风险值
      weight: '',
      // 无数据配置时间段
      areaColor: [],
      // 某站点的基本信息
      siteInfo:{}
    }
  },
  mounted() {
    // // 加载风险值最高的站点数据
    this.ShowDefaultData()
  },
  computed: {
    // 风险等级
    riskGradeAndAdvice() {
      return riskApi.getRiskAdvice(this.weight)
    }
  },
  methods: {
    // 查询站点统计信息
    async querySiteStaticsInfo(row) {
      this.form.name = row.siteName
      // 更新统计数据
      await this.getAnalysisData()
      // 计算风险值
      this.calRiskValue()
  import CompDataRiskModel from '@/views/risk_assessment/components/CompDataRiskModel.vue'
  export default {
    components:{
      CompDataRiskModel
    },
    data() {
      return{
    // 格式化月份
    giveMonth(val) {
      //将中国标准时间转为指定格式(该组件返回的标准时间的格式,所以必须的加这个函数)
      this.month = dayjs(val).format('YYYY-MM-DD')
      // 同时更新开始和结束时间
      this.form.beginTime = dayjs(this.month).startOf().format('YYYY-MM-DD HH:mm:ss')
      this.form.endTime = dayjs(this.month).endOf('month').format('YYYY-MM-DD HH:mm:ss')
    },
    /**
     * 风险评估按钮
     * @param:
     * @returns:
     */
    riskAssessment() {
      // 更新排名清单
      this.getRiskRank()
      // 更新该站点的所属场景和运维商
      this.getSiteInfo(this.form.number)
      // 更新分析数据
      this.getAnalysisData()
      // 计算风险值
      this.calRiskValue()
    },
    // 更新分析数据
    getAnalysisData() {
      // 日统计数据
      this.fetchDayAnalysisData()
      // 异常数据
      this.fetchExceptionAnalysisData()
    },
    findObjectByPropertyValue(array, property, value) {
      return array.find((obj) => obj[property] === value)
    },
    // 此页面打开时
    ShowDefaultData() {
      // 默认加载展示的内容
      this.updateOriginPage()
    },
    // 加载默认展示的内容
    async updateOriginPage() {
      this.screenLoading = true
      // 更新排名清单,并得到风险值最高站点
      let arr = await this.getRiskRank()
      this.form.name = arr[0]
      this.form.number = arr[1]
      this.screenLoading = false
      // 更新该站点的所属场景和运维商
      this.getSiteInfo(this.form.number)
      // 更新日统计数据
      this.getAnalysisData()
      // 计算风险值
      this.calRiskValue()
    },
    // 计算风险值
    calRiskValue() {
      console.log('设备编码:',this.form.number)
      riskApi.queryRiskValue(this.form.number, this.month, 'month').then((response) => {
        this.weight = riskValue.calRiskValue(response.data.data[0]).toFixed(2)
      })
    },
    //  根据目前站点,月份,查折线图日统计数据
    fetchDayAnalysisData() {
      let params = {}
      if (this.form.name) {
        params['siteName'] = this.form.name
      }
      if (this.form.beginTime) {
        params['beginTime'] = this.form.beginTime
      }
      if (this.form.endTime) {
        params['endTime'] = this.form.endTime
      }
      this.loading = true
      this.queryButton = true
      exceptionApi
        .analysisdata(this.form.name, this.form.beginTime, this.form.endTime, 'day')
        .then((response) => {
          this.chartData = response.data.data
          this.loading = false
          this.queryButton = false
          if (response.data.data.length == 0) {
            this.isNoData = true
            return
          }
          // 分析数据中的最早时间
          let begin = this.chartData[0].lst
          // 分析数据中的最晚时间
          let end = this.chartData[this.chartData.length - 1].lst
          // 移除空数据状态
          this.isNoData = false
          // 无数据的时间段
          let noDataTimeInteval = lineChart.backNoDataInteval(begin, end)
          // 无数据配置时间段
          this.areaColor = lineChart.getMarkArea(noDataTimeInteval)
          this.setChart()
          //  折线图数据
          let temp = index.calBillData(this.chartData, begin, end)
          this.bill.min = temp['min']
          this.bill.max = temp['max']
          this.bill.avg = temp['avg']
          this.bill.online = temp['online']
          this.bill.valid = temp['valid']
          this.bill.exceeding = temp['exceeding']
        })
    },
    // 企业异常统计数据
    fetchExceptionAnalysisData() {
      exceptionApi
        .exceptiondata1({
          siteName: this.form.name,
          beginTime: this.form.beginTime,
          endTime: this.form.endTime
        })
        .then((res) => {
          let obj = index.calRecur(res.data.data)
          this.bill.exceptionRecurrence = obj['exceptionRecurrence']
          this.bill.exceptionTypeAggregation = obj['exceptionTypeAggregation']
        })
    },
    // 选择其他值类型时
    setChart() {
      if (this.chartData.length) {
        // 构建折线图x,y数据
        let obj = lineChart.getLineChartXYData(
          this.chartData,
          this.form.beginTime,
          this.form.endTime
        )
        this.chartData1 = {
          x: obj.xData,
          y: obj.yAvg
        }
        this.chartData2 = {
          x: obj.xData,
          y: obj.yOnline
        }
        this.chartData3 = {
          x: obj.xData,
          y: obj.yValid
        }
        this.chartData4 = {
          x: obj.xData,
          y: obj.yExceed
        }
      }
    },
    mounted() {
    // 得到前10风险排名清单
    async getRiskRank() {
      let response = await riskApi.queryRiskValue('', this.month, 'month')
      let tableData = riskValue.backComprehensiveRiskTableData(response.data.data)
      this.top_10_sites_with_risk_values = this.getTopRiskData(tableData, 10)
      if (this.top_10_sites_with_risk_values.length != 0) {
        // 表格按风险值倒叙排列
        this.$nextTick(() => {
          this.$refs.table.sort('riskValue', 'descending')
        })
        // 保存风险值最高的站点名称和设备编号
        let temp = []
        temp.push(
          this.top_10_sites_with_risk_values[0].siteName,
          this.top_10_sites_with_risk_values[0].mnCode
        )
        return temp
      }
    },
    /**
     * 降序排列,返回降序前num的元素
     * @param: 对象数组,返回的数量
     */
    getTopRiskData(arr, num) {
      // 按照riskValue降序排列
      arr.sort((a, b) => b.riskValue - a.riskValue)
      // 获取前num个元素
      return arr.slice(0, num)
    },
    /**
     * 根据设备编号查询站点基本信息
     * @param: 设备编号
     */
    getSiteInfo(mnCode) {
      siteInfo.querySiteInfoByMnCode(mnCode).then(response => {
        this.siteInfo = response.data.data[0]
      })
    },
    methods: {
    openDetail() {
      const encodedSiteName = encodeURIComponent(this.form.name)
      this.$router.push(`/exceptionDetail/${encodedSiteName}/${this.month}`)
    }
  }
     }
}
</script>
<template>
  <el-form :inline="true" :model="form">
    <el-form-item class="form-item">
      <AreaAndmonitorType></AreaAndmonitorType>
    </el-form-item>
    <el-form-item class="form-item">
      <InputSearch
        :site-name="form.name"
        isNeedDefaultSite="0"
        @submit-value="(n) => (form.name = n)"
        @submit-mncode="(n) => (form.number = n)"
      ></InputSearch>
    </el-form-item>
    <el-form-item>
      <MonthSelect  @submit-value="giveMonth"></MonthSelect>
    </el-form-item>
    <el-form-item>
      <ButtonClick
        content="风险评估"
        type="primary"
        :loading="queryButton"
        @do-search="riskAssessment"
      ></ButtonClick>
    </el-form-item>
  </el-form>
  <!-- <el-card class="site-info time-text" >
   <span>{{form.name}}</span>
   <br/>
   <br/>
    <span>数据统计时段:{{ form.beginTime }} ~ {{ form.endTime }}</span>
    <el-tag class="mx-1" >场景</el-tag>{{siteInfo.typename}}
    <el-tag class="mx-1">运维商</el-tag>{{siteInfo.dutyCompany}}
    <el-button type="primary"  size="small" class="exception-button" @click="openDetail()">
      异常详情
    </el-button>
  </el-card> -->
  <div v-loading="screenLoading" class="wait-name">
    <div class="chart-container" v-show="!isNoData && !screenLoading">
      <!-- <div class="time-text">
        <span>数据统计时段:{{ form.beginTime }} ~ {{ form.endTime }}</span>
        <span class="site-name">
              <el-button type="primary" text class="exception-button" @click="openDetail()">
               异常详情
              </el-button>
        </span>
        <el-tag class="mx-1" >场景</el-tag>{{siteInfo.typename}}
        <el-tag class="mx-2">运维商</el-tag>{{siteInfo.dutyCompany}}
      </div> -->
      <el-card class="time-text" >
        <span>{{form.name}}</span>
        <br/>
        <br/>
         <span>数据统计时段:{{ form.beginTime }} ~ {{ form.endTime }}</span>
         <el-tag class="mx-1" >场景</el-tag>{{siteInfo.typename}}
         <el-tag class="mx-1">运维商</el-tag>{{siteInfo.dutyCompany}}
         <el-button type="primary"  size="small" class="exception-button" @click="openDetail">
           异常详情
         </el-button>
       </el-card>
      <el-row :gutter="10">
        <el-col :span="5">
          <el-card shadow="never" class="table-class">
            <el-table
              ref="table"
              :highlight-current-row="true"
              :data="top_10_sites_with_risk_values"
              :default-sort="{ prop: 'riskValue', order: 'descending' }"
              height="540"
            >
              <el-table-column
                type="index"
                label="序号"
                fixed
                width="52"
                show-overflow-tooltip
                align="center"
              />
              <el-table-column
                prop="siteName"
                label="点位名称"
                show-overflow-tooltip
                width="97"
                align="center"
              >
                <template #default="{ row }">
                  <el-button
                    type="primary"
                    text
                    class="table-button"
                    @click="querySiteStaticsInfo(row)"
                    >
                  <span class="risk-rank-site">
                    {{ row.siteName }}
                  </span>
                    </el-button
                  >
                </template>
              </el-table-column>
              <el-table-column
                prop="riskValue"
                label="风险值"
                sortable
                show-overflow-tooltip
                align="center"
              />
            </el-table>
          </el-card>
        </el-col>
        <el-col :span="11">
          <el-card shadow="never" class="table-class">
            <DustRadarChart
              :name="[
                '数据有效风险',
                '典型异常复现风险',
                '异常类型聚集风险',
                '超标异常风险',
                '数据在线风险'
              ]"
              :yData="[
                bill.valid,
                bill.exceptionRecurrence,
                bill.exceptionTypeAggregation,
                bill.exceeding,
                bill.online
              ]"
            ></DustRadarChart>
          </el-card>
        </el-col>
        <el-col :span="4">
          <el-card shadow="never" class="card-height risk-card">
            <template #header>
              <h1
                :class="{
                  'weightColor-low': weight < 0.2,
                  'weightColor-medium': weight >= 0.2 && weight < 0.6,
                  'weightColor-heigh': weight >= 0.6
                }"
              >
                风险值(0~1):{{ weight }}
              </h1>
            </template>
            <div class="risk-text-container">
            <div class="risk-grade">
              <h1 class="sub-title">风险等级:</h1>
              <span class="sub-title">{{ riskGradeAndAdvice.riskGrade }} </span>
            </div>
            <div class="risk-advice">
              <h1 class="sub-title">管控建议:</h1>
              <div v-for="item in riskGradeAndAdvice.riskAdvice" :key="item" class="risk-advice-text">
                {{ item }}
              </div>
            </div>
            <div class="grade-instance">
              <div class="container">
                <div class="block-color heigh"></div>
                <div>高风险(≥0.6)</div>
              </div>
              <div class="container">
                <div class="block-color medium"></div>
                <div>中风险(0.2~0.6)</div>
              </div>
              <div class="container">
                <div class="block-color low"></div>
                <div>低风险(<0.2)</div>
              </div>
            </div>
            </div>
          </el-card>
        </el-col>
        <el-col :span="4">
          <el-card shadow="never" class="card-height">
            <template #header>
              <span class="title-16">风险详情</span>
            </template>
            <el-form>
              <el-form-item label="最大值:"> {{ bill.max }} mg/m³ </el-form-item>
              <el-form-item label="最小值:"> {{ bill.min }} mg/m³ </el-form-item>
              <el-form-item label="数据有效率:"> {{ bill.online }}% </el-form-item>
              <el-form-item label="数据在线率:"> {{ bill.valid }}% </el-form-item>
              <el-form-item label="数据超标率:"> {{ bill.exceeding }}% </el-form-item>
              <el-form-item label="异常类型聚集度:">
                {{ bill.exceptionTypeAggregation * 100 }}%
              </el-form-item>
              <el-form-item label="典型异常复现率:">
                {{ bill.exceptionRecurrence * 100 }}%
              </el-form-item>
            </el-form>
          </el-card>
        </el-col>
      </el-row>
      <el-row :gutter="20">
        <el-col :span="12">
          <el-card shadow="never" class="card-value">
            <LineChart
              title="日均值"
              :chartData="chartData1"
              yName="mg/m³"
              seriesName="日均值"
              :areaColor="areaColor"
            >
            </LineChart>
          </el-card>
        </el-col>
        <el-col :span="12">
          <el-card shadow="never" class="card-value">
            <LineChart
              title="日在线率"
              :chartData="chartData2"
              yName="%"
              seriesName="日在线率"
              :areaColor="areaColor"
            >
            </LineChart>
          </el-card>
        </el-col>
      </el-row>
      <el-row :gutter="20">
        <el-col :span="12">
          <el-card shadow="never" class="card-value">
            <LineChart
              title="日有效率"
              :chartData="chartData3"
              yName="%"
              seriesName="日有效率"
              :areaColor="areaColor"
            >
            </LineChart>
          </el-card>
        </el-col>
        <el-col :span="12">
          <el-card shadow="never" class="card-value">
            <LineChart
              title="日超标率"
              :chartData="chartData4"
              yName="%"
              seriesName="日超标率"
              :areaColor="areaColor"
            >
            </LineChart>
          </el-card>
        </el-col>
      </el-row>
    </div>
  </div>
  <el-empty description="暂无数据" v-show="isNoData" :image-size="200" />
  <CompDataRiskModel  :show-all="true"/>
</template>
<style scoped>
.el-form {
  margin: 10px;
}
.form-item {
  margin-top: 10px;
}
.chart-container {
  margin-left: 10px;
}
.time-text {
  font-size: 14px;
  color: #333333;
  letter-spacing: 1px;
}
.el-card {
  margin-top: 15px;
  border-radius: 9px;
}
.chart-container {
  width: 98%;
  /* height: 600px; */
}
<style  scoped>
.card-height {
  height: 570px;
}
.el-header {
  background-color: #010408;
  color: #333;
  line-height: 60px;
}
.risk-advice {
  /* margin: 20px 0px; */
}
.container {
  display: flex;
  margin-bottom: 10px;
}
.grade-instance {
  /* margin-top: 50px; */
}
.block-color {
  width: 1em;
  height: 1em;
  margin-right: 10px;
  margin-top: 3px;
}
.heigh {
  background-color: red;
}
.medium {
  background-color: #fadc19;
}
.low {
  background-color: #9fdb1d;
}
.el-text {
  align-self: left;
}
.el-form-item {
  margin-bottom: 20px;
}
:deep().el-form-item__content {
  justify-content: flex-end;
}
.title-16 {
  font-size: 16px;
  font-weight: bold;
}
.weightColor-low {
  color: #9fdb1d;
  font-size: 16px;
}
.weightColor-medium {
  color: #dabe09;
  font-size: 16px;
}
.weightColor-heigh {
  color: red;
  font-size: 16px;
}
.risk-grade {
  display: flex;
}
:deep().el-table__header-wrapper {
  color: red;
}
/* .wait-name {
    width: 500px;
    height: 600px;
  } */
.table-class {
  /* border: 1px solid blue; */
  /* margin: 20px 0px 20px 0px; */
  height: 570px;
}
.table-button {
  letter-spacing: 1px;
  text-decoration: underline;
  /* border-radius: 0px; */
}
.risk-rank-site {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  width: 80px;
}
.site-name {
  margin-left: 20px;
}
.risk-advice-text {
  font-size: 14px;
  color: #333333;
  letter-spacing: 1.5px;
  margin-top: 10px;
}
.sub-title {
  font-size: 14px;
  color: #333333;
}
.risk-text-container{
  height: 490px;
  display: flex;
  flex-direction: column;
  justify-content: space-around;
}
.el-tag{
  margin-left: 25px;
  font-size: 14px;
  vertical-align: baseline;
}
.exception-button {
  vertical-align: baseline;
  margin-left: 150px;
}
.site-info-detail{
  display: flex;
  justify-content: space-between;
}
.mx-1{
  margin-left: 100px;
}
</style>
</style>