whychw
2020-10-28 83a168f68179068dd04009f73e2d305959d9ebe3
UA 添加参试设备相关
4个文件已修改
3个文件已添加
1284 ■■■■■ 已修改文件
src/assets/css/m-element-ui.css 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/PageNav.vue 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/chart/LineChartMul.vue 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/routes.js 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/script/config_subject.js 276 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/subject/history.vue 492 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/subject/realtime.vue 474 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/css/m-element-ui.css
@@ -270,6 +270,7 @@
.el-form-item .el-form-item__label {
    color: #606266;
}
.drawer-bg .el-form-item .el-form-item__label,
.dialog-bg .el-form-item .el-form-item__label {
    color: inherit;
}
src/components/PageNav.vue
@@ -109,6 +109,24 @@
                    key: 'watercooling'
                },
                {
                    txt: '参试设备',
                    name: 'subject',
                    router: '',
                    key: 'subject',
                    childrens: [
                        {
                            txt: '实时页面',
                            name: 'subject_realtime',
                            router: '/subject/realtime'
                        },
                        {
                            txt: '历史页面',
                            name: 'subject_history',
                            router: '/subject/history'
                        }
                    ]
                },
                {
                    txt: '用户管理',
                    name: 'usersCenter',
                    router: '',
src/components/chart/LineChartMul.vue
@@ -100,7 +100,8 @@
    },
    methods: {
        setOption(opt) {
            // console.trace();
            // console.trace('lineChart setOption');
            // console.log(opt);
            let dataZoom = this.dataZoom;
            // let tooltip = this.tooltip;
            const self = this;
@@ -199,12 +200,13 @@
                    series.push({
                        type: 'line'
                        ,name: v.name
                        ,smooth: true
                        ,smooth: !v.step
                        ,symbolSize: 0
                        ,sampling: 'average'
                        ,hoverAnimation: false
                        ,data: v.data
                        ,xAxisIndex: i
                        ,step: !!v.step
                        ,yAxisIndex: i
                    });
                    this.unit.push(v.unit);
src/router/routes.js
@@ -305,6 +305,23 @@
                },
                component: (resolve)=>require(['@/views/chargePower/main.vue'], resolve)
            }
            // 参试设备
            ,{
                path: '/subject/realtime',
                name: 'subject_realtime',
                meta: {
                    crumb: '参试设备/实时'
                },
                component: (resolve)=>require(['@/views/subject/realtime.vue'], resolve)
            }
            ,{
                path: '/subject/history',
                name: 'subject_history',
                meta: {
                    crumb: '参试设备/历史'
                },
                component: (resolve)=>require(['@/views/subject/history.vue'], resolve)
            }
        ]
    }
