浏览代码

添加设备健康相关模块

dongjh 1 年之前
父节点
当前提交
b6f4eb890d

+ 14 - 1
src/config/router.config.js

@@ -322,7 +322,20 @@ export const constantRouterMap = [
       },
     ]
   },
-
+  // 设备运行详情,注意,不能放到 asyncRouterMap 中,否则不起作用
+  {
+    path: '/equipment/info',
+    component: TabLayout,
+    permission: [ '/ehm/status' ], // 貌似有没有都可以
+    children: [
+      {
+        path: 'detail/:equipmentid(\\d+)',
+        component: () => import('@/views/module_tpm/equipmentInfo/index'),
+        name: 'equipmentinfo',
+        meta: { title: '设备运行详情' }
+      }
+    ]
+  },
   // {
   //   path: '/',
   //   name: 'index',

+ 218 - 0
src/views/module_tpm/equipmentInfo/index.vue

@@ -0,0 +1,218 @@
+<template>
+  <a-card :bordered="false">
+    <div class="table-page-search-wrapper">
+      <a-form layout="inline">
+        <a-row :gutter="24">
+          <a-col :xl="4" :lg="7" :md="8" :sm="24">
+            <a-form-item label="日期">
+              <a-date-picker v-model="queryParams.day" valueFormat="YYYY-MM-DD" placeholder="选择日期"> </a-date-picker>
+            </a-form-item>
+          </a-col>
+          <a-col :xl="4" :lg="7" :md="8" :sm="24">
+            <a-form-item label="类型" prop="tagtype">
+              <a-select v-model="queryParams.tagtype" placeholder="请选择">
+                <a-select-option v-for="(value, key) of tageTypeList" :value="key" :key="key">{{ value }}</a-select-option>
+              </a-select>
+            </a-form-item>
+          </a-col>
+          <a-col :xl="4" :lg="7" :md="8" :sm="24">
+            <a-form-item>
+              <a-button type="primary" icon="search" @click="handleQuery">搜索</a-button>
+            </a-form-item>
+          </a-col>
+        </a-row>
+      </a-form>
+    </div>
+    <div class="trend-charts" ref="trendCharts" :style="{ height: echartsHeight + 'px' }"></div>
+  </a-card>
+</template>
+
+<script>
+import * as echarts from 'echarts'
+import { httpAction, getAction } from '@/api/manage'
+export default {
+  name: 'equipmentInfo',
+  data() {
+    return {
+      loading: true,
+      // 时间
+      timeList: [],
+      echartsHeight: window.innerHeight - 84 - 60 - 30,
+      // 值
+      tagvalueList: [],
+      // 类型
+      tageTypeList: {
+        electricity: '电量',
+        currentA: 'A相电流',
+        currentB: 'B相电流',
+        currentC: 'C相电流',
+        voltageA: 'A相电压',
+        voltageB: 'B相电压',
+        voltageC: 'C相电压',
+        // power: "功率",
+      },
+      equipmentid: null,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 1000,
+        equipmentid: null,
+        day: null,
+        tagtype: null,
+      },
+      url: {
+        list: '/emsStatistics/searchEquipmentDetail',
+      },
+    }
+  },
+  created() {
+    this.queryParams.equipmentid = this.$route.params && this.$route.params.equipmentid
+    // this.queryParams.day = "2023-08-15";
+    this.getNowDate()
+    this.queryParams.tagtype = 'electricity'
+    this.handleQuery()
+  },
+  mounted() {
+    // this.$nextTick(() => {
+    //   this.handleQuery();
+    // });
+  },
+  methods: {
+    /**
+     * 查询当天日期
+     */
+    getNowDate() {
+      const nowTime = new Date()
+      const year = nowTime.getFullYear()
+      let month = nowTime.getMonth() + 1
+      let day = nowTime.getDate()
+      month = month < 10 ? '0' + month : month
+      day = day < 10 ? '0' + day : day
+      this.queryParams.day = `${year}-${month}-${day}`
+    },
+    handleQuery() {
+      var _this = this
+      if (this.queryParams.day == '' || this.queryParams.day == null) {
+        this.$modal.msgError('请选择日期!')
+        return false
+      }
+      _this.loading = true
+      getAction(this.url.list, _this.queryParams).then((response) => {
+        _this.timeList = []
+        _this.tagvalueList = []
+        response.result.forEach((item) => {
+          _this.timeList.push(item.time)
+          _this.tagvalueList.push(item.tagvalue)
+        })
+        // Generate mock data
+        this.loading = false
+
+        this.initEcharts()
+      })
+    },
+    initEcharts() {
+      var _this = this
+      var chartDom = this.$refs.trendCharts
+      var myChart = echarts.init(chartDom)
+      var option
+
+      var tagtypename = ''
+      switch (_this.queryParams.tagtype) {
+        case 'electricity':
+          tagtypename = '累计电量(kW)'
+          break
+        case 'currentA':
+          tagtypename = 'A相电流(A)'
+          break
+        case 'currentB':
+          tagtypename = 'B相电流(A)'
+          break
+        case 'currentC':
+          tagtypename = 'C相电流(A)'
+          break
+        case 'voltageA':
+          tagtypename = 'A相电压(V)'
+          break
+        case 'voltageB':
+          tagtypename = 'B相电压(V)'
+          break
+        case 'voltageC':
+          tagtypename = 'C相电压(V)'
+          break
+        case 'power':
+          tagtypename = '功率(kWH)'
+          break
+        default:
+          break
+      }
+      option = {
+        // Make gradient line here
+        // visualMap: [
+        //   {
+        //     show: false,
+        //     type: "continuous",
+        //   },
+        // ],
+        title: [
+          {
+            left: 'center',
+            text: tagtypename,
+          },
+        ],
+        tooltip: {
+          trigger: 'axis',
+        },
+        dataZoom: [
+          {
+            type: 'inside',
+            start: 0,
+            end: 100,
+            xAxisIndex: 0,
+          },
+          {
+            start: 0,
+            end: 10,
+          },
+        ],
+        xAxis: [
+          {
+          type: 'category',
+          boundaryGap: false,
+            data: _this.timeList,
+          },
+        ],
+        yAxis: [{}],
+        series: [
+          {
+            type: 'line',
+            showSymbol: false,
+            data: _this.tagvalueList,
+            markPoint: {
+              data: [
+                { type: 'max', name: 'Max' },
+                { type: 'min', name: 'Min' },
+              ],
+            },
+          },
+        ],
+      }
+      option && myChart.setOption(option)
+
+      window.addEventListener('resize', function () {
+        myChart.resize()
+      })
+    },
+  },
+}
+</script>
+
+<style lang="less" scoped>
+@import '~@/assets/less/uStyle.less';
+</style>
+<style lang="less">
+.trend-charts {
+  padding: 10px;
+  margin-top: 10px;
+  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
+}
+</style>

