|  | @@ -1,5 +1,42 @@
 | 
	
		
			
				|  |  |  <template>
 | 
	
		
			
				|  |  |    <div class="page">
 | 
	
		
			
				|  |  | +    <!-- 新增信息展示栏 -->
 | 
	
		
			
				|  |  | +    <div class="info-row">
 | 
	
		
			
				|  |  | +      <div class="info-item">
 | 
	
		
			
				|  |  | +        <label>井号:</label>
 | 
	
		
			
				|  |  | +        <span class="highlight">{{ infoModel.jh }}</span>
 | 
	
		
			
				|  |  | +      </div>
 | 
	
		
			
				|  |  | +      <div class="info-item">
 | 
	
		
			
				|  |  | +        <label>最新时间:</label>
 | 
	
		
			
				|  |  | +        <span class="highlight">{{ infoModel.latestTime }}</span>
 | 
	
		
			
				|  |  | +      </div>
 | 
	
		
			
				|  |  | +      <div class="info-item">
 | 
	
		
			
				|  |  | +        <label>当前工况:</label>
 | 
	
		
			
				|  |  | +        <span :class="infoModel.workConditionClass">{{ infoModel.workCondition }}</span>
 | 
	
		
			
				|  |  | +      </div>
 | 
	
		
			
				|  |  | +      <div class="info-item">
 | 
	
		
			
				|  |  | +        <label>当前风险:</label>
 | 
	
		
			
				|  |  | +        <span class="risk-status">
 | 
	
		
			
				|  |  | +          <span class="risk-item" v-for="(risk, index) in infoModel.riskStatus" :key="index" :style="{ color: risk.color }">
 | 
	
		
			
				|  |  | +            {{ risk.name }}: {{ risk.level }}
 | 
	
		
			
				|  |  | +          </span>
 | 
	
		
			
				|  |  | +        </span>
 | 
	
		
			
				|  |  | +      </div>
 | 
	
		
			
				|  |  | +    </div>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    <!-- 新增日期查询 -->
 | 
	
		
			
				|  |  | +    <div class="filter-row">
 | 
	
		
			
				|  |  | +      <el-date-picker
 | 
	
		
			
				|  |  | +        v-model="endDate"
 | 
	
		
			
				|  |  | +        type="date"
 | 
	
		
			
				|  |  | +        placeholder="选择结束日期"
 | 
	
		
			
				|  |  | +        value-format="yyyy-MM-dd"
 | 
	
		
			
				|  |  | +        :picker-options="pickerOptions"
 | 
	
		
			
				|  |  | +        style="width: 240px; margin-right: 15px;"
 | 
	
		
			
				|  |  | +      />
 | 
	
		
			
				|  |  | +      <el-button type="primary" @click="handleDateQuery" icon="el-icon-search">查询</el-button>
 | 
	
		
			
				|  |  | +    </div>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      <!-- 顶部状态卡片 -->
 | 
	
		
			
				|  |  |      <div class="head">
 | 
	
		
			
				|  |  |        <div class="head-card" v-for="(card, index) in headCards" :key="index" :style="{ backgroundColor: card.color }">
 | 
	
	
		
			
				|  | @@ -49,7 +86,8 @@
 | 
	
		
			
				|  |  |              </thead>
 | 
	
		
			
				|  |  |              <tbody>
 | 
	
		
			
				|  |  |                <tr v-for="(item, i) in chart.data" :key="i">
 | 
	
		
			
				|  |  | -                <td>{{ formatTime(i) }}</td>
 | 
	
		
			
				|  |  | +                <td>{{ formatTime(chart.timeStamps[i]) }}</td>
 | 
	
		
			
				|  |  | +                <!-- 使用实际时间 -->
 | 
	
		
			
				|  |  |                  <td>{{ item }}%</td>
 | 
	
		
			
				|  |  |                  <td :class="getStatusClass(item)">
 | 
	
		
			
				|  |  |                    {{ getStatusText(item) }}
 | 
	
	
		
			
				|  | @@ -70,19 +108,32 @@
 | 
	
		
			
				|  |  |  </template>
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  <script>
 | 
	
		
			
				|  |  | -import * as echarts from 'echarts';
 | 
	
		
			
				|  |  | -import { throttle } from 'lodash-es';
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +import * as echarts from 'echarts'
 | 
	
		
			
				|  |  | +import { throttle } from 'lodash-es'
 | 
	
		
			
				|  |  | +import drillingRiskApi from '@api/drillingRiskApi'
 | 
	
		
			
				|  |  | +import moment from 'moment'
 | 
	
		
			
				|  |  | +import { filter } from 'vuedraggable'
 | 
	
		
			
				|  |  |  export default {
 | 
	
		
			
				|  |  |    name: 'SingleWellWarnInfo',
 | 
	
		
			
				|  |  |    data() {
 | 
	
		
			
				|  |  |      return {
 | 
	
		
			
				|  |  | +      infoModel:{
 | 
	
		
			
				|  |  | +        jh:'草27-侧平12',
 | 
	
		
			
				|  |  | +        latestTime: '2023-09-16 08:08:08',
 | 
	
		
			
				|  |  | +        workCondition: '起下钻',
 | 
	
		
			
				|  |  | +        workConditionClass: 'condition-normal',
 | 
	
		
			
				|  |  | +        riskStatus: [
 | 
	
		
			
				|  |  | +        { name: '卡钻', level: '高', color: '#ff4d4f' },
 | 
	
		
			
				|  |  | +        { name: '井漏', level: '中', color: '#faad14' },
 | 
	
		
			
				|  |  | +        { name: '溢流', level: '低', color: '#52c41a' }
 | 
	
		
			
				|  |  | +      ],
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  |        chartHeight: '400px',
 | 
	
		
			
				|  |  | -      currentView: 'day',
 | 
	
		
			
				|  |  | +      currentView: '1',
 | 
	
		
			
				|  |  |        views: [
 | 
	
		
			
				|  |  | -        { label: '日视图', value: 'day' },
 | 
	
		
			
				|  |  | -        { label: '周视图', value: 'week' },
 | 
	
		
			
				|  |  | -        { label: '月视图', value: 'month' }
 | 
	
		
			
				|  |  | +        { label: '日视图', value: '1' },
 | 
	
		
			
				|  |  | +        { label: '周视图', value: '2' },
 | 
	
		
			
				|  |  | +        { label: '月视图', value: '3' }
 | 
	
		
			
				|  |  |        ],
 | 
	
		
			
				|  |  |        allCharts: [],
 | 
	
		
			
				|  |  |        visibleCharts: [],
 | 
	
	
		
			
				|  | @@ -90,67 +141,180 @@ export default {
 | 
	
		
			
				|  |  |        currentPage: 1,
 | 
	
		
			
				|  |  |        loading: false,
 | 
	
		
			
				|  |  |        showTables: [],
 | 
	
		
			
				|  |  | -      headCards: [{ value: 1000, label: '钩载异常', color: '#6DA9E4' },
 | 
	
		
			
				|  |  | -      { value: 1000, label: '扭矩异常', color: '#7ED957' },
 | 
	
		
			
				|  |  | -      { value: 1000, label: '泵压异常', color: '#FFB347' },
 | 
	
		
			
				|  |  | -      { value: 1000, label: '总池体积异常', color: '#FF6B6B' }]
 | 
	
		
			
				|  |  | -    };
 | 
	
		
			
				|  |  | +      headCards: [
 | 
	
		
			
				|  |  | +        { value: 1000, label: '钩载异常', color: '#6DA9E4' },
 | 
	
		
			
				|  |  | +        { value: 1000, label: '扭矩异常', color: '#7ED957' },
 | 
	
		
			
				|  |  | +        { value: 1000, label: '泵压异常', color: '#FFB347' },
 | 
	
		
			
				|  |  | +        { value: 1000, label: '总池体积异常', color: '#FF6B6B' }
 | 
	
		
			
				|  |  | +      ],
 | 
	
		
			
				|  |  | +      endDate: new Date().toISOString().split('T')[0], // 默认当天
 | 
	
		
			
				|  |  | +      pickerOptions: {
 | 
	
		
			
				|  |  | +        shortcuts: [
 | 
	
		
			
				|  |  | +          {
 | 
	
		
			
				|  |  | +            text: '最近三天',
 | 
	
		
			
				|  |  | +            onClick(picker) {
 | 
	
		
			
				|  |  | +              const date = new Date()
 | 
	
		
			
				|  |  | +              date.setDate(date.getDate() - 2)
 | 
	
		
			
				|  |  | +              picker.$emit('pick', date)
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +          },
 | 
	
		
			
				|  |  | +          {
 | 
	
		
			
				|  |  | +            text: '最近一周',
 | 
	
		
			
				|  |  | +            onClick(picker) {
 | 
	
		
			
				|  |  | +              const date = new Date()
 | 
	
		
			
				|  |  | +              date.setDate(date.getDate() - 6)
 | 
	
		
			
				|  |  | +              picker.$emit('pick', date)
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +        ]
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |    },
 | 
	
		
			
				|  |  |    created() {
 | 
	
		
			
				|  |  | -    this.generateChartData();
 | 
	
		
			
				|  |  |    },
 | 
	
		
			
				|  |  |    mounted() {
 | 
	
		
			
				|  |  | -    this.initCharts();
 | 
	
		
			
				|  |  | -    window.addEventListener('resize', this.handleResize);
 | 
	
		
			
				|  |  | +    this.infoModel.jh = this.$route.query.jh
 | 
	
		
			
				|  |  | +    console.log('this.$route.query.jh',this.$route.query.jh)
 | 
	
		
			
				|  |  | +    this.getRealDataByJh()
 | 
	
		
			
				|  |  | +    this.initCharts()
 | 
	
		
			
				|  |  | +    this.loadChartData()
 | 
	
		
			
				|  |  | +    window.addEventListener('resize', this.handleResize)
 | 
	
		
			
				|  |  | +    this.getWarnCountByJhAndDate()
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  |    },
 | 
	
		
			
				|  |  |    beforeDestroy() {
 | 
	
		
			
				|  |  | -    window.removeEventListener('resize', this.handleResize);
 | 
	
		
			
				|  |  | +    window.removeEventListener('resize', this.handleResize)
 | 
	
		
			
				|  |  |    },
 | 
	
		
			
				|  |  |    methods: {
 | 
	
		
			
				|  |  | -    generateChartData() {
 | 
	
		
			
				|  |  | -      // 生成模拟数据
 | 
	
		
			
				|  |  | -      this.allCharts = [
 | 
	
		
			
				|  |  | -        { id: 1, title: '卡钻风险', data: this.generateRandomData() },
 | 
	
		
			
				|  |  | -        { id: 2, title: '井漏风险', data: this.generateRandomData() },
 | 
	
		
			
				|  |  | -        { id: 3, title: '溢流风险', data: this.generateRandomData() },
 | 
	
		
			
				|  |  | -        // 添加更多测试数据...
 | 
	
		
			
				|  |  | -      ];
 | 
	
		
			
				|  |  | -      this.visibleCharts = this.allCharts.slice(0, this.pageSize);
 | 
	
		
			
				|  |  | -      this.showTables = new Array(this.visibleCharts.length).fill(false);
 | 
	
		
			
				|  |  | -    },
 | 
	
		
			
				|  |  | +    getRealDataByJh(){
 | 
	
		
			
				|  |  | +      var param={
 | 
	
		
			
				|  |  | +        jh:this.infoModel.jh
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      drillingRiskApi.getRealDataByJh(param).then(res=>{
 | 
	
		
			
				|  |  | +        console.log('井实时数据',res)
 | 
	
		
			
				|  |  | +        if(res.success){
 | 
	
		
			
				|  |  | +          this.infoModel.latestTime= res.result[0].warnTime
 | 
	
		
			
				|  |  | +          this.infoModel.workCondition= res.result[0].workingCondition+'-'+res.result[0].motion
 | 
	
		
			
				|  |  | +          // this.infoModel=res.result
 | 
	
		
			
				|  |  | +          this.infoModel.riskStatus.forEach(item=>{
 | 
	
		
			
				|  |  | +            let itemRes=res.result.filter(items=>items.warnType==item.name)
 | 
	
		
			
				|  |  | +            item.level=this.judgeRisk(itemRes[0].warnLevel)
 | 
	
		
			
				|  |  | +          })
 | 
	
		
			
				|  |  | +          
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      })
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    generateRandomData() {
 | 
	
		
			
				|  |  | -      return Array.from({ length: this.getDataLength() }, () =>
 | 
	
		
			
				|  |  | -        Math.floor(Math.random() * 100)
 | 
	
		
			
				|  |  | -      );
 | 
	
		
			
				|  |  |      },
 | 
	
		
			
				|  |  | +    judgeRisk(warnLevel){
 | 
	
		
			
				|  |  | +      if (warnLevel >= 80) {
 | 
	
		
			
				|  |  | +        return '高'
 | 
	
		
			
				|  |  | +      } else if (warnLevel >= 50) {
 | 
	
		
			
				|  |  | +        return '中'
 | 
	
		
			
				|  |  | +      } else {
 | 
	
		
			
				|  |  | +        return '低'
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +    handleDateQuery() {
 | 
	
		
			
				|  |  | +      this.getWarnCountByJhAndDate()
 | 
	
		
			
				|  |  | +      this.loadChartData()
 | 
	
		
			
				|  |  | +      this.getLogByJh()
 | 
	
		
			
				|  |  | +      this.$nextTick(() => {
 | 
	
		
			
				|  |  | +        this.initCharts()
 | 
	
		
			
				|  |  | +      })
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +    getWarnCountByJhAndDate() {
 | 
	
		
			
				|  |  | +      var param = {
 | 
	
		
			
				|  |  | +        startDate: this.endDate + ' 00:00:00',
 | 
	
		
			
				|  |  | +        endDate: this.endDate + ' 23:59:59',
 | 
	
		
			
				|  |  | +        jh: this.infoModel.jh
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      drillingRiskApi.getWarnCountByJhAndDate(param).then(res => {
 | 
	
		
			
				|  |  | +        if (res.success) {
 | 
	
		
			
				|  |  | +          this.headCards[0].value = res.result.gzCount
 | 
	
		
			
				|  |  | +          this.headCards[1].value = res.result.njCount
 | 
	
		
			
				|  |  | +          this.headCards[2].value = res.result.byCount
 | 
	
		
			
				|  |  | +          this.headCards[3].value = res.result.jlCount + res.result.ylCount
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      })
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    async loadChartData() {
 | 
	
		
			
				|  |  | +      try {
 | 
	
		
			
				|  |  | +        // 并行获取三种风险数据
 | 
	
		
			
				|  |  | +        const [qzRes, jlRes, ylRes] = await Promise.all([
 | 
	
		
			
				|  |  | +          this.getLogByJh(this.endDate, this.infoModel.jh, this.currentView, '卡钻'),
 | 
	
		
			
				|  |  | +          this.getLogByJh(this.endDate, this.infoModel.jh, this.currentView, '井漏'),
 | 
	
		
			
				|  |  | +          this.getLogByJh(this.endDate, this.infoModel.jh, this.currentView, '溢流')
 | 
	
		
			
				|  |  | +        ])
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 时间对齐处理逻辑
 | 
	
		
			
				|  |  | +        const processData = data => {
 | 
	
		
			
				|  |  | +          // 按时间升序排序
 | 
	
		
			
				|  |  | +          const sortedData = data.sort((a, b) => new Date(a.warnTime) - new Date(b.warnTime))
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          return {
 | 
	
		
			
				|  |  | +            timeStamps: sortedData.map(d => d.warnTime),
 | 
	
		
			
				|  |  | +            values: sortedData.map(d => d.warnLevel)
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 处理各风险数据
 | 
	
		
			
				|  |  | +        const chartData = {
 | 
	
		
			
				|  |  | +          卡钻风险: processData(qzRes),
 | 
	
		
			
				|  |  | +          井漏风险: processData(jlRes),
 | 
	
		
			
				|  |  | +          溢流风险: processData(ylRes)
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +        // 生成图表配置
 | 
	
		
			
				|  |  | +        this.allCharts = Object.entries(chartData).map(([title, data], index) => ({
 | 
	
		
			
				|  |  | +          id: index + 1,
 | 
	
		
			
				|  |  | +          title,
 | 
	
		
			
				|  |  | +          data: data.values,
 | 
	
		
			
				|  |  | +          timeStamps: data.timeStamps // 保存时间序列用于表格显示
 | 
	
		
			
				|  |  | +        }))
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        this.visibleCharts = this.allCharts.slice(0, this.pageSize)
 | 
	
		
			
				|  |  | +        this.$nextTick(this.initCharts)
 | 
	
		
			
				|  |  | +      } catch (error) {
 | 
	
		
			
				|  |  | +        console.error('数据加载失败:', error)
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +    async getLogByJh(endDate, jh, dateType, warnType) {
 | 
	
		
			
				|  |  | +      var param = {
 | 
	
		
			
				|  |  | +        endDate: endDate,
 | 
	
		
			
				|  |  | +        jh: jh,
 | 
	
		
			
				|  |  | +        dateType: dateType,
 | 
	
		
			
				|  |  | +        warnType: warnType
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      var res = await drillingRiskApi.getLogByJh(param)
 | 
	
		
			
				|  |  | +      return res.result
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  |      getDataLength() {
 | 
	
		
			
				|  |  |        switch (this.currentView) {
 | 
	
		
			
				|  |  | -        case 'day': return 24;
 | 
	
		
			
				|  |  | -        case 'week': return 7;
 | 
	
		
			
				|  |  | -        case 'month': return 30;
 | 
	
		
			
				|  |  | -        default: return 24;
 | 
	
		
			
				|  |  | +        case 'day':
 | 
	
		
			
				|  |  | +          return 24
 | 
	
		
			
				|  |  | +        case 'week':
 | 
	
		
			
				|  |  | +          return 7
 | 
	
		
			
				|  |  | +        case 'month':
 | 
	
		
			
				|  |  | +          return 30
 | 
	
		
			
				|  |  | +        default:
 | 
	
		
			
				|  |  | +          return 24
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |      },
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    formatTime(index) {
 | 
	
		
			
				|  |  | -      if (this.currentView === 'day') {
 | 
	
		
			
				|  |  | -        return `${index}:00`;
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -      return `第${index + 1}${this.currentView === 'week' ? '天' : '日'}`;
 | 
	
		
			
				|  |  | +    formatTime(timeStamp) {
 | 
	
		
			
				|  |  | +      return moment(timeStamp).format('HH:mm')
 | 
	
		
			
				|  |  |      },
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      initCharts() {
 | 
	
		
			
				|  |  |        this.visibleCharts.forEach(chart => {
 | 
	
		
			
				|  |  | -        const chartDom = document.getElementById(`chart${chart.id}`);
 | 
	
		
			
				|  |  | -        if (!chartDom) return;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        const myChart = echarts.init(chartDom);
 | 
	
		
			
				|  |  | -        const option = this.getChartOption(chart);
 | 
	
		
			
				|  |  | -        myChart.setOption(option);
 | 
	
		
			
				|  |  | -        chart.instance = myChart;
 | 
	
		
			
				|  |  | -      });
 | 
	
		
			
				|  |  | +        const chartDom = document.getElementById(`chart${chart.id}`)
 | 
	
		
			
				|  |  | +        if (!chartDom) return
 | 
	
		
			
				|  |  | +        const myChart = echarts.init(chartDom)
 | 
	
		
			
				|  |  | +        const option = this.getChartOption(chart)
 | 
	
		
			
				|  |  | +        myChart.setOption(option)
 | 
	
		
			
				|  |  | +        chart.instance = myChart
 | 
	
		
			
				|  |  | +      })
 | 
	
		
			
				|  |  |      },
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      getChartOption(chart) {
 | 
	
	
		
			
				|  | @@ -164,11 +328,11 @@ export default {
 | 
	
		
			
				|  |  |          },
 | 
	
		
			
				|  |  |          xAxis: {
 | 
	
		
			
				|  |  |            type: 'category',
 | 
	
		
			
				|  |  | -          data: Array.from({ length: this.getDataLength() }, (_, i) =>
 | 
	
		
			
				|  |  | -            this.formatTime(i)
 | 
	
		
			
				|  |  | -          ),
 | 
	
		
			
				|  |  | -          axisLabel: { rotate: 45, color: '#666' },
 | 
	
		
			
				|  |  | -          axisLine: { lineStyle: { color: '#999' } }
 | 
	
		
			
				|  |  | +          data: chart.timeStamps, // 使用实际时间序列
 | 
	
		
			
				|  |  | +          axisLabel: {
 | 
	
		
			
				|  |  | +            rotate: 45,
 | 
	
		
			
				|  |  | +            formatter: value => moment(value).format('HH:mm')
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  |          },
 | 
	
		
			
				|  |  |          yAxis: {
 | 
	
		
			
				|  |  |            type: 'value',
 | 
	
	
		
			
				|  | @@ -192,10 +356,11 @@ export default {
 | 
	
		
			
				|  |  |                color: '#fff'
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |            },
 | 
	
		
			
				|  |  | -          formatter: (params) => {
 | 
	
		
			
				|  |  | +          formatter: params => {
 | 
	
		
			
				|  |  |              const time = params[0].name
 | 
	
		
			
				|  |  |              const value = params[0].value
 | 
	
		
			
				|  |  | -            const riskLevel = this.getRiskLevel(value)
 | 
	
		
			
				|  |  | +            const riskLevel = '低'
 | 
	
		
			
				|  |  | +            //this.getRiskLevel(value)
 | 
	
		
			
				|  |  |              return `
 | 
	
		
			
				|  |  |              <div class="custom-tooltip">
 | 
	
		
			
				|  |  |                <div class="time">${time}</div>
 | 
	
	
		
			
				|  | @@ -211,89 +376,137 @@ export default {
 | 
	
		
			
				|  |  |            `
 | 
	
		
			
				|  |  |            }
 | 
	
		
			
				|  |  |          },
 | 
	
		
			
				|  |  | -        series: [{
 | 
	
		
			
				|  |  | -          type: 'line',
 | 
	
		
			
				|  |  | -          data: chart.data,
 | 
	
		
			
				|  |  | -          smooth: true,
 | 
	
		
			
				|  |  | -          lineStyle: { width: 2, color: '#5470C6' },
 | 
	
		
			
				|  |  | -          areaStyle: {
 | 
	
		
			
				|  |  | -            color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
 | 
	
		
			
				|  |  | -              { offset: 0, color: 'rgba(84, 112, 198, 0.3)' },
 | 
	
		
			
				|  |  | -              { offset: 1, color: 'rgba(84, 112, 198, 0.05)' }
 | 
	
		
			
				|  |  | -            ])
 | 
	
		
			
				|  |  | +        series: [
 | 
	
		
			
				|  |  | +          {
 | 
	
		
			
				|  |  | +            type: 'line',
 | 
	
		
			
				|  |  | +            data: chart.data,
 | 
	
		
			
				|  |  | +            smooth: true,
 | 
	
		
			
				|  |  | +            lineStyle: { width: 2, color: '#5470C6' },
 | 
	
		
			
				|  |  | +            areaStyle: {
 | 
	
		
			
				|  |  | +              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
 | 
	
		
			
				|  |  | +                { offset: 0, color: 'rgba(84, 112, 198, 0.3)' },
 | 
	
		
			
				|  |  | +                { offset: 1, color: 'rgba(84, 112, 198, 0.05)' }
 | 
	
		
			
				|  |  | +              ])
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  |            }
 | 
	
		
			
				|  |  | -        }]
 | 
	
		
			
				|  |  | -      };
 | 
	
		
			
				|  |  | +        ]
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  |      },
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      toggleTable(index) {
 | 
	
		
			
				|  |  | -      this.$set(this.showTables, index, !this.showTables[index]);
 | 
	
		
			
				|  |  | +      this.$set(this.showTables, index, !this.showTables[index])
 | 
	
		
			
				|  |  |        this.$nextTick(() => {
 | 
	
		
			
				|  |  |          this.visibleCharts.forEach(chart => {
 | 
	
		
			
				|  |  | -          chart.instance.resize();
 | 
	
		
			
				|  |  | -        });
 | 
	
		
			
				|  |  | -      });
 | 
	
		
			
				|  |  | +          chart.instance.resize()
 | 
	
		
			
				|  |  | +        })
 | 
	
		
			
				|  |  | +      })
 | 
	
		
			
				|  |  |      },
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      changeView(view) {
 | 
	
		
			
				|  |  | -      this.currentView = view;
 | 
	
		
			
				|  |  | -      this.generateChartData();
 | 
	
		
			
				|  |  | +      this.currentView = view
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |        this.$nextTick(() => {
 | 
	
		
			
				|  |  | -        this.initCharts();
 | 
	
		
			
				|  |  | -      });
 | 
	
		
			
				|  |  | +        this.loadChartData()
 | 
	
		
			
				|  |  | +      })
 | 
	
		
			
				|  |  |      },
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      getStatusClass(value) {
 | 
	
		
			
				|  |  | -      if (value > 80) return 'status-high';
 | 
	
		
			
				|  |  | -      if (value > 50) return 'status-medium';
 | 
	
		
			
				|  |  | -      return 'status-low';
 | 
	
		
			
				|  |  | +      if (value > 80) return 'status-high'
 | 
	
		
			
				|  |  | +      if (value > 50) return 'status-medium'
 | 
	
		
			
				|  |  | +      return 'status-low'
 | 
	
		
			
				|  |  |      },
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      getStatusText(value) {
 | 
	
		
			
				|  |  | -      if (value > 80) return '高风险';
 | 
	
		
			
				|  |  | -      if (value > 50) return '中风险';
 | 
	
		
			
				|  |  | -      return '低风险';
 | 
	
		
			
				|  |  | +      if (value > 80) return '高风险'
 | 
	
		
			
				|  |  | +      if (value > 50) return '中风险'
 | 
	
		
			
				|  |  | +      return '低风险'
 | 
	
		
			
				|  |  |      },
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    handleScroll: throttle(function () {
 | 
	
		
			
				|  |  | -      const container = this.$refs.container;
 | 
	
		
			
				|  |  | -      if (!container) return;
 | 
	
		
			
				|  |  | +    handleScroll: throttle(function() {
 | 
	
		
			
				|  |  | +      const container = this.$refs.container
 | 
	
		
			
				|  |  | +      if (!container) return
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -      const { scrollTop, scrollHeight, clientHeight } = container;
 | 
	
		
			
				|  |  | +      const { scrollTop, scrollHeight, clientHeight } = container
 | 
	
		
			
				|  |  |        if (scrollHeight - (scrollTop + clientHeight) < 100 && !this.loading) {
 | 
	
		
			
				|  |  | -        this.loadMore();
 | 
	
		
			
				|  |  | +        this.loadMore()
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |      }, 200),
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      loadMore() {
 | 
	
		
			
				|  |  | -      this.loading = true;
 | 
	
		
			
				|  |  | +      this.loading = true
 | 
	
		
			
				|  |  |        setTimeout(() => {
 | 
	
		
			
				|  |  | -        const nextPage = this.currentPage + 1;
 | 
	
		
			
				|  |  | -        const start = this.currentPage * this.pageSize;
 | 
	
		
			
				|  |  | -        const newCharts = this.allCharts.slice(start, start + this.pageSize);
 | 
	
		
			
				|  |  | +        const nextPage = this.currentPage + 1
 | 
	
		
			
				|  |  | +        const start = this.currentPage * this.pageSize
 | 
	
		
			
				|  |  | +        const newCharts = this.allCharts.slice(start, start + this.pageSize)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          if (newCharts.length) {
 | 
	
		
			
				|  |  | -          this.visibleCharts = [...this.visibleCharts, ...newCharts];
 | 
	
		
			
				|  |  | -          this.showTables = [...this.showTables, ...new Array(newCharts.length).fill(false)];
 | 
	
		
			
				|  |  | +          this.visibleCharts = [...this.visibleCharts, ...newCharts]
 | 
	
		
			
				|  |  | +          this.showTables = [...this.showTables, ...new Array(newCharts.length).fill(false)]
 | 
	
		
			
				|  |  |            this.$nextTick(() => {
 | 
	
		
			
				|  |  | -            this.initCharts();
 | 
	
		
			
				|  |  | -            this.currentPage = nextPage;
 | 
	
		
			
				|  |  | -          });
 | 
	
		
			
				|  |  | +            this.initCharts()
 | 
	
		
			
				|  |  | +            this.currentPage = nextPage
 | 
	
		
			
				|  |  | +          })
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        this.loading = false;
 | 
	
		
			
				|  |  | -      }, 1000);
 | 
	
		
			
				|  |  | +        this.loading = false
 | 
	
		
			
				|  |  | +      }, 1000)
 | 
	
		
			
				|  |  |      },
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      handleResize() {
 | 
	
		
			
				|  |  |        this.visibleCharts.forEach(chart => {
 | 
	
		
			
				|  |  | -        chart.instance.resize();
 | 
	
		
			
				|  |  | -      });
 | 
	
		
			
				|  |  | +        chart.instance.resize()
 | 
	
		
			
				|  |  | +      })
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  </script>
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  <style lang="less" scoped>
 | 
	
		
			
				|  |  | +.info-row {
 | 
	
		
			
				|  |  | +  background: rgba(242, 245, 247, 0.9);
 | 
	
		
			
				|  |  | +  padding: 16px;
 | 
	
		
			
				|  |  | +  border-radius: 8px;
 | 
	
		
			
				|  |  | +  margin-bottom: 20px;
 | 
	
		
			
				|  |  | +  display: flex;
 | 
	
		
			
				|  |  | +  gap: 30px;
 | 
	
		
			
				|  |  | +  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +.info-item {
 | 
	
		
			
				|  |  | +  display: flex;
 | 
	
		
			
				|  |  | +  align-items: center;
 | 
	
		
			
				|  |  | +  font-size: 16px;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  label {
 | 
	
		
			
				|  |  | +    color: #666;
 | 
	
		
			
				|  |  | +    margin-right: 8px;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  .highlight {
 | 
	
		
			
				|  |  | +    color: #2d8cf0;
 | 
	
		
			
				|  |  | +    font-weight: 500;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  .risk-status {
 | 
	
		
			
				|  |  | +    display: flex;
 | 
	
		
			
				|  |  | +    gap: 15px;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    .risk-item {
 | 
	
		
			
				|  |  | +      padding: 4px 8px;
 | 
	
		
			
				|  |  | +      border-radius: 4px;
 | 
	
		
			
				|  |  | +      background-color: rgba(255, 255, 255, 0.9);
 | 
	
		
			
				|  |  | +      box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +.filter-row {
 | 
	
		
			
				|  |  | +  display: flex;
 | 
	
		
			
				|  |  | +  align-items: center;
 | 
	
		
			
				|  |  | +  margin-bottom: 20px;
 | 
	
		
			
				|  |  | +  padding: 12px 16px;
 | 
	
		
			
				|  |  | +  background: #fff;
 | 
	
		
			
				|  |  | +  border-radius: 8px;
 | 
	
		
			
				|  |  | +  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  .head {
 | 
	
		
			
				|  |  |    display: flex;
 | 
	
		
			
				|  |  |    gap: 15px;
 | 
	
	
		
			
				|  | @@ -488,4 +701,4 @@ th {
 | 
	
		
			
				|  |  |    background: rgba(82, 196, 26, 0.1);
 | 
	
		
			
				|  |  |    border: 1px solid rgba(82, 196, 26, 0.3);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  | -</style>
 | 
	
		
			
				|  |  | +</style>
 |