src/script/config_subject.js
New file
@@ -0,0 +1,276 @@
// ac230v_ups
let ac230v_ups = {
  "DCInput_vol": '直流输入电压'
  ,"ACInput_vol": '交流输入电压'
  ,"batt_vol": '蓄电池电压'
  ,"batt_curr": '蓄电池电流'
  ,"ACOutput_vol": '交流输出电压'
  ,"ACOutput_curr": '交流输出电流'
  ,"DCOutput_vol": '直流输出电压'
  ,"DCBus_vol": '中间直流母线电压'
  ,"radiator_tmp": '散热器温度'
  ,"Thyristor_tmp": '可控硅温度'
  ,"Transfor_tmp": '变压器温度'
  ,"ACInduc_tmp": '交流电感温度'
  ,"DCInduc_tmp": '直流电感温度'
  ,"Environ_tmp": '环境温度'
  ,"power_state_code": '供电状态代码'
  ,"error_code": '故障代码'
  ,"work_state": '运行状态'
  ,"fault_state": '故障报警'
};
let cabin_board = {
  "threeAB_vol": '三相线电压AB'
  ,"threeBC_vol": '三相线电压BC'
  ,"threeCA_vol": '三相线电压CA'
  ,"Q1F": '频率'
  ,"Q1currA": '电流A'
  ,"Q1currB": '电流B'
  ,"Q1currC": '电流C'
  ,"Q1power_active": '有功功率'
  ,"Q1power_apparent": '视在功率'
  ,"Q1power_factor": '功率因数'
  ,"Q1circuit_state": '断路器状态'
  ,"Q1ele_state": '电量附件状态'
}
let centra_frequency = {
  "uin1_vol": '整机输入电压1'
  ,"uin2_vol": '整机输入电压2'
  ,"iin1_curr": '整机输入电流1'
  ,"iin2_curr": '整机输入电流2'
  ,"protigbt1_tmp": '保护igbt模块1温度'
  ,"protigbt2_tmp": '保护igbt模块2温度'
  ,"protigbt8_tmp": '保护igbt模块8温度'
  ,"tl1_tmp": '电抗器1温度'
  ,"tl2_tmp": '电抗器2温度'
  ,"tcab_tmp": '柜体温度'
  ,"flag": '整机运行状态信息'
  ,"vdc_up1_vol": '1#模块上直流电容电压'
  ,"vdc_down1_vol": '1#模块下直流电容电压'
  ,"um1_in_vol": '1#模块输入电压'
  ,"ila1_curr": '1#模块A相电感电流'
  ,"ilb1_curr": '1#模块B相电感电流'
  ,"ilc1_curr": '1#模块C相电感电流'
  ,"ioa1_curr": '1#模块A相输出电流'
  ,"iob1_curr": '1#模块B相输出电流'
  ,"ioc1_curr": '1#模块C相输出电流'
  ,"uoab1_vol": '1#模块AB输出线电压'
  ,"uobc1_vol": '1#模块BC输出线电压'
  ,"uoca1_vol": '1#模块CA输出线电压'
  ,"tigbt1_tmp": '1#模块igbt温度'
  ,"tdiode1_tmp": '1#模块箝位二极管温度'
  ,"tlac1_tmp": '1#模块交流滤波电感温度'
  ,"tcac1_tmp": '1#模块交流滤波电容温度'
  ,"tcdc1_tmp": '1#模块直流滤波电容温度'
  ,"m1_flag_state": '1#模块运行状态信息'
  ,"power1": '1#模块功率'
  ,"f1": '1#模块频率'
  ,"errcode1": '1#模块故障代码'
  ,"vdc_up8_vol": '8#模块上直流电容电压'
  ,"vdc_down8_vol": '8#模块下直流电容电压'
  ,"um_in8_vol": '8#模块输入电压'
  ,"ila8_curr": '8#模块A相电感电流'
  ,"ilb8_curr": '8#模块B相电感电流'
  ,"ilc8_curr": '8#模块C相电感电流'
  ,"ioa8_curr": '8#模块A相输出电流'
  ,"iob8_curr": '8#模块B相输出电流'
  ,"ioc8_curr": '8#模块C相输出电流'
  ,"uoab8_vol": '8#模块AB输出线电压'
  ,"uobc8_vol": '8#模块BC输出线电压'
  ,"uoca8_vol": '8#模块CA输出线电压'
  ,"tigbt8_tmp": '8#模块igbt温度'
  ,"tdiode8_tmp": '8#模块箝位二极管温度'
  ,"tlac8_tmp": '8#模块交流滤波电感温度'
  ,"tcac8_tmp": '8#模块交流滤波电容温度'
  ,"tcdc8_tmp": '8#模块直流滤波电容温度'
  ,"m8_flag_state": '8#模块运行状态信息'
  ,"power8": '8#模块功率'
  ,"f8": '8#模块频率'
}
let dc230v_batt = {
  "output_vol": '输出电压'
  ,"output_curr": '输出电流'
  ,"input_vol": '输入电压'
  ,"input_curr": '输入电流'
  ,"bconn_CAN_comstate": '并联CAN通讯状态'
  ,"work_state": '工作状态'
  ,"Under_vol_alarm": '欠压报警'
  ,"Over_vol_alarm": '过压报警'
  ,"Over_load_alarm": '过载报警'
  ,"Over_tmp_alarm": '过温报警'
  ,"short_out_alarm": '短路报警'
}
let dc25v_batt = {
  "output_vol": '输出电压'
  ,"output_curr": '输出电流'
  ,"input_vol": '输入电压'
  ,"input_curr": '输入电流'
  ,"work_state": '工作状态'
  ,"Under_vol_alarm": '欠压报警'
  ,"Over_vol_alarm": '过压报警'
  ,"Over_load_alarm": '过载报警'
  ,"Over_tmp_alarm": '过温报警'
  ,"short_out_alarm": '短路报警'
}
let electrical_monitor_station = {
  "IOc": '输出电流'
  ,"UObc": '输出线电压UObc'
  ,"Udc": '直流电容电压'
  ,"f": '输出频率'
  ,"ErrCode": '故障代码'
  ,"Flag": '运行状态信息'
  ,"Uin1": '输入电压1'
  ,"Uin2": '输入电压2'
  ,"lin1": '输入电流1'
  ,"lin2": '输入电流2'
  ,"UOab": '输出线电压UOab'
  ,"UOca": '输出线电压UOca'
  ,"IOa": '输出电流IOa'
  ,"IOb": '输出电流IOb'
  ,"Power": '总输出功率'
  ,"Cosa": '功率因数'
  ,"TScr1": '晶闸管1温度'
  ,"TIgbta": 'A相IGBT散热器温度'
  ,"TIgbtb": 'B相IGBT散热器温度'
  ,"TIgbtc": 'C相IGBT散热器温度'
  ,"TLa": 'A相电感温度'
  ,"TLb": 'B相电感温度'
  ,"TLc": 'C相电感温度'
  ,"TInyCup": '逆变柜温度'
  ,"TTranCup": '变压柜温度'
  ,"TTran": '变压器温度'
}
let inverter_ele = {
  "uin1_vol": '整机输入电压1'
  ,"uin2_vol": '整机输入电压2'
  ,"iin1_curr": '整机输入电流1'
  ,"iin2_curr": '整机输入电流2'
  ,"ugrid_output_vol": '岸电输出线电压'
  ,"tscr1_tmp": 'SCR1模块温度'
  ,"tscr2_tmp": 'SCR2模块温度'
  ,"ttr1_tmp": '变压器1温度'
  ,"ttr2_tmp": '变压器2温度'
  ,"twater_in_tmp": '入水口温度'
  ,"twater_out_tmp": '出水口温度'
  ,"flux1_flow": '左机流量1'
  ,"flux2_flow": '右机流量2'
  ,"humi_tmp": '整机湿度'
  ,"tcab_tmp": '柜体温度'
  ,"power_output": '输出功率'
  ,"power_cosa": '功率因数'
  ,"fo_output": '输出频率'
  ,"errcode": '故障代码'
  ,"flag": '整机运行状态信息'
  ,"vdc_up1_vol": '1#模块上直流电容电压'
  ,"vdc_down1_vol": '1#模块下直流电容电压'
  ,"um1_in_vol": '1#模块输入电压'
  ,"ila1_curr": '1#模块A相电感电流'
  ,"ilb1_curr": '1#模块B相电感电流'
  ,"ilc1_curr": '1#模块C相电感电流'
  ,"ioa1_curr": '1#模块A相输出电流'
  ,"iob1_curr": '1#模块B相输出电流'
  ,"ioc1_curr": '1#模块C相输出电流'
  ,"uoab1_vol": '1#模块AB输出线电压'
  ,"uobc1_vol": '1#模块BC输出线电压'
  ,"tigbt1_tmp": '1#模块igbt温度'
  ,"tdiode1_tmp": '1#模块箝位二极管温度'
  ,"tlac1_tmp": '1#模块交流滤波电感温度'
  ,"tcac1_tmp": '1#模块交流滤波电容温度'
  ,"tcdc1_tmp": '1#模块直流滤波电容温度'
  ,"m1_flag_state": '1#模块运行状态信息'
  ,"vdc_up8_vol": '8#模块上直流电容电压'
  ,"vdc_down8_vol": '8#模块下直流电容电压'
  ,"um_in8_vol": '8#模块输入电压'
  ,"ila8_curr": '8#模块A相电感电流'
  ,"ilb8_curr": '8#模块B相电感电流'
  ,"ilc8_curr": '8#模块C相电感电流'
  ,"ioa8_curr": '8#模块A相输出电流'
  ,"iob8_curr": '8#模块B相输出电流'
  ,"ioc8_curr": '8#模块C相输出电流'
  ,"uoab8_vol": '8#模块AB输出线电压'
  ,"uobc8_vol": '8#模块BC输出线电压'
  ,"tigbt8_tmp": '8#模块igbt温度'
  ,"tdiode8_tmp": '8#模块箝位二极管温度'
  ,"tlac8_tmp": '8#模块交流滤波电感温度'
  ,"tcac8_tmp": '8#模块交流滤波电容温度'
  ,"tcdc8_tmp": '8#模块直流滤波电容温度'
  ,"m8_flag_state": '8#模块运行状态信息'
}
let medvoldc_converter = {
  "uin_vol": '整机输入电压'
  ,"uout_vol": '整机输出电压'
  ,"iin_curr": '整机输入电流'
  ,"iout_curr": '整机输出电流'
  ,"dcin_tmp": '直流输入开关温度'
  ,"twater_in_tmp": '入水口温度'
  ,"twater_out_tmp": '出水口温度'
  ,"humi_tmp": '整机湿度'
  ,"tcab_tmp": '柜体温度'
  ,"errcode": '故障代码'
  ,"flag": '整机运行状态信息'
  ,"vin1_vol": '1#模块输入电压'
  ,"vin1_curr": '1#模块输入电流'
  ,"vout1_vol": '1#模块输出电压'
  ,"vohalf1_vol": '1#模块输出分压下电容电压'
  ,"iout1_curr": '1#模块输出电流'
  ,"twater_in1_tmp": '1#模块入水口温度'
  ,"twater_out1_tmp": '1#模块出水口温度'
  ,"tscr1_tmp": '1#模块scr温度'
  ,"tigbt_boost1_tmp": '1#模块boost中igbt温度'
  ,"tigbt_buck1_tmp": '1#模块buck中igbt温度'
  ,"tdiode1_tmp": '1#模块二极管温度'
  ,"tlc1_tmp": '1#模块耦合电感温度'
  ,"tlo1_tmp": '1#模块空心电感温度'
  ,"tro1_tmp": '1#模块假负载温度'
  ,"m1_flag_state": '1#模块运行状态信息'
  ,"vin10_vol": '10#模块输入电压'
  ,"vin10_curr": '10#模块输入电流'
  ,"vout10_vol": '10#模块输出电压'
  ,"vohalf10_vol": '10#模块输出分压下电容电压'
  ,"iout10_curr": '10#模块输出电流'
  ,"twater_in10_tmp": '10#模块入水口温度'
  ,"twater_out10_tmp": '10#模块出水口温度'
  ,"tscr10_tmp": '10#模块scr温度'
  ,"tigbt_boost10_tmp": '10#模块boost中igbt温度'
  ,"tigbt_buck10_tmp": '10#模块buck中igbt温度'
  ,"tdiode10_tmp": '10#模块二极管温度'
  ,"tlc10_tmp": '10#模块耦合电感温度'
  ,"tlo10_tmp": '10#模块空心电感温度'
  ,"tro10_tmp": '10#模块假负载温度'
  ,"m10_flag_state": '10#模块运行状态信息'
}
let reliable_board = {
  "threeAB_vol": '三相线电压AB'
  ,"threeBC_vol": '三相线电压BC'
  ,"threeCA_vol": '三相线电压CA'
  ,"Q1F": '频率'
  ,"Q1currA": '电流A'
  ,"Q1currB": '电流B'
  ,"Q1currC": '电流C'
  ,"Q1power_active": '有功功率'
  ,"Q1power_apparent": '视在功率'
  ,"Q1power_factor": '功率因数'
  ,"Q1circuit_state": '断路器状态'
  ,"Q1ele_state": '电量附件状态'
  ,"Q1event_state": '事件代码'
}
export default {
    ac230v_ups
    ,cabin_board
    ,centra_frequency
    ,dc230v_batt
    ,dc25v_batt
    ,electrical_monitor_station
    ,inverter_ele
    ,medvoldc_converter
    ,reliable_board
}
src/views/subject/history.vue
New file
@@ -0,0 +1,492 @@
<template>
  <div class="main">
    <!-- list -->
    <div class="list">
      <div class="list-title">
        <div class="">设备列表</div>
      </div>
      <div class="list-content posR">
        <div class="posA_full">
          <div class="inner">
            <div class="list-item" :class="{'isRun': item.isRun, 'disabled': !item.isRun, 'active': cur_id == item.id}" v-for="(item, index) in list" :key="'list_' + index">
              <div class="name">{{item.name + item.id}}</div>
            </div>
            <!-- 无数据 -->
            <div v-if="!list.length" class="empty-list">暂无数据</div>
          </div>
        </div>
      </div>
    </div>
    <div class="page-content">
      <div class="page-banner tac">
        <div class="f_right d_flex">
          <div class="btn-grp" v-show="!showTable">
            <div class="btn_3d" @click="prevGrp">上一组</div>
            <div class="btn_3d" @click="nextGrp">下一组</div>
            <div class="btn_3d" @click="showGOptions">图表选项</div>
          </div>
          <div class="btn_3d" @click="toggle">显示{{showTable ? '图表' : '表格'}}</div>
        </div>
        <div class="content-title">设备名称</div>
      </div>
      <div class="wraper">
        <div class="container" :class="{'showTable': showTable}">
          <div class="wrap-graph">
          <line-chart-mul id="G_linechart" ref="G_linechart"
            title="我是标题"
            height="100%"
            :max-size='true'
            :show-xaxis="true"
            :categoryLen="categoryLen"
            :show-zoom='false'
            :subtext="true"  trigger-on="mousemove"></line-chart-mul>
          </div>
          <div class="wrap-table">
            <assemble-table
              :data=rtData
              :len="3"
              ></assemble-table>
          </div>
        </div>
      </div>
    </div>
    <!-- 图表配置 -->
    <el-drawer
      title="图表配置"
      direction="rtl"
      size="800px"
      custom-class="drawer-bg drawer-options"
      :visible.sync="G_options.show" >
      <div class="drawer-content">
        <el-form ref="form" :inline="true" size="mini" :model="form.data" :rules="form.rules" label-width="8em">
          <el-form-item label="显示属性数量" prop="categoryLen">
            <el-input type="number" v-model="form.data.categoryLen"></el-input>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" @click="setCategoryLen">设定</el-button>
          </el-form-item>
        </el-form>
        <el-transfer
            class=""
            v-model="selectedLegends"
            :titles="['未选定属性', '已选定属性']"
            :button-texts="['移除', '添加']"
            :data="allLegends"
            :filterable="true"
            @change="selectChange"
            >
          </el-transfer>
        <!-- <el-input
          placeholder="请输入搜索内容"
          prefix-icon="el-icon-search"
          size="small"
          v-model.trim="keyword"
          @input="matching"
          clearable>
          </el-input>
          列表
          <div class="" v-for="(item, index) in categoryList" :key="'list_' + index">{{item}}</div> -->
      </div>
    </el-drawer>
    <!-- ROOTEND -->
  </div>