+ 49 - 235
src/views/module_tpm/equipmentOnoffSection/EquipmentOnoffSectionList.vue

@@ -1,243 +1,57 @@
 <template>
-  <a-card :bordered="false">
-    <!-- 查询区域 -->
-    <div class="table-page-search-wrapper">
-      <a-form layout="inline" @keyup.enter.native="searchQuery">
-        <a-row :gutter="24">
-        </a-row>
-      </a-form>
-    </div>
-    <!-- 查询区域-END -->
-
-    <!-- 操作按钮区域 -->
-    <div class="table-operator">
-      <a-button @click="handleAdd" type="primary" icon="plus">新增</a-button>
-      <a-button type="primary" icon="download" @click="handleExportXls('tpm_equipment_onoff_section')">导出</a-button>
-      <a-upload name="file" :showUploadList="false" :multiple="false" :headers="tokenHeader" :action="importExcelUrl" @change="handleImportExcel">
-        <a-button type="primary" icon="import">导入</a-button>
-      </a-upload>
-      <!-- 高级查询区域 -->
-      <j-super-query :fieldList="superFieldList" ref="superQueryModal" @handleSuperQuery="handleSuperQuery"></j-super-query>
-      <a-dropdown v-if="selectedRowKeys.length > 0">
-        <a-menu slot="overlay">
-          <a-menu-item key="1" @click="batchDel"><a-icon type="delete"/>删除</a-menu-item>
-        </a-menu>
-        <a-button style="margin-left: 8px"> 批量操作 <a-icon type="down" /></a-button>
-      </a-dropdown>
-    </div>
-
-    <!-- table区域-begin -->
-    <div>
-      <div class="ant-alert ant-alert-info" style="margin-bottom: 16px;">
-        <i class="anticon anticon-info-circle ant-alert-icon"></i> 已选择 <a style="font-weight: 600">{{ selectedRowKeys.length }}</a>项
-        <a style="margin-left: 24px" @click="onClearSelected">清空</a>
-      </div>
-
-      <a-table
-        ref="table"
-        size="middle"
-        :scroll="{x:true}"
-        bordered
-        rowKey="id"
-        :columns="columns"
-        :dataSource="dataSource"
-        :pagination="ipagination"
-        :loading="loading"
-        :rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
-        class="j-table-force-nowrap"
-        @change="handleTableChange">
-
-        <template slot="htmlSlot" slot-scope="text">
-          <div v-html="text"></div>
-        </template>
-        <template slot="imgSlot" slot-scope="text,record">
-          <span v-if="!text" style="font-size: 12px;font-style: italic;">无图片</span>
-          <img v-else :src="getImgView(text)" :preview="record.id" height="25px" alt="" style="max-width:80px;font-size: 12px;font-style: italic;"/>
-        </template>
-        <template slot="fileSlot" slot-scope="text">
-          <span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span>
-          <a-button
-            v-else
-            :ghost="true"
-            type="primary"
-            icon="download"
-            size="small"
-            @click="downloadFile(text)">
-            下载
-          </a-button>
-        </template>
-
-        <span slot="action" slot-scope="text, record">
-          <a @click="handleEdit(record)">编辑</a>
-
-          <a-divider type="vertical" />
-          <a-dropdown>
-            <a class="ant-dropdown-link">更多 <a-icon type="down" /></a>
-            <a-menu slot="overlay">
-              <a-menu-item>
-                <a @click="handleDetail(record)">详情</a>
-              </a-menu-item>
-              <a-menu-item>
-                <a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)">
-                  <a>删除</a>
-                </a-popconfirm>
-              </a-menu-item>
-            </a-menu>
-          </a-dropdown>
-        </span>
-
-      </a-table>
-    </div>
-
-    <equipment-onoff-section-modal ref="modalForm" @ok="modalFormOk"></equipment-onoff-section-modal>
-  </a-card>
+  <div class="tabPage">
+    <a-tabs v-model="curtab" @tab-click="tabClick">
+      <a-tab-pane tab="图表查询" key="chart">
+        <chartSection v-if="curtab==='chart'"></chartSection>
+      </a-tab-pane>
+      <a-tab-pane tab="表格查询" key="grid">
+        <gridSection v-if="curtab==='grid'"></gridSection>
+      </a-tab-pane>
+    </a-tabs>
+  </div>
 </template>
 
 <script>