</template>
<script>
import Timeout from '@/script/Timeout'
import Mock from 'mockjs'
import AssembleTable from '@/components/AssembleTable';
import LineChartMul from '@/components/chart/LineChartMul';
// 设定值的备份 因为要处理最后的余项
let category_len = 10;
let name, unit;
export default {
  name: 'subject_history',
  components: {
    AssembleTable
    ,LineChartMul
  },
  data () {
    const dev_id = this.$route.query.dev_id;
    return {
      list: []
      ,timer: new Timeout()
      ,cur_id: 0
      ,showTable: false
      ,rtData: []
      ,G_data: []
      ,curLegendIdx: 0
      // 当前选中的
      ,selectedLegends: []
      // 图表显示的
      ,curLegends: []
      // 查询出的全量
      ,allLegends: []
      // 筛选后的
      ,categoryList: []
      ,record_time: []
      ,categoryLen_old: 10
      ,categoryLen: 10
      ,G_options: {
        show: false
      }
      ,keyword: ''
      ,form: {
        data: {
          categoryLen: 10
        }
        ,rules: {
          categoryLen: [{
            validator: (rule, value, callback) => {
              if (!('' + value).trim()) {
                callback(new Error('显示属性数量必填'));
              }
              if (/[^0-9]/.test(value)) {
                callback(new Error('显示属性数量必须为数值'));
              }
              if (value < 1 || value > 10) {
                callback(new Error('显示属性数量应介于1~10之间'));
              } else {
                callback()
              }
            },
            trigger: 'blur'
          }]
        }
      }
    }
  },
  computed: {
  },
  methods: {
    // 获取列表
    getList () {
      // TODO
      let data = Mock.mock({
        'list|20-50': [{
          'id|+1': 1,
          'name|1': ['某设备', '未知设备', '一级设备', '二级设备'],
          'isRun': '@boolean(1, 10, true)'
        }]
      });
      console.log(data.list, 0);
      data.list.sort((a, b) => {
        return b.isRun - a.isRun;
      });
      this.list = data.list;
    }
    ,toggle () {
      this.showTable = !this.showTable;
    }
    // 根据id查询实时数据
    ,getRTData (id) {
      let data = Mock.mock({
        'data': {
          'record_time': "@datetime('yyyy-MM-dd HH:mm:ss')",
          'value|33': ['@float(30, 100, 2, 3)'],
        }
      });
      let rtData = [];
      console.log(data.data, 'data.data');
      data.data.value.forEach((v, i) => {
        rtData.push({
          text: name[i],
          val: v + ' ' + unit[i],
          value: v
        });
      });
      this.rtData = rtData;
      this.G_data.forEach((v, i) => {
        // debugger;
        v.value.push(rtData[i].value);
        v.value.shift();
      });
      this.record_time.push(data.data.record_time);
      this.record_time.shift();
    }
    // 根据id查询前100笔数据
    ,get100Data (id) {
      let data = Mock.mock({
        'record_time|100': ["@datetime('yyyy-MM-dd HH:mm:ss')"],
        'name|33': ['@word(3, 8)'],
        'unit|33': ['@Cword(1)'],
        'list|33': [{
          // 'name': '@word(3, 8)',
          'value|100': ['@float(30, 100, 2, 3)'],
          // 'unit': '@Cword(1)'
        }]
      });
      name = data.name;
      unit = data.unit;
      let list = [];
      let allLegends = [];
      data.list.forEach((v, i) => {
        list.push({
          text: name[i],
          key: name[i],
          val: v.value + ' ' + v.unit,
        });
        // allLegends.push(v.name);
        allLegends.push({
          key: name[i]
          ,label: name[i]
          ,unit: unit[i]
        });
      });
      this.record_time = data.record_time;
      this.G_data = data.list;
      // legend数据
      this.allLegends = allLegends;
      this.selectedLegends = allLegends;
      this.curLegends = allLegends.slice(this.curLegendIdx, category_len);
    }
    ,format (data) {
      let xLabel = [],
          series = [],
          obj = {};
      let curLegends = this.curLegends;
      // debugger;
      curLegends.forEach((v) => {
        obj[v.key] = [];
        series.push({
          name: v.key,
          unit: v.unit,
          data: obj[v.key]
        })
      });
      data.forEach((v, idx) => {
        // xLabel.push(v.record_time);
        for (let i = 0, j = curLegends.length; i < j; i++) {
          if (curLegends[i].key == name[idx]) {
            obj[name[idx]].push(...v.value);
            break;
          }
        }
        /*if (curLegends.indexOf(v.name) > -1) {
          obj[v.name].push(...v.value);
        }*/
      });
      console.log(this.record_time, series, 99899);
      return {
        xLabel: this.record_time
        ,series
      }
    }
    /*// 过滤属性类别
    ,matching () {
      let keyword = this.keyword;
      let allLegends = this.allLegends;
      const reg = new RegExp(keyword, ['i']);
      let categoryList = allLegends.filter((v) => {
        return reg.test(v);
      });
      this.categoryList = categoryList;
    }*/
    // 选配置项 上一组
    ,prevGrp () {
      if (this.curLegendIdx < category_len) {
        return false;
      }
      this.curLegendIdx -= category_len;
      this.curLegends = this.selectedLegends.slice(this.curLegendIdx, this.curLegendIdx + category_len);
      // 更新图表
      this.updateGraph();
    }
    // 选配置项 下一组
    ,nextGrp () {
      if (this.curLegendIdx + category_len >= this.selectedLegends.length) {
        return false;
      }
      // debugger;
      this.curLegendIdx += category_len;
      this.curLegends = this.selectedLegends.slice(this.curLegendIdx, this.curLegendIdx + category_len);
      // 更新图表
      this.updateGraph();
    }
    // 更新图表
    ,updateGraph () {
      this.categoryLen = this.curLegends.length;
      if (this.categoryLen != this.categoryLen_old) {
        console.log('clear');
        this.$G.chartManage.get('G_linechart').clear();
      }
      this.categoryLen_old = this.categoryLen;
      this.$nextTick(() => {
        this.$refs['G_linechart'].setOption(this.format(this.G_data));
      });
    }
    // 设定categoryLen
    ,setCategoryLen () {
      this.$refs.form.validate((valid) => {
        if (valid) {
          this.categoryLen = this.form.data.categoryLen * 1;
          category_len = this.form.data.categoryLen * 1;
          this.curLegendIdx = 0;
          this.curLegends = this.selectedLegends.slice(this.curLegendIdx, this.curLegendIdx + category_len);
          this.updateGraph();
        }
      });
    }
    ,showGOptions () {
      this.G_options.show = true;
    }
    ,selectChange (list, type, values) {
      console.log('hhh',list, type, values);
      // 根据类型确定事件
      switch(type) {
        case 'left':
          this.removeSelect(values);
        break;
        case 'right':
          this.addSelect(values);
        break;
      }
    }
    // 向权限组 添加用户
    ,addSelect (list) {
      // console.log(list);
    }
    // 从权限组 移除用记
    ,removeSelect (list) {
      // console.log(list);
    }
    ,loop () {
      this.timer.start(() => {
        this.getRTData();
        this.updateGraph();
        this.timer.open();
      }, 1000);
    }
  },
  mounted () {
    this.getList();
    this.get100Data();
    this.loop();
  },
  destroyed() {
    this.timer.stop();
  }
}
</script>
<style scoped>
.main {
  display: -webkit-flex;
  display: flex;
  height: 100%;
}
.list {
  display: -webkit-flex;
  display: flex;
  flex-direction: column;
  width: 12em;
  margin-right: .4em;
}
.list-title {
  background: #24a3bf;
  padding: 10px 0;
  text-align: center;
}
.list-content {
  flex: 1;
  background: #00324b;
}
.inner {
  height: 100%;
  padding: .6em 0 .6em .6em;
  overflow-y: auto;
}
.list-item {
  margin: .2em 0;
  color: #999;
}
.list-item .name {
  font-style: italic;
}
.list-item.isRun {
  color: #fff;
  cursor: pointer;
}
.list-item.disabled {
  cursor: not-allowed;
}
.list-item.active {
  background: rgba(200, 200, 200, .4);
}
.list-item.isRun .name {
  font-style: normal;
}
.list-item:hover {
  background: rgba(200, 200, 200, .2);
}
.page-content {
  flex: 1;
  background: rgba(0,0,0,.2);
  display: -webkit-flex;
  display: flex;
  flex-direction: column;
}
.wraper {
  flex: 1;
  overflow: hidden;
}
.page-banner {
  padding: 6px;
}
.page-banner .btn_3d {
  width: 6em;
  margin-left: 1em;
}
.container {
  width: 200%;
  height: 100%;
  display: -webkit-flex;
  display: flex;
  -webkit-transition: -webkit-transform 0.4s;
  transition: transform 0.4s;
}
.showTable {
  -webkit-transform: translateX(-50%);
  transform: translateX(-50%);
}
.wrap-graph,
.wrap-table {
  flex: 1;
}
.wrap-graph {
  background: rgba(0,0,0,.2);
}
.empty-list {
  text-align: center;
  -webkit-transform: translate(-.3em, 1em);
  transform: translate(-.3em, 1em);
}
.btn-grp {
  display: -webkit-flex;
  display: flex;
}
>>> .drawer-options {
  background: #005074;
}
/* >>> .drawer-options .el-input {
  width: 6em;
} */
.drawer-content {
  height: 100%;
  display: -webkit-flex;
  display: flex;
  flex-direction: column;
  padding: 10px;
}
</style>
src/views/subject/realtime.vue
New file
@@ -0,0 +1,474 @@
<template>
  <div class="main">
    <!-- list -->
    <div class="list">
      <div class="list-title">
        <div class="">设备列表</div>
      </div>
      <div class="list-content posR">
        <div class="posA_full">
          <div class="inner">
            <div class="list-item" :class="{'isRun': item.isRun, 'disabled': !item.isRun, 'active': cur_id == item.id}" v-for="(item, index) in list" :key="'list_' + index">
              <div class="name">{{item.name + item.id}}</div>
            </div>
            <!-- 无数据 -->
            <div v-if="!list.length" class="empty-list">暂无数据</div>
          </div>
        </div>
      </div>
    </div>
    <div class="page-content">
      <div class="page-banner tac">
        <div class="f_right d_flex">
          <div class="btn-grp" v-show="!showTable">
            <div class="btn_3d" :class="{'disabled': prevDisabled}" @click="prevGrp">上一组</div>
            <div class="btn_3d" :class="{'disabled': nextDisabled}" @click="nextGrp">下一组</div>
            <div class="btn_3d" @click="showGOptions">图表选项</div>
          </div>
          <div class="btn_3d" @click="toggle">显示{{showTable ? '图表' : '表格'}}</div>
        </div>
        <div class="content-title">设备名称</div>
      </div>
      <div class="wraper">
        <div class="container" :class="{'showTable': showTable}">
          <div class="wrap-graph">
          <line-chart-mul id="G_linechart" ref="G_linechart"
            title="我是标题"
            height="100%"
            :max-size='true'
            :show-xaxis="true"
            :categoryLen="categoryLen"
            :show-zoom='false'
            :subtext="true"  trigger-on="mousemove"></line-chart-mul>
          </div>
          <div class="wrap-table">
            <assemble-table
              :data=rtData
              :len="3"
              ></assemble-table>
          </div>
        </div>
      </div>
    </div>
    <!-- 图表配置 -->
    <el-drawer
      title="图表配置"
      direction="rtl"
      size="800px"
      custom-class="drawer-bg drawer-options"
      :visible.sync="G_options.show" >
      <div class="drawer-content">
        <el-form ref="form" :inline="true" size="mini" :model="form.data" :rules="form.rules" label-width="8em">
          <el-form-item label="显示属性数量" prop="categoryLen">
            <el-input type="number" v-model="form.data.categoryLen"></el-input>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" @click="setCategoryLen">设定</el-button>
          </el-form-item>
        </el-form>
        <el-transfer
            class=""
            v-model="selectedLegends"
            :titles="['未选定属性', '已选定属性']"
            :button-texts="['移除', '添加']"
            :data="allLegends"
            :filterable="true"
            @change="selectChange"
            >
          </el-transfer>
        <!-- <el-input
          placeholder="请输入搜索内容"
          prefix-icon="el-icon-search"
          size="small"
          v-model.trim="keyword"
          @input="matching"
          clearable>
          </el-input>
          列表
          <div class="" v-for="(item, index) in categoryList" :key="'list_' + index">{{item}}</div> -->
      </div>
    </el-drawer>
    <!-- ROOTEND -->
  </div>
</template>
<script>
import Timeout from '@/script/Timeout'
import Mock from 'mockjs'
import AssembleTable from '@/components/AssembleTable';
import LineChartMul from '@/components/chart/LineChartMul';
// 设定值的备份 因为要处理最后的余项
let category_len = 10;
let name, unit = {}, step = {};
export default {
  name: 'subject_realtime',
  components: {
    AssembleTable
    ,LineChartMul
  },
  data () {
    const dev_id = this.$route.query.dev_id;
    return {
      list: []
      ,timer: new Timeout()
      ,cur_id: 0
      ,showTable: false
      ,rtData: []
      ,G_data: []
      ,curLegendIdx: 0
      // 当前选中的
      ,selectedLegends: []
      // 图表显示的
      ,curLegends: []
      // 查询出的全量
      ,allLegends: []
      // 筛选后的
      ,categoryList: []
      ,record_time: []
      ,categoryLen_old: 10
      ,categoryLen: 10
      ,G_options: {
        show: false
      }
      ,keyword: ''
      ,form: {
        data: {
          categoryLen: 10
        }
        ,rules: {
          categoryLen: [{
            validator: (rule, value, callback) => {
              if (!('' + value).trim()) {
                callback(new Error('显示属性数量必填'));
              }
              if (/[^0-9]/.test(value)) {
                callback(new Error('显示属性数量必须为数值'));
              }
              if (value < 1 || value > 10) {
                callback(new Error('显示属性数量应介于1~10之间'));
              } else {
                callback()
              }
            },
            trigger: 'blur'
          }]
        }
      }
    }
  },
  computed: {
    prevDisabled () {
      return this.curLegendIdx < category_len;
    }
    ,nextDisabled () {
      // 收集依赖
      this.categoryLen;
      return this.curLegendIdx + category_len >= this.selectedLegends.length;
    }
  },
  methods: {
    // 获取列表
    getList () {
      // TODO
      let data = Mock.mock({
        'list|20-50': [{
          'id|+1': 1,
          'name|1': ['某设备', '未知设备', '一级设备', '二级设备'],
          'isRun': '@boolean(1, 10, true)'
        }]
      });
      console.log(data.list, 0);
      data.list.sort((a, b) => {
        return b.isRun - a.isRun;
      });
      this.list = data.list;
    }
    ,toggle () {
      this.showTable = !this.showTable;
    }
    // 根据id查询实时数据
    ,getRTData (id) {
      let data = Mock.mock({
        'data': {
          'record_time': "@datetime('yyyy-MM-dd HH:mm:ss')",
          'value|33': ['@float(30, 100, 2, 3)'],
        }
      });
      let rtData = [];
      console.log(data.data, 'data.data');
      data.data.value.forEach((v, i) => {
        rtData.push({
          text: name[i],
          val: v + ' ' + unit[name[i]],
          value: v
        });
      });
      this.rtData = rtData;
      this.G_data.forEach((v, i) => {
        // debugger;
        v.value.push(rtData[i].value);
        v.value.shift();
      });
      this.record_time.push(data.data.record_time);
      this.record_time.shift();
    }
    // 根据id查询前100笔数据
    ,get100Data (id) {
      let data = Mock.mock({
        'record_time|100': ["@datetime('yyyy-MM-dd HH:mm:ss')"],
        'name|33': ['@word(3, 8)'],
        'unit|33': ['@Cword(1)'],
        'step|33': ['@bool(1, 5, true)'],
        'list|33': [{
          // 'name': '@word(3, 8)',
          'value|100': ['@float(30, 100, 2, 3)'],
          // 'unit': '@Cword(1)'
        }]
      });
      name = data.name;
      name.forEach((v, i) => {
        unit[v] = data.unit[i];
        step[v] = data.step[i];
      });
      let allLegends = [];
      let selectedLegends = [];
      data.list.forEach((v, i) => {
        // allLegends.push(v.name);
        allLegends.push({
          key: name[i]
          ,label: name[i]
          ,unit: unit[name[i]]
        });
        selectedLegends.push(name[i]);
      });
      this.record_time = data.record_time;
      this.G_data = data.list;
      // legend数据
      this.allLegends = allLegends;
      this.selectedLegends = selectedLegends;
      this.curLegends = selectedLegends.slice(this.curLegendIdx, category_len);
    }
    ,format (data) {
      let xLabel = [],
          series = [],
          obj = {};
      let curLegends = this.curLegends;
      // debugger;
      curLegends.forEach((v) => {
        obj[v] = [];
        series.push({
          name: v,
          unit: unit[v],
          data: obj[v],
          step: step[v]
        })
      });
      data.forEach((v, idx) => {
        // xLabel.push(v.record_time);
        for (let i = 0, j = curLegends.length; i < j; i++) {
          if (curLegends[i] == name[idx]) {
            obj[name[idx]].push(...v.value);
            break;
          }
        }
      });
      console.log(this.record_time, series, 99899);
      return {
        xLabel: this.record_time
        ,series
      }
    }
    // 选配置项 上一组
    ,prevGrp () {
      if (this.curLegendIdx < category_len) {
        return false;
      }
      this.curLegendIdx -= category_len;
      this.curLegends = this.selectedLegends.slice(this.curLegendIdx, this.curLegendIdx + category_len);
      // 更新图表
      this.updateGraph();
    }
    // 选配置项 下一组
    ,nextGrp () {
      if (this.curLegendIdx + category_len >= this.selectedLegends.length) {
        return false;
      }
      // debugger;
      this.curLegendIdx += category_len;
      this.curLegends = this.selectedLegends.slice(this.curLegendIdx, this.curLegendIdx + category_len);
      // 更新图表
      this.updateGraph();
    }
    // 更新图表
    ,updateGraph () {
      this.categoryLen = this.curLegends.length;
      if (this.categoryLen != this.categoryLen_old) {
        console.log('clear');
        this.$G.chartManage.get('G_linechart').clear();
      }
      this.categoryLen_old = this.categoryLen;
      this.$nextTick(() => {
        this.$refs['G_linechart'].setOption(this.format(this.G_data));
      });
    }
    // 设定categoryLen
    ,setCategoryLen () {
      this.$refs.form.validate((valid) => {
        if (valid) {
          this.categoryLen = this.form.data.categoryLen * 1;
          category_len = this.form.data.categoryLen * 1;
          this.curLegendIdx = 0;
          this.curLegends = this.selectedLegends.slice(this.curLegendIdx, this.curLegendIdx + category_len);
          this.updateGraph();
        }
      });
    }
    ,showGOptions () {
      console.log(this.selectedLegends, 765)
      // debugger;
      this.G_options.show = true;
    }
    ,selectChange (list, type, values) {
      console.log('hhh',list, type, values);
      this.curLegendIdx = 0;
      this.selectedLegends = list;
      this.curLegends = this.selectedLegends.slice(this.curLegendIdx, this.curLegendIdx + category_len);
      this.updateGraph();
    }
    ,loop () {
      this.timer.start(() => {
        this.getRTData();
        this.updateGraph();
        this.timer.open();
      }, 1000);
    }
  },
  mounted () {
    this.getList();
    this.get100Data();
    this.loop();
  },
  destroyed() {
    this.timer.stop();
  }
}
</script>
<style scoped>
.main {
  display: -webkit-flex;
  display: flex;
  height: 100%;
}
.list {
  display: -webkit-flex;
  display: flex;
  flex-direction: column;
  width: 12em;
  margin-right: .4em;
}
.list-title {
  background: #24a3bf;
  padding: 10px 0;
  text-align: center;
}
.list-content {
  flex: 1;
  background: #00324b;
}
.inner {
  height: 100%;
  padding: .6em 0 .6em .6em;
  overflow-y: auto;
}
.list-item {
  margin: .2em 0;
  color: #999;
}
.list-item .name {
  font-style: italic;
}
.list-item.isRun {
  color: #fff;
  cursor: pointer;
}
.list-item.disabled {
  cursor: not-allowed;
}
.list-item.active {
  background: rgba(200, 200, 200, .4);
}
.list-item.isRun .name {
  font-style: normal;
}
.list-item:hover {
  background: rgba(200, 200, 200, .2);
}
.page-content {
  flex: 1;
  /*background: rgba(0,0,0,.2);*/
  display: -webkit-flex;
  display: flex;
  flex-direction: column;
}
.wraper {
  flex: 1;
  overflow: hidden;
}
.page-banner {
  padding: 6px;
}
.page-banner .btn_3d {
  width: 6em;
  margin-left: 1em;
}
.container {
  width: 200%;
  height: 100%;
  display: -webkit-flex;
  display: flex;
  -webkit-transition: -webkit-transform 0.4s;
  transition: transform 0.4s;
}
.showTable {
  -webkit-transform: translateX(-50%);
  transform: translateX(-50%);
}
.wrap-graph,
.wrap-table {
  flex: 1;
}
.wrap-graph {
  background: rgba(0,0,0,.2);
}
.empty-list {
  text-align: center;
  -webkit-transform: translate(-.3em, 1em);
  transform: translate(-.3em, 1em);
}
.btn-grp {
  display: -webkit-flex;
  display: flex;
}
>>> .drawer-options {
  background: #005074;
}
/* >>> .drawer-options .el-input {
  width: 6em;
} */
.drawer-content {
  height: 100%;
  display: -webkit-flex;
  display: flex;
  flex-direction: column;
  padding: 10px;
}
</style>