-
-  import '@/assets/less/TableExpand.less'
-  import { mixinDevice } from '@/utils/mixin'
-  import { JeecgListMixin } from '@/mixins/JeecgListMixin'
-  import EquipmentOnoffSectionModal from './modules/EquipmentOnoffSectionModal'
-
-  export default {
-    name: 'EquipmentOnoffSectionList',
-    mixins:[JeecgListMixin, mixinDevice],
-    components: {
-      EquipmentOnoffSectionModal
-    },
-    data () {
-      return {
-        description: 'tpm_equipment_onoff_section管理页面',
-        // 表头
-        columns: [
-          {
-            title: '#',
-            dataIndex: '',
-            key:'rowIndex',
-            width:60,
-            align:"center",
-            customRender:function (t,r,index) {
-              return parseInt(index)+1;
-            }
-          },
-          {
-            title:'设备id',
-            align:"center",
-            dataIndex: 'equipmentid'
-          },
-          {
-            title:'设备状态:1运行、2待机、3停机',
-            align:"center",
-            dataIndex: 'status'
-          },
-          {
-            title:'开始时间',
-            align:"center",
-            dataIndex: 'starttime',
-            customRender:function (text) {
-              return !text?"":(text.length>10?text.substr(0,10):text)
-            }
-          },
-          {
-            title:'结束时间',
-            align:"center",
-            dataIndex: 'endtime',
-            customRender:function (text) {
-              return !text?"":(text.length>10?text.substr(0,10):text)
-            }
-          },
-          {
-            title:'时长(分钟)',
-            align:"center",
-            dataIndex: 'duration'
-          },
-          {
-            title:'所属年',
-            align:"center",
-            dataIndex: 'year'
-          },
-          {
-            title:'所属月',
-            align:"center",
-            dataIndex: 'month'
-          },
-          {
-            title:'日期',
-            align:"center",
-            dataIndex: 'day'
-          },
-          {
-            title:'时间',
-            align:"center",
-            dataIndex: 'time'
-          },
-          {
-            title:'所属年月',
-            align:"center",
-            dataIndex: 'yearmonth'
-          },
-          {
-            title:'所属周',
-            align:"center",
-            dataIndex: 'week'
-          },
-          {
-            title:'周几',
-            align:"center",
-            dataIndex: 'dayofweek'
-          },
-          {
-            title: '操作',
-            dataIndex: 'action',
-            align:"center",
-            fixed:"right",
-            width:147,
-            scopedSlots: { customRender: 'action' }
-          }
-        ],
-        url: {
-          list: "/equipmentOnoffSection/equipmentOnoffSection/list",
-          delete: "/equipmentOnoffSection/equipmentOnoffSection/delete",
-          deleteBatch: "/equipmentOnoffSection/equipmentOnoffSection/deleteBatch",
-          exportXlsUrl: "/equipmentOnoffSection/equipmentOnoffSection/exportXls",
-          importExcelUrl: "equipmentOnoffSection/equipmentOnoffSection/importExcel",
-          
-        },
-        dictOptions:{},
-        superFieldList:[],
-      }
-    },
-    created() {
-    this.getSuperFieldList();
+import chartSection from "./chartsection.vue";
+import gridSection from "./gridsection.vue";
+export default {
+  name: "equipmentonoffsection",
+  components: {
+    gridSection, //表格查询
+    chartSection, //图表查询
+  },
+  data() {
+    return {
+      curtab: 'chart',
+      // 遮罩层
+      loading: true,
+    };
+  },
+  created() {
+  },
+  methods: {
+    // 选择tab标签
+    tabClick(tab, event) {
+      this.curtab = tab.name;
     },
-    computed: {
-      importExcelUrl: function(){
-        return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`;
-      },
-    },
-    methods: {
-      initDictConfig(){
-      },
-      getSuperFieldList(){
-        let fieldList=[];
-        fieldList.push({type:'int',value:'equipmentid',text:'设备id'})
-        fieldList.push({type:'string',value:'status',text:'设备状态:1运行、2待机、3停机'})
-        fieldList.push({type:'date',value:'starttime',text:'开始时间'})
-        fieldList.push({type:'date',value:'endtime',text:'结束时间'})
-        fieldList.push({type:'int',value:'duration',text:'时长(分钟)'})
-        fieldList.push({type:'int',value:'year',text:'所属年'})
-        fieldList.push({type:'int',value:'month',text:'所属月'})
-        fieldList.push({type:'string',value:'day',text:'日期'})
-        fieldList.push({type:'string',value:'time',text:'时间'})
-        fieldList.push({type:'string',value:'yearmonth',text:'所属年月'})
-        fieldList.push({type:'int',value:'week',text:'所属周'})
-        fieldList.push({type:'int',value:'dayofweek',text:'周几'})
-        this.superFieldList = fieldList
-      }
+  },
+};
+</script>
+<style lang="less" scoped>
+  @import '~@/assets/less/uStyle.less';
+</style>
+<style lang="less" scoped>
+.tabPage {
+  min-height: calc(100vh - 104px);
+  margin: 10px;
+  box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12), 0 0 6px 0 rgba(0, 0, 0, 0.04);
+  border: 1px solid #dcdfe6;
+  .a-tabs--border-card {
+    border: none;
+    box-shadow: none;
+    ::v-deep .a-tabs__content {
+      padding: 0px;
     }
   }
-</script>
-<style scoped>
-  @import '~@assets/less/common.less';
+}
 </style>

+ 199 - 0
src/views/module_tpm/equipmentOnoffSection/chartsection.vue

@@ -0,0 +1,199 @@
+<template>
+  <div>
+    <div class="table-page-search-wrapper">
+      <a-form layout="inline" :model="queryParams" ref="queryForm">
+        <a-row :gutter="24">
+          <a-col :xl="6" :lg="11" :md="12" :sm="24">
+            <a-form-item label="查询日期">
+              <a-range-picker date-format="YYYY-MM-DD" v-model="queryParams.date" @change="onChangeDate" />
+            </a-form-item>
+          </a-col>
+          <a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <span style="float: left; overflow: hidden" class="table-page-search-submitButtons">
+              <a-button type="primary" @click="handleQuery" icon="search">查询</a-button>
+            </span>
+          </a-col>
+        </a-row>
+      </a-form>
+    </div>
+    <div class="trend-charts" ref="trendCharts" style="width: 100%; height: 1800px"></div>
+  </div>
+</template>
+
+<script>
+import * as echarts from 'echarts'
+import { httpAction, getAction } from '@/api/manage'
+export default {
+  name: '',
+  data() {
+    return {
+      loading: true,
+      // 数据
+      tpmequiponoffsectionList: [],
+      // 查询参数
+      queryParams: {
+        date: [],
+        day_begin: '',
+        day_end: '',
+      },
+      // 设备
+      equipments: [],
+      // 运行
+      onduration: [],
+      // 待机
+      pauseduration: [],
+      // 关机
+      offduration: [],
+      url: {
+        list: '/equipmentOnoffSection/equipmentOnoffSection/gettransverse',
+      },
+    }
+  },
+  created() {},
+  mounted() {
+    this.$nextTick(() => {
+      var now = this.dateformat(new Date()).substring(0, 10)
+      this.queryParams.date.push(now)
+      this.queryParams.date.push(now)
+      this.queryParams.day_begin = now
+      this.queryParams.day_end = now
+      this.handleQuery()
+    })
+  },
+  methods: {
+    // 时间处理
+    onChangeDate(date, dateString) {
+      this.queryParams.day_begin = dateString[0]
+      this.queryParams.day_end = dateString[1]
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.handleQuery()
+    },
+    dateformat(date) {
+      var year = date.getFullYear()
+      var month = date.getMonth() + 1
+      month = month < 10 ? '0' + month : month
+      var strDate = date.getDate()
+      strDate = strDate < 10 ? '0' + strDate : strDate
+      var hour = date.getHours()
+      hour = hour < 10 ? '0' + hour : hour
+      var minute = date.getMinutes()
+      minute = minute < 10 ? '0' + minute : minute
+      var second = date.getSeconds()
+      second = second < 10 ? '0' + second : second
+
+      return year + '-' + month + '-' + strDate + ' ' + hour + ':' + minute + ':' + second
+    },
+    handleQuery() {
+      var _this = this
+      _this.loading = true
+      getAction(this.url.list, _this.queryParams).then((response) => {
+        _this.tpmequiponoffsectionList = response.result
+        // Generate mock data
+        _this.equipments = []
+        _this.onduration = []
+        _this.pauseduration = []
+        _this.offduration = []
+        _this.tpmequiponoffsectionList.forEach(function (equipment, key) {
+          _this.equipments.push(equipment.equipmentid_dictText + '[' + equipment.equipmentcode + ']')
+          _this.onduration.push(equipment.onduration)
+          _this.pauseduration.push(equipment.pauseduration)
+          _this.offduration.push(equipment.offduration)
+        })
+
+        this.loading = false
+
+        this.initEcharts()
+      })
+    },
+    initEcharts() {
+      var _this = this
+      var chartDom = this.$refs.trendCharts
+      var myChart = echarts.init(chartDom)
+      var option
+      var types = [
+        { name: '运行', color: '#75d874' },
+        { name: '待机', color: '#dc77dc' },
+        { name: '停机', color: '#bd6d6c' },
+      ]
+
+      option = {
+        title: {
+          text: '设备运行情况(分钟)',
+          left: 'center',
+        },
+        tooltip: {
+          trigger: 'axis',
+          axisPointer: {
+            type: 'shadow',
+          },
+        },
+        legend: {
+          bottom: 0,
+        },
+        grid: {
+          top: '30px',
+          left: '3%',
+          right: '4%',
+          bottom: '25px',
+          containLabel: true,
+        },
+        xAxis: {
+          type: 'value',
+        },
+        yAxis: {
+          type: 'category',
+          data: _this.equipments,
+        },
+        toolbox: {
+          show: true,
+          feature: {
+            saveAsImage: {},
+          },
+        },
+        series: [
+          {
+            name: types[0].name,
+            type: 'bar',
+            stack: 'total',
+            color: types[0].color,
+            data: _this.onduration,
+          },
+          {
+            name: types[1].name,
+            type: 'bar',
+            stack: 'total',
+            color: types[1].color,
+            data: _this.pauseduration,
+          },
+          {
+            name: types[2].name,
+            type: 'bar',
+            stack: 'total',
+            color: types[2].color,
+            data: _this.offduration,
+          },
+        ],
+      }
+
+      option && myChart.setOption(option)
+
+      window.addEventListener('resize', function () {
+        myChart.resize()
+      })
+    },
+  },
+}
+</script>
+
+<style lang="less" scoped>
+@import '~@/assets/less/uStyle.less';
+</style>
+<style lang="less">
+.trend-charts {
+  padding: 10px;
+  margin-top: 10px;
+  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
+}
+</style>

+ 232 - 0
src/views/module_tpm/equipmentOnoffSection/gridsection.vue

@@ -0,0 +1,232 @@
+<template>
+  <a-card :bordered="false">
+    <div class="table-page-search-wrapper">
+      <a-form layout="inline">
+        <a-row :gutter="24">
+          <a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <a-form-item label="设备名称">
+              <!-- <j-dict-select-tag placeholder="请选择设备名称" v-model="queryParam.result" dictCode="spotcheck_result"/> -->
+            </a-form-item>
+          </a-col>
+          <a-col :xl="6" :lg="11" :md="12" :sm="24">
+            <a-form-item label="查询日期">
+              <a-range-picker date-format="YYYY-MM-DD" v-model="queryParam.date" @change="onChangeDate" />
+            </a-form-item>
+          </a-col>
+          <a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <span style="float: left; overflow: hidden" class="table-page-search-submitButtons">
+              <a-button type="primary" @click="loadData" icon="search">查询</a-button>
+              <!-- <a-button type="primary" @click="searchReset" icon="reload" style="margin-left: 8px">重置</a-button> -->
+            </span>
+          </a-col>
+        </a-row>
+      </a-form>
+    </div>
+
+    <!-- table区域-begin -->
+    <div>
+      <a-table
+        ref="table"
+        size="middle"
+        :scroll="{ x: true }"
+        bordered
+        rowKey="equipmentid"
+        :columns="columns"
+        :dataSource="dataSource"
+        :pagination="ipagination"
+        :loading="loading"
+        :rowSelection="{ selectedRowKeys: selectedRowKeys, onChange: onSelectChange }"
+        class="j-table-force-nowrap"
+        @change="handleTableChange"
+      >
+        <template slot="htmlSlot" slot-scope="text">
+          <div v-html="text"></div>
+        </template>
+        <template slot="imgSlot" slot-scope="text, record">
+          <span v-if="!text" style="font-size: 12px; font-style: italic">无图片</span>
+          <img
+            v-else
+            :src="getImgView(text)"
+            :preview="record.equipmentid"
+            height="25px"
+            alt=""
+            style="max-width: 80px; font-size: 12px; font-style: italic"
+          />
+        </template>
+        <template slot="fileSlot" slot-scope="text">
+          <span v-if="!text" style="font-size: 12px; font-style: italic">无文件</span>
+          <a-button v-else :ghost="true" type="primary" icon="download" size="small" @click="downloadFile(text)">
+            下载
+          </a-button>
+        </template>
+      </a-table>
+    </div>
+  </a-card>
+</template>
+
+<script>
+import { mixinDevice } from '@/utils/mixin'
+import { JeecgListMixin } from '@/mixins/JeecgListMixin'
+// import SelectDialogEq from "@/components/SelectDialogEq/index.vue";
+import { httpAction, getAction } from '@/api/manage'
+
+export default {
+  name: 'Tpmequiponoffsection',
+  mixins: [JeecgListMixin, mixinDevice],
+  components: {
+    // SelectDialogEq,
+  },
+  data() {
+    return {
+      // 查询参数
+      // queryParam: {
+      //   equipmentid: '',
+      //   day_begin: '',
+      //   day_end: '',
+      // },
+      url: {
+        list: '/equipmentOnoffSection/equipmentOnoffSection/listtransverse',
+      },
+      // 表头
+      columns: [
+        {
+          title: '#',
+          dataIndex: '',
+          key: 'rowIndex',
+          width: 60,
+          align: 'center',
+          customRender: function (t, r, index) {
+            return parseInt(index) + 1
+          },
+        },
+        {
+          title: '设备名称',
+          align: 'center',
+          dataIndex: 'equipmentid_dictText',
+        },
+        {
+          title: '设备编号',
+          align: 'center',
+          dataIndex: 'equipmentcode',
+        },
+        {
+          title: '日期',
+          align: 'center',
+          dataIndex: 'day',
+        },
+        {
+          title: '总时长(分钟)',
+          align: 'center',
+          dataIndex: 'duration',
+        },
+        {
+          title: '运行时长(分钟)',
+          align: 'center',
+          dataIndex: 'onduration',
+        },
+        {
+          title: '待机时长(分钟)',
+          align: 'center',
+          dataIndex: 'pauseduration',
+        },
+        {
+          title: '关机时长(分钟)',
+          align: 'center',
+          dataIndex: 'offduration',
+        },
+      ],
+    }
+  },
+  created() {},
+  methods: {
+    // 时间处理
+    onChangeDate(date, dateString) {
+      console.log(date, dateString)
+      this.queryParam.day_begin = dateString[0]
+      this.queryParam.day_end = dateString[1]
+    },
+    // 选择框上,选择设备
+    // chooseEquipment1(params) {
+    //   // 返回对象
+    //   this.queryParam.equipmentid = params.equipmentid
+    //   this.queryParam.equipmentcode = params.equipmentcode
+    //   this.queryParam.equipmentname = params.equipmentname
+    //   this.loadData()
+    // },
+    /** 查询设备运行状态时间段列表 */
+    loadData(arg) {
+      if (!this.url.list) {
+        this.$message.error('请设置url.list属性!')
+        return
+      }
+      //加载数据 若传入参数1则加载第一页的内容
+      if (arg === 1) {
+        this.ipagination.current = 1
+      }
+      var params = this.getQueryParams() //查询条件
+      params.equipmentid = !params.equipmentid ? '' : params.equipmentid
+      params.day_begin = !params.day_begin ? '' : params.day_begin
+      params.day_end = !params.day_end ? '' : params.day_end
+      this.loading = true
+      getAction(this.url.list, params).then((res) => {
+        if (res.success) {
+          //update-begin---author:zhangyafei    Date:20201118  for:适配不分页的数据列表------------
+          this.dataSource = res.result.records || res.result
+          if (res.result.total) {
+            this.ipagination.total = res.result.total
+          } else {
+            this.ipagination.total = 0
+          }
+          //update-end---author:zhangyafei    Date:20201118  for:适配不分页的数据列表------------
+        } else {
+          this.$message.warning(res.message)
+        }
+
+        this.loading = false
+      })
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false
+      this.reset()
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParam.pageNum = 1
+      this.getList()
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm('queryForm')
+      this.handleQuery()
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map((item) => item.onoffsectionid)
+      this.single = selection.length !== 1
+      this.multiple = !selection.length
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      if (this.dateRange == null || this.dateRange.length < 1) {
+        this.$message({
+          type: 'error',
+          message: '请先选择日期!',
+        })
+        return false
+      }
+      this.download(
+        'tpm/tpmequipmentonoffsection/exporttransverse',
+        {
+          ...this.queryParam,
+        },
+        `设备运行状态_${new Date().getTime()}.xlsx`
+      )
+    },
+  },
+}
+</script>
+
+<style scoped>
+@import '~@assets/less/common.less';
+</style>

+ 209 - 0
src/views/module_tpm/equipmentRunStatis/history.vue

@@ -0,0 +1,209 @@
+<template>
+  <div>
+    <div class="table-page-search-wrapper">
+      <a-form layout="inline" :model="queryParams" ref="queryForm">
+        <a-row :gutter="24">
+          <a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <a-form-item label="设备名称">
+              <!-- <j-dict-select-tag placeholder="请选择设备名称" v-model="queryParam.result" dictCode="spotcheck_result"/> -->
+            </a-form-item>
+          </a-col>
+          <a-col :xl="6" :lg="11" :md="12" :sm="24">
+            <a-form-item label="查询日期">
+              <a-range-picker date-format="YYYY-MM-DD" v-model="queryParams.date" @change="onChangeDate" />
+            </a-form-item>
+          </a-col>
+          <a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <a-form-item label="参数类型">
+              <!-- <j-dict-select-tag placeholder="请选择参数类型" v-model="queryParam.result" dictCode="spotcheck_result"/> -->
+            </a-form-item>
+          </a-col>
+          <a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <span style="float: left; overflow: hidden" class="table-page-search-submitButtons">
+              <a-button type="primary" @click="handleQuery" icon="search">查询</a-button>
+            </span>
+          </a-col>
+        </a-row>
+      </a-form>
+    </div>
+    <div class="trend-charts" ref="trendCharts" style="width: 100%; height: 1800px"></div>
+  </div>
+</template>
+
+<script>
+import * as echarts from 'echarts'
+import { httpAction, getAction } from '@/api/manage'
+export default {
+  name: '',
+  data() {
+    return {
+      loading: true,
+      // 数据
+      tpmequiponoffsectionList: [],
+      // 查询参数
+      queryParams: {
+        date: [],
+        day_begin: '',
+        day_end: '',
+      },
+      // 设备
+      equipments: [],
+      // 运行
+      onduration: [],
+      // 待机
+      pauseduration: [],
+      // 关机
+      offduration: [],
+      url: {
+        list: '/equipmentOnoffSection/equipmentOnoffSection/gettransverse',
+      },
+    }
+  },
+  created() {},
+  mounted() {
+    this.$nextTick(() => {
+      var now = this.dateformat(new Date()).substring(0, 10)
+      this.queryParams.date.push(now)
+      this.queryParams.date.push(now)
+      this.queryParams.day_begin = now
+      this.queryParams.day_end = now
+      this.handleQuery()
+    })
+  },
+  methods: {
+    // 时间处理
+    onChangeDate(date, dateString) {
+      this.queryParams.day_begin = dateString[0]
+      this.queryParams.day_end = dateString[1]
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.handleQuery()
+    },
+    dateformat(date) {
+      var year = date.getFullYear()
+      var month = date.getMonth() + 1
+      month = month < 10 ? '0' + month : month
+      var strDate = date.getDate()
+      strDate = strDate < 10 ? '0' + strDate : strDate
+      var hour = date.getHours()
+      hour = hour < 10 ? '0' + hour : hour
+      var minute = date.getMinutes()
+      minute = minute < 10 ? '0' + minute : minute
+      var second = date.getSeconds()
+      second = second < 10 ? '0' + second : second
+
+      return year + '-' + month + '-' + strDate + ' ' + hour + ':' + minute + ':' + second
+    },
+    handleQuery() {
+      var _this = this
+      _this.loading = true
+      getAction(this.url.list, _this.queryParams).then((response) => {
+        _this.tpmequiponoffsectionList = response.result
+        // Generate mock data
+        _this.equipments = []
+        _this.onduration = []
+        _this.pauseduration = []
+        _this.offduration = []
+        _this.tpmequiponoffsectionList.forEach(function (equipment, key) {
+          _this.equipments.push(equipment.equipmentid_dictText + '[' + equipment.equipmentcode + ']')
+          _this.onduration.push(equipment.onduration)
+          _this.pauseduration.push(equipment.pauseduration)
+          _this.offduration.push(equipment.offduration)
+        })
+
+        this.loading = false
+
+        this.initEcharts()
+      })
+    },
+    initEcharts() {
+      var _this = this
+      var chartDom = this.$refs.trendCharts
+      var myChart = echarts.init(chartDom)
+      var option
+      var types = [
+        { name: '运行', color: '#75d874' },
+        { name: '待机', color: '#dc77dc' },
+        { name: '停机', color: '#bd6d6c' },
+      ]
+
+      option = {
+        title: {
+          text: '设备运行情况(分钟)',
+          left: 'center',
+        },
+        tooltip: {
+          trigger: 'axis',
+          axisPointer: {
+            type: 'shadow',
+          },
+        },
+        legend: {
+          bottom: 0,
+        },
+        grid: {
+          top: '30px',
+          left: '3%',
+          right: '4%',
+          bottom: '25px',
+          containLabel: true,
+        },
+        xAxis: {
+          type: 'value',
+        },
+        yAxis: {
+          type: 'category',
+          data: _this.equipments,
+        },
+        toolbox: {
+          show: true,
+          feature: {
+            saveAsImage: {},
+          },
+        },
+        series: [
+          {
+            name: types[0].name,
+            type: 'bar',
+            stack: 'total',
+            color: types[0].color,
+            data: _this.onduration,
+          },
+          {
+            name: types[1].name,
+            type: 'bar',
+            stack: 'total',
+            color: types[1].color,
+            data: _this.pauseduration,
+          },
+          {
+            name: types[2].name,
+            type: 'bar',
+            stack: 'total',
+            color: types[2].color,
+            data: _this.offduration,
+          },
+        ],
+      }
+
+      option && myChart.setOption(option)
+
+      window.addEventListener('resize', function () {
+        myChart.resize()
+      })
+    },
+  },
+}
+</script>
+
+<style lang="less" scoped>
+@import '~@/assets/less/uStyle.less';
+</style>
+<style lang="less">
+.trend-charts {
+  padding: 10px;
+  margin-top: 10px;
+  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
+}
+</style>

+ 57 - 0
src/views/module_tpm/equipmentRunStatis/index.vue

@@ -0,0 +1,57 @@
+<template>
+  <div class="tabPage">
+    <a-tabs v-model="curtab" @tab-click="tabClick">
+      <a-tab-pane tab="实时数据" key="realtime">
+        <realtime v-if="curtab==='realtime'"></realtime>
+      </a-tab-pane>
+      <a-tab-pane tab="历史数据" key="history">
+        <history v-if="curtab==='history'"></history>
+      </a-tab-pane>
+    </a-tabs>
+  </div>
+</template>
+
+<script>
+import realtime from "./realtime.vue";
+import history from "./history.vue";
+export default {
+  name: "equipmentRunStatis",
+  components: {
+    realtime, //实时数据
+    history, //历史数据
+  },
+  data() {
+    return {
+      curtab: 'realtime',
+      // 遮罩层
+      loading: true,
+    };
+  },
+  created() {
+  },
+  methods: {
+    // 选择tab标签
+    tabClick(tab, event) {
+      this.curtab = tab.name;
+    },
+  },
+};
+</script>
+<style lang="less" scoped>
+  @import '~@/assets/less/uStyle.less';
+</style>
+<style lang="less" scoped>
+.tabPage {
+  min-height: calc(100vh - 104px);
+  margin: 10px;
+  box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12), 0 0 6px 0 rgba(0, 0, 0, 0.04);
+  border: 1px solid #dcdfe6;
+  .a-tabs--border-card {
+    border: none;
+    box-shadow: none;
+    ::v-deep .a-tabs__content {
+      padding: 0px;
+    }
+  }
+}
+</style>

+ 204 - 0
src/views/module_tpm/equipmentRunStatis/realtime.vue

@@ -0,0 +1,204 @@
+<template>
+  <div>
+    <div class="table-page-search-wrapper">
+      <a-form layout="inline" :model="queryParams" ref="queryForm">
+        <a-row :gutter="24">
+          <a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <a-form-item label="设备名称">
+              <!-- <j-dict-select-tag placeholder="请选择设备名称" v-model="queryParam.result" dictCode="spotcheck_result"/> -->
+            </a-form-item>
+          </a-col>
+          <a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <a-form-item label="参数类型">
+              <!-- <j-dict-select-tag placeholder="请选择参数类型" v-model="queryParam.result" dictCode="spotcheck_result"/> -->
+            </a-form-item>
+          </a-col>
+          <a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <span style="float: left; overflow: hidden" class="table-page-search-submitButtons">
+              <a-button type="primary" @click="handleQuery" icon="search">查询</a-button>
+            </span>
+          </a-col>
+        </a-row>
+      </a-form>
+    </div>
+    <div class="trend-charts" ref="trendCharts" style="width: 100%; height: 1800px"></div>
+  </div>
+</template>
+
+<script>
+import * as echarts from 'echarts'
+import { httpAction, getAction } from '@/api/manage'
+export default {
+  name: '',
+  data() {
+    return {
+      loading: true,
+      // 数据
+      tpmequiponoffsectionList: [],
+      // 查询参数
+      queryParams: {
+        date: [],
+        day_begin: '',
+        day_end: '',
+      },
+      // 设备
+      equipments: [],
+      // 运行
+      onduration: [],
+      // 待机
+      pauseduration: [],
+      // 关机
+      offduration: [],
+      url: {
+        list: '/equipmentOnoffSection/equipmentOnoffSection/gettransverse',
+      },
+    }
+  },
+  created() {},
+  mounted() {
+    this.$nextTick(() => {
+      var now = this.dateformat(new Date()).substring(0, 10)
+      this.queryParams.date.push(now)
+      this.queryParams.date.push(now)
+      this.queryParams.day_begin = now
+      this.queryParams.day_end = now
+      this.handleQuery()
+    })
+  },
+  methods: {
+    // 时间处理
+    onChangeDate(date, dateString) {
+      this.queryParams.day_begin = dateString[0]
+      this.queryParams.day_end = dateString[1]
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.handleQuery()
+    },
+    dateformat(date) {
+      var year = date.getFullYear()
+      var month = date.getMonth() + 1
+      month = month < 10 ? '0' + month : month
+      var strDate = date.getDate()
+      strDate = strDate < 10 ? '0' + strDate : strDate
+      var hour = date.getHours()
+      hour = hour < 10 ? '0' + hour : hour
+      var minute = date.getMinutes()
+      minute = minute < 10 ? '0' + minute : minute
+      var second = date.getSeconds()
+      second = second < 10 ? '0' + second : second
+
+      return year + '-' + month + '-' + strDate + ' ' + hour + ':' + minute + ':' + second
+    },
+    handleQuery() {
+      var _this = this
+      _this.loading = true
+      getAction(this.url.list, _this.queryParams).then((response) => {
+        _this.tpmequiponoffsectionList = response.result
+        // Generate mock data
+        _this.equipments = []
+        _this.onduration = []
+        _this.pauseduration = []
+        _this.offduration = []
+        _this.tpmequiponoffsectionList.forEach(function (equipment, key) {
+          _this.equipments.push(equipment.equipmentid_dictText + '[' + equipment.equipmentcode + ']')
+          _this.onduration.push(equipment.onduration)
+          _this.pauseduration.push(equipment.pauseduration)
+          _this.offduration.push(equipment.offduration)
+        })
+
+        this.loading = false
+
+        this.initEcharts()
+      })
+    },
+    initEcharts() {
+      var _this = this
+      var chartDom = this.$refs.trendCharts
+      var myChart = echarts.init(chartDom)
+      var option
+      var types = [
+        { name: '运行', color: '#75d874' },
+        { name: '待机', color: '#dc77dc' },
+        { name: '停机', color: '#bd6d6c' },
+      ]
+
+      option = {
+        title: {
+          text: '设备运行情况(分钟)',
+          left: 'center',
+        },
+        tooltip: {
+          trigger: 'axis',
+          axisPointer: {
+            type: 'shadow',
+          },
+        },
+        legend: {
+          bottom: 0,
+        },
+        grid: {
+          top: '30px',
+          left: '3%',
+          right: '4%',
+          bottom: '25px',
+          containLabel: true,
+        },
+        xAxis: {
+          type: 'value',
+        },
+        yAxis: {
+          type: 'category',
+          data: _this.equipments,
+        },
+        toolbox: {
+          show: true,
+          feature: {
+            saveAsImage: {},
+          },
+        },
+        series: [
+          {
+            name: types[0].name,
+            type: 'bar',
+            stack: 'total',
+            color: types[0].color,
+            data: _this.onduration,
+          },
+          {
+            name: types[1].name,
+            type: 'bar',
+            stack: 'total',
+            color: types[1].color,
+            data: _this.pauseduration,
+          },
+          {
+            name: types[2].name,
+            type: 'bar',
+            stack: 'total',
+            color: types[2].color,
+            data: _this.offduration,
+          },
+        ],
+      }
+
+      option && myChart.setOption(option)
+
+      window.addEventListener('resize', function () {
+        myChart.resize()
+      })
+    },
+  },
+}
+</script>
+
+<style lang="less" scoped>
+@import '~@/assets/less/uStyle.less';
+</style>
+<style lang="less">
+.trend-charts {
+  padding: 10px;
+  margin-top: 10px;
+  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
+}
+</style>

+ 271 - 0
src/views/module_tpm/equipmentStatus/EquipmentStatusShow.vue

@@ -0,0 +1,271 @@
+<template>
+  <div class="chejian-container">
+    <div class="page-title"></div>
+    <div class="tri-colorLight" ref="flexDivGroup1">
+      <div
+        class="item-content item_content_rad"
+        ref="itemFlexDiv1"
+        v-for="(item, index) in tpmequipmentstatusList1"
+        :key="index"
+        cl
+      >
+        <div class="item-title">{{ item.equipmentname }}</div>
+        <div class="item-title"></div>
+        <div>
+          {{ item.equipmentcode }}
+        </div>
+        <div>当天用电量:{{ item.tagvalue }} kW</div>
+        <br />
+        <div>A相电流:{{ item.tagvalueca }} A | A相电压:{{ item.tagvalueva }} V</div>
+        <div>B相电流:{{ item.tagvaluecb }} A | B相电压:{{ item.tagvaluevb }} V</div>
+        <div>C相电流:{{ item.tagvaluecc }} A | C相电压:{{ item.tagvaluevc }} V</div>
+        <router-link :to="'/equipment/info/detail/' + item.equipmentid">
+          <a-button type="primary" plain icon="search" style="margin-top: 10px">查看详情 </a-button>
+        </router-link>
+      </div>
+    </div>
+    <div class="tri-colorLight" ref="flexDivGroup">
+      <div class="item-content" ref="itemFlexDiv" v-for="(item, index) in tpmequipmentstatusList" :key="index" cl>
+        <div class="item-title">{{ item.equipmentid_dictText }}</div>
+        <div class="item-title"></div>
+        <div>
+          {{ item.equipmentcode }}
+        </div>
+        <div>当天用电量:{{ item.tagvalue }} kW</div>
+        <br />
+        <div>A相电流:{{ item.tagvalueca }} A | A相电压:{{ item.tagvalueva }} V</div>
+        <div>B相电流:{{ item.tagvaluecb }} A | B相电压:{{ item.tagvaluevb }} V</div>
+        <div>C相电流:{{ item.tagvaluecc }} A | C相电压:{{ item.tagvaluevc }} V</div>
+        <!-- <div>功率:{{ item.tagvaluep }} kW·h</div> -->
+        <div class="light-con">
+          <div class="item-light" :class="item.status === '1' ? 'green' : ''"></div>
+          <!-- <div
+            class="item-light"
+            :class="item.status === '2' ? 'yellow' : ''"
+          ></div> -->
+          <div class="item-light" :class="item.status === '3' ? 'red' : ''"></div>
+        </div>
+        <router-link :to="'/equipment/info/detail/' + item.equipmentid">
+          <a-button type="primary" plain icon="search" style="margin-top: 10px">查看详情 </a-button>
+        </router-link>
+      </div>
+      <!-- 优化布局 -->
+      <div ref="completion" v-for="item in completionNumber" :key="'com' + item" class="completion"></div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { httpAction, getAction } from '@/api/manage'
+
+export default {
+  name: 'equipmentStatusShow',
+  data() {
+    return {
+      //设备状态列表
+      tpmequipmentstatusList: [],
+      tpmequipmentstatusList1: [],
+      completionNumber: 0, // 布局使用参数
+      completionNumber1: 0, // 布局使用参数
+      url: {
+        list: '/equipmentStatus/equipmentStatus/getElectricity',
+      },
+    }
+  },
+  created() {
+    this.getList()
+    var _this = this
+    setInterval(function () {
+      _this.getList()
+    }, 60000)
+  },
+  mounted() {
+    // 监听窗口改变设置最后一行布局
+    window.addEventListener('resize', () => {
+      this.WindowOnresize()
+    })
+  },
+  // computed:{
+  //   List(){
+  //     return this.tpmequipmentstatusList.concat(this.tpmequipmentelectricy);
+  //   }
+  // },
+  methods: {
+    //获取设备运行状态
+    getList() {
+      getAction(this.url.list).then((response) => {
+        this.tpmequipmentstatusList1 = []
+        this.tpmequipmentstatusList = []
+        // 拆分数据
+        response.result.forEach((item) => {
+          if (
+            item.equipmentcode == 'M20230061' ||
+            item.equipmentcode == 'M20230062' ||
+            item.equipmentcode == 'M20230064' ||
+            item.equipmentcode == 'M20230063'
+          ) {
+            this.tpmequipmentstatusList1.push(item)
+          } else {
+            this.tpmequipmentstatusList.push(item)
+          }
+        })
+        this.$nextTick(() => {
+          this.WindowOnresize()
+        })
+      })
+    },
+
+    // 设置最后一行布局
+    WindowOnresize() {
+      const equipmentGroupWidth = this.$refs.flexDivGroup.offsetWidth
+      const itemEquipmentList = this.$refs.itemFlexDiv
+      const itemEquipmentCount = itemEquipmentList.length // 现有item数量
+      // console.log("现有的item的数量:--->"+itemEquipmentCount);
+      const itemEquipmentWidth = itemEquipmentList[0].offsetWidth
+      // console.log("宽度:--->"+itemEquipmentWidth);
+      // const itemEquipmentWidth = itemEquipmentList[0].getBoundingClientRect().width + 6;
+      const rowEquipmentCount = parseInt(equipmentGroupWidth / itemEquipmentWidth) // 每一行有几个item
+      // console.log("每一行有几个item:--->"+rowEquipmentCount);
+      const lastItemLenth = itemEquipmentCount % rowEquipmentCount // 最后一行有几个
+      // console.log(equipmentGroupWidth,itemEquipmentWidth, itemEquipmentCount, rowEquipmentCount, lastItemLenth)
+      // console.log("最后一行有几个item:--->"+lastItemLenth);
+      this.completionNumber = lastItemLenth === 0 ? 0 : rowEquipmentCount - lastItemLenth
+      // console.log("需要补上的空白格子的个数:"+this.completionNumber)
+    },
+  },
+}
+</script>
+  
+<style lang="less" scoped>
+@import '~@/assets/less/uStyle.less';
+</style>
+<style lang="less" scoped>
+.chejian-container {
+  width: 100%;
+  // height: 100vh;
+  background-color: #040634;
+  .page-title {
+    height: 20px;
+  }
+  // 三色灯
+  .tri-colorLight {
+    display: flex;
+    justify-content: space-around;
+    align-items: center;
+    flex-wrap: wrap;
+    // width: 20%;
+    .item-container {
+      padding: 10px;
+      box-sizing: border-box;
+    }
+    .item-content {
+      width: 254px;
+      border: 2px solid #314977;
+      color: #63b4ca;
+      // padding: 16px 50px 20px;
+      padding-top: 16px;
+      padding-bottom: 20px;
+      margin: 10px 6px;
+      box-shadow: 0 2px 10px 2px rgba(59, 78, 128, 0.5) inset;
+      text-align: center;
+      box-sizing: border-box;
+      display: flex;
+      flex-direction: column;
+      justify-content: center;
+      align-items: center;
+      .item-title {
+        font-weight: bold;
+      }
+      .light-con {
+        margin-top: 20px;
+        display: flex;
+      }
+      .item-light {
+        width: 20px;
+        height: 20px;
+        border-radius: 100%;
+        margin: 0 15px;
+        background: #7c7ea6;
+      }
+      .green {
+        background-color: #0df708;
+        box-shadow: 0 0 18px 6px rgba(13, 247, 8, 0.5);
+      }
+      .yellow {
+        background-color: #f8fa12;
+        box-shadow: 0 0 18px 6px rgba(248, 250, 18, 0.5);
+      }
+      .red {
+        background-color: #fb0301;
+        box-shadow: 0 0 18px 6px rgba(251, 3, 1, 0.5);
+      }
+    }
+    .item_content_rad {
+      border-radius: 18px;
+    }
+    .completion {
+      width: 254px;
+      margin: 10px 6px;
+    }
+  }
+  // 三色灯
+  .tri-colorLight1 {
+    display: flex;
+    justify-content: space-around;
+    align-items: center;
+    flex-wrap: wrap;
+    // width: 20%;
+    .item-container {
+      padding: 10px;
+      box-sizing: border-box;
+    }
+    .item-content {
+      width: 254px;
+      border: 2px solid #314977;
+      color: #63b4ca;
+      // padding: 16px 50px 20px;
+      padding-top: 16px;
+      padding-bottom: 20px;
+      margin: 10px 6px;
+      box-shadow: 0 2px 10px 2px rgba(59, 78, 128, 0.5) inset;
+      text-align: center;
+      box-sizing: border-box;
+      display: flex;
+      flex-direction: column;
+      justify-content: center;
+      align-items: center;
+      .item-title {
+        font-weight: bold;
+      }
+      .light-con {
+        margin-top: 20px;
+        display: flex;
+      }
+      .item-light {
+        width: 20px;
+        height: 20px;
+        border-radius: 100%;
+        margin: 0 15px;
+        background: #7c7ea6;
+      }
+      .green {
+        background-color: #0df708;
+        box-shadow: 0 0 18px 6px rgba(13, 247, 8, 0.5);
+      }
+      .yellow {
+        background-color: #f8fa12;
+        box-shadow: 0 0 18px 6px rgba(248, 250, 18, 0.5);
+      }
+      .red {
+        background-color: #fb0301;
+        box-shadow: 0 0 18px 6px rgba(251, 3, 1, 0.5);
+      }
+    }
+    .completion {
+      width: 254px;
+      margin: 10px 6px;
+    }
+  }
+}
+</style>
+