chen.cheng 5 mesiacov pred
rodič
commit
4a49c11c62

+ 2 - 2
src/components/Breadcrumb/index.vue

@@ -35,7 +35,7 @@ export default {
       const first = matched[0]
 
       if (!this.isDashboard(first)) {
-        matched = [{ path: '/index', meta: { title: '首页' }}].concat(matched)
+        matched = [{path: '/index', meta: {title: '首页'}}].concat(matched)
       }
 
       this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
@@ -48,7 +48,7 @@ export default {
       return name.trim() === 'Index'
     },
     handleLink(item) {
-      const { redirect, path } = item
+      const {redirect, path} = item
       if (redirect) {
         this.$router.push(redirect)
         return

+ 120 - 0
src/components/charts/BarChartBlock.vue

@@ -0,0 +1,120 @@
+<template>
+  <div class="grid-chart" :id="id">
+
+  </div>
+</template>
+
+<script>
+
+import {copyObj, uuid} from '@/utils';
+import * as echarts from 'echarts';
+
+const basicSerie = {
+  type: 'bar',
+  label: {
+    show: true,
+  },
+  stack: '总量',
+  data: [],
+};
+const opts = {
+  toolbox: {
+    itemGap: 10,
+    itemSize: 16,
+    right: 10,
+    top: 0,
+    show: true,
+    feature: {
+      magicType: {
+        show: true,
+        type: ['bar', 'line']
+      },
+      saveAsImage: {
+        show: true
+      }
+    }
+  },
+  tooltip: {
+    trigger: 'axis',
+    axisPointer: {
+      type: 'shadow',
+    },
+  },
+  legend: {
+    data: [],
+  },
+  grid: {
+    left: '3%',
+    right: '4%',
+    bottom: '3%',
+    containLabel: true,
+  },
+  xAxis: {
+    type: 'category',
+    boundaryGap: true,
+    data: [],
+    axisTick: {
+      alignWithLabel: true,
+    },
+  },
+  yAxis: {
+    type: 'value',
+    minInterval: 1,
+  },
+  series: [],
+};
+export default {
+  props: {
+    title: {
+      default: '标题',
+      type: String,
+    },
+    optCfg: {
+      type: Object,
+      default: () => {
+        return {};
+      },
+    },
+  },
+  watch: {
+    optCfg: {
+      handler(val) {
+        this.initChart();
+      },
+      deep: true,
+    },
+  },
+  data() {
+    return {
+      id: uuid(),
+      refCharts: null,
+    };
+  },
+  mounted() {
+    this.$nextTick(this.initChart);
+  },
+  created() {
+  },
+  methods: {
+    initChart() {
+      this.refCharts && this.refCharts.clear();
+      const chartDom = document.getElementById(this.id);
+      this.refCharts = echarts.init(chartDom);
+      const {series, ...rest} = this.optCfg
+      const option = Object.assign({}, copyObj(opts), rest);
+      const legend = [];
+      series.forEach((item, index) => {
+        const serie = copyObj(basicSerie);
+        Object.assign(serie, item);
+        option.series.push(serie);
+        legend.push(item.name);
+      });
+      option.legend.data = legend;
+      option.xAxis = this.optCfg.xAxis;
+      option && this.refCharts && this.refCharts.setOption(option);
+      this.refCharts.resize();
+    },
+  },
+};
+</script>
+<style src="./index.scss" lang="scss"/>

+ 103 - 0
src/components/charts/LineChartBlock.vue

@@ -0,0 +1,103 @@
+<template>
+  <div class="grid-chart" :id="id">
+
+  </div>
+</template>
+
+<script>
+
+import {copyObj, uuid} from '@/utils';
+import * as echarts from 'echarts';
+
+const basicSerie = {
+  type: 'line',
+};
+const opts = {
+  legend: {
+    top: '5%',
+  },
+  grid: {
+    top: 10,
+    bottom: 20,
+  },
+  tooltip: {
+    show: true,
+    trigger: 'axis',
+  },
+  xAxis: {
+    type: 'category',
+    boundaryGap: false,
+  },
+  yAxis: {
+    type: 'value',
+    name: 'kW·h',
+    minInterval: 1,
+    nameLocation: 'middle',
+    nameTextStyle: {
+      color: '#000',
+      fontSize: '14px',
+      lineHeight: 56,
+    },
+  },
+  series: [],
+};
+export default {
+  props: {
+    title: {
+      default: '标题',
+      type: String,
+    },
+    optCfg: {
+      type: Object,
+      default: () => {
+        return {};
+      },
+    },
+  },
+  watch: {
+    optCfg: {
+      handler(val) {
+        this.initChart();
+      },
+      deep: true,
+    },
+  },
+  data() {
+    return {
+      id: uuid(),
+      refCharts: null,
+    };
+  },
+  mounted() {
+    this.$nextTick(this.initChart);
+  },
+  created() {
+  },
+  methods: {
+    initChart() {
+      this.refCharts && this.refCharts.clear();
+      const chartDom = document.getElementById(this.id);
+      this.refCharts = echarts.init(chartDom);
+      const option = copyObj(opts);
+      const legend = [];
+      this.optCfg.series.forEach((item, index) => {
+        const serie = copyObj(basicSerie);
+        Object.assign(serie, item);
+        const {name} = item;
+        option.series.push(serie);
+        if (name) {
+          legend.push(name);
+        }
+      });
+      option.legend = {
+        data: legend,
+      };
+      option.xAxis = this.optCfg.xAxis;
+      option.yAxis.name = this.optCfg.unit || "kW·h"
+      option && this.refCharts && this.refCharts.setOption(option);
+      this.refCharts.resize();
+    },
+  },
+};
+</script>
+<style src="./index.scss" lang="scss"/>

+ 93 - 0
src/components/charts/PieChartBlock.vue

@@ -0,0 +1,93 @@
+<template>
+  <div class="grid-chart" :id="id">
+
+  </div>
+</template>
+
+<script>
+
+import {copyObj, uuid} from '@/utils';
+import * as echarts from 'echarts';
+
+const basicSerie = {
+  type: 'pie',
+  radius: ['50%', '70%'],
+  center: ['50%', '60%'],
+  data: [],
+};
+const opts = {
+  tooltip: {
+    trigger: 'item',
+  },
+  legend: {
+    top: 0,
+    left: 'center',
+  },
+  emphasis: {
+    itemStyle: {
+      shadowBlur: 10,
+      shadowOffsetX: 0,
+      shadowColor: 'rgba(0, 0, 0, 0.5)'
+    }
+  },
+  label: {
+    show: true,
+    position: 'outside',
+    formatter: '{c}' // 显示名称、值和百分比 {b}: {c} ({d}%)
+  },
+  labelLine: {
+    show: true
+  },
+  series: [],
+};
+export default {
+  props: {
+    title: {
+      default: '标题',
+      type: String,
+    },
+    optCfg: {
+      type: Object,
+      default: () => {
+        return {};
+      },
+    },
+  },
+  watch: {
+    optCfg: {
+      handler(val) {
+        this.initChart();
+      },
+      deep: true,
+    },
+  },
+  data() {
+    return {
+      id: uuid(),
+      refCharts: null,
+    };
+  },
+  mounted() {
+    this.$nextTick(this.initChart);
+  },
+  created() {
+  },
+  methods: {
+    initChart() {
+      this.refCharts && this.refCharts.clear();
+      const chartDom = document.getElementById(this.id);
+      this.refCharts = echarts.init(chartDom);
+      const {series, ...rest} = this.optCfg
+      const option = Object.assign({}, copyObj(opts), rest);
+      series.forEach((item, index) => {
+        const serie = copyObj(basicSerie);
+        Object.assign(serie, item);
+        option.series.push(serie);
+      });
+      option && this.refCharts && this.refCharts.setOption(option);
+      this.refCharts.resize();
+    },
+  },
+};
+</script>
+<style src="./index.scss" lang="scss"/>

+ 9 - 0
src/components/charts/index.scss

@@ -0,0 +1,9 @@
+@import "src/assets/styles";
+
+.grid-content {
+  .grid-chart {
+    flex-grow: 1;
+    width: 100%;
+  }
+}
+

+ 3 - 4
src/views/bd/map/index.vue → src/components/map/index.vue

@@ -24,7 +24,7 @@ export default {
       const options = {
         mapType: BDLayers.Lib.Constant.BaseLayerType.Blank,
         mapModel: BDLayers.Lib.Constant.BaseLayerModel.Satellite,
-        center: [118.8738802982145, 32.010241883966096],
+        center: [103.51, 1.18],
         defaultZoom: 15,
         showCenter: true,
         baseControl: false,
@@ -64,8 +64,7 @@ export default {
               material: { // 如果绘制插件为lit,设置pbr材质
                 baseColorFactor: [0.48235, 0.48235, 0.48235, 1], // 基础色,四位归一化数组
                 hsv: [
-                  0, 0, -
-                      0.532,
+                  0, 0, -0.532,
                 ], // hsv颜色参数,三位分别是hue,saturation,value,即色相,饱和度和明度,每一位的取值范围都是0-1
                 roughnessFactor: 0.22, // 粗糙度,取值范围 0 - 1,0为最光滑,1为最粗糙
                 metallicFactor: 0.58, // 金属度,取值范围 0 - 1,0为非金属,1为金属
@@ -89,7 +88,7 @@ export default {
       this.mapView.addCustomLayers(satelliteTileLayer, -1, true);
       this.mapView.on('click', function (param) {
         console.log(new Date().toLocaleTimeString(),
-            'click map on', param.coordinate.toFixed(5).toArray().join());
+          'click map on', param.coordinate.toFixed(5).toArray().join());
       });
       this.loaded(this.mapView);
     });

+ 0 - 0
src/views/bd/map/maphandle.js → src/components/map/maphandle.js


+ 2 - 2
src/i18n/en.js

@@ -22,8 +22,8 @@ export default {
     outTime: "Your login status has expired. You can continue to stay on this page or log in again."
   },
   menus: {
-    首页: "Home",
-    用户管理: "User manage"
+    "首页": "Home",
+    "用户管理": "User manage"
   },
   error: {
     401: "Authentication failed, unable to access system resources",

+ 2 - 2
src/i18n/zh.js

@@ -39,8 +39,8 @@ export default {
     outTime: "登录状态已过期,您可以继续留在该页面,或者重新登录。"
   },
   menus: {
-    首页: "home page",
-    用户管理: "user manage"
+    "首页": "home page",
+    "用户管理": "user manage"
   },
   error: {
     401: "认证失败,无法访问系统资源",

+ 1 - 0
src/main.js

@@ -44,6 +44,7 @@ import VideoPlayer from 'vue-video-player'
 
 import 'video.js/dist/video-js.css'
 
+import './assets/iconfont/iconfont.css'
 import 'vue-video-player/src/custom-theme.css'
 
 Vue.use(VideoPlayer)

+ 24 - 19
src/router/index.js

@@ -19,12 +19,12 @@ Vue.use(Router)
  * roles: ['admin', 'common']       // 访问路由的角色权限
  * permissions: ['a:a:a', 'b:b:b']  // 访问路由的菜单权限
  * meta : {
-    noCache: true                   // 如果设置为true,则不会被 <keep-alive> 缓存(默认 false)
-    title: 'title'                  // 设置该路由在侧边栏和面包屑中展示的名字
-    icon: 'svg-name'                // 设置该路由的图标,对应路径src/assets/icons/svg
-    breadcrumb: false               // 如果设置为false,则不会在breadcrumb面包屑中显示
-    activeMenu: '/system/user'      // 当路由设置了该属性,则会高亮相对应的侧边栏。
-  }
+ noCache: true                   // 如果设置为true,则不会被 <keep-alive> 缓存(默认 false)
+ title: 'title'                  // 设置该路由在侧边栏和面包屑中展示的名字
+ icon: 'svg-name'                // 设置该路由的图标,对应路径src/assets/icons/svg
+ breadcrumb: false               // 如果设置为false,则不会在breadcrumb面包屑中显示
+ activeMenu: '/system/user'      // 当路由设置了该属性,则会高亮相对应的侧边栏。
+ }
  */
 
 // 公共路由
@@ -45,11 +45,16 @@ export const constantRoutes = [
     component: () => import('@/views/login'),
     hidden: true
   },
-    {
-      path: '/bd',
-      component: () => import('@/views/bd/index'),
-      hidden: true,
-    },
+  {
+    path: '/bd',
+    component: () => import('@/views/bd/index'),
+    hidden: true,
+  },
+  {
+    path: '/digital-screen',
+    component: () => import('@/views/cons/screen/index'),
+    hidden: true,
+  },
   {
     path: '/register',
     component: () => import('@/views/register'),
@@ -74,7 +79,7 @@ export const constantRoutes = [
         path: 'index',
         component: () => import('@/views/index'),
         name: 'Index',
-        meta: { title: '首页', icon: 'dashboard', affix: true }
+        meta: {title: '首页', icon: 'dashboard', affix: true}
       }
     ]
   },
@@ -88,7 +93,7 @@ export const constantRoutes = [
         path: 'profile',
         component: () => import('@/views/system/user/profile/index'),
         name: 'Profile',
-        meta: { title: '个人中心', icon: 'user' }
+        meta: {title: '个人中心', icon: 'user'}
       }
     ]
   }
@@ -106,7 +111,7 @@ export const dynamicRoutes = [
         path: 'role/:userId(\\d+)',
         component: () => import('@/views/system/user/authRole'),
         name: 'AuthRole',
-        meta: { title: '分配角色', activeMenu: '/system/user' }
+        meta: {title: '分配角色', activeMenu: '/system/user'}
       }
     ]
   },
@@ -120,7 +125,7 @@ export const dynamicRoutes = [
         path: 'user/:roleId(\\d+)',
         component: () => import('@/views/system/role/authUser'),
         name: 'AuthUser',
-        meta: { title: '分配用户', activeMenu: '/system/role' }
+        meta: {title: '分配用户', activeMenu: '/system/role'}
       }
     ]
   },
@@ -134,7 +139,7 @@ export const dynamicRoutes = [
         path: 'index/:dictId(\\d+)',
         component: () => import('@/views/system/dict/data'),
         name: 'Data',
-        meta: { title: '字典数据', activeMenu: '/system/dict' }
+        meta: {title: '字典数据', activeMenu: '/system/dict'}
       }
     ]
   },
@@ -148,7 +153,7 @@ export const dynamicRoutes = [
         path: 'index/:jobId(\\d+)',
         component: () => import('@/views/monitor/job/log'),
         name: 'JobLog',
-        meta: { title: '调度日志', activeMenu: '/monitor/job' }
+        meta: {title: '调度日志', activeMenu: '/monitor/job'}
       }
     ]
   },
@@ -162,7 +167,7 @@ export const dynamicRoutes = [
         path: 'index/:tableId(\\d+)',
         component: () => import('@/views/tool/gen/editTable'),
         name: 'GenEdit',
-        meta: { title: '修改生成配置', activeMenu: '/tool/gen' }
+        meta: {title: '修改生成配置', activeMenu: '/tool/gen'}
       }
     ]
   }
@@ -182,6 +187,6 @@ Router.prototype.replace = function push(location) {
 
 export default new Router({
   mode: 'history', // 去掉url中的#
-  scrollBehavior: () => ({ y: 0 }),
+  scrollBehavior: () => ({y: 0}),
   routes: constantRoutes
 })

+ 8 - 0
src/utils/index.js

@@ -19,6 +19,14 @@ export function formatDate(cellValue) {
 export const uuid = () => {
   return UUID.generate();
 };
+/**
+ * 对象浅拷贝,防止嵌套对象的引用还是原来的对象
+ * @param obj
+ * @returns {any}
+ */
+export const copyObj = obj => {
+  return JSON.parse(JSON.stringify(obj));
+};
 
 /**
  * @param {number} time

+ 1 - 1
src/views/bd/fence/index.vue

@@ -84,7 +84,7 @@
 <script>
 
 import {addFenceInfo, listFenceInfo, updateFenceInfo} from '@/api/bd/fenceInfo';
-import maphandle from '@/views/bd/map/maphandle';
+import maphandle from '@/components/map/maphandle';
 import Pannel from '@/views/bd/pannel/index.vue';
 import {FenceType} from "@/utils/BDConst";
 import RoomLayer from "@/views/bd/rooms/index.vue";

+ 1 - 1
src/views/bd/fenceEvt/index.vue

@@ -41,7 +41,7 @@
 import {listFenceInfo} from '@/api/bd/fenceInfo';
 import {listFenceVioEvt} from '@/api/bd/fenceVioEvt';
 import SocketMessage from '@/components/WebsocketMessage/index.vue';
-import maphandle from '@/views/bd/map/maphandle';
+import maphandle from '@/components/map/maphandle';
 import Pannel from '@/views/bd/pannel/index.vue';
 import FingerprintJS from '@fingerprintjs/fingerprintjs';
 import dayjs from 'dayjs';

+ 5 - 5
src/views/bd/index.vue

@@ -5,10 +5,10 @@
     <div class="menus">
       <template v-for="item in Object.keys(menus)">
         <div
-            :key="item"
-            :class="{'menu-item':true,'active': activeMenu[menus[item].name]} "
-            :data-type="item"
-            @click="menuClick"
+          :key="item"
+          :class="{'menu-item':true,'active': activeMenu[menus[item].name]} "
+          :data-type="item"
+          @click="menuClick"
         >
           <svg-icon :icon-class="menus[item].icon"></svg-icon>
           {{ menus[item].title }}
@@ -31,7 +31,7 @@
 import Fence from '@/views/bd/fence/index.vue';
 import FenceVioEvt from '@/views/bd/fenceEvt/index.vue';
 import Location from '@/views/bd/location/index.vue';
-import BdMap from '@/views/bd/map/index.vue';
+import BdMap from '@/components/map';
 import RealtimeLocation from '@/views/bd/realtimeLocation/index.vue';
 import RoomLocation from '@/views/bd/roomlocation/index.vue';
 import menu from '@/views/system/menu/index.vue';

+ 1 - 1
src/views/bd/roomlocation/index.vue

@@ -31,7 +31,7 @@
 
 import SocketMessage from '@/components/WebsocketMessage/index.vue';
 import { uuid } from '@/utils';
-import maphandle from '@/views/bd/map/maphandle';
+import maphandle from '@/components/map/maphandle';
 import Pannel from '@/views/bd/pannel/index.vue';
 import RoomMap from '@/views/bd/roomlocation/roommap/index.vue';
 import dayjs from 'dayjs';

+ 2 - 2
src/views/bd/roomlocation/roommap/index.vue

@@ -21,8 +21,8 @@
 
 import {listFenceInfo, pushDevcLocation} from '@/api/bd/fenceInfo';
 import SocketMessage from '@/components/WebsocketMessage/index.vue';
-import BdMap from '@/views/bd/map/index.vue';
-import maphandle from '@/views/bd/map/maphandle';
+import BdMap from '@/components/map/index.vue';
+import maphandle from '@/components/map/maphandle';
 import position from '@/views/bd/realtimeLocation/icon/position.png';
 import dayjs from 'dayjs';
 import VideoP from "@/views/bd/roomlocation/roommap/video/video.vue";

+ 2 - 2
src/views/bdspace/fenceInfo/draw-fence-dialog.vue

@@ -26,8 +26,8 @@
 
 <script>
 
-import BdMap from '@/views/bd/map/index.vue';
-import maphandle from '@/views/bd/map/maphandle';
+import BdMap from '@/components/map/index.vue';
+import maphandle from '@/components/map/maphandle';
 import dayjs from 'dayjs';
 import {addFenceInfo, updateFenceInfo} from "@/api/bd/fenceInfo";
 // import {uuid} from "@/utils";

+ 46 - 0
src/views/cons/consUnit/ConsUnitTree.vue

@@ -0,0 +1,46 @@
+<template>
+  <treeselect :options="consUnitOptions" :normalizer="normalizer" @input="handleInput"
+              placeholder="选择上级施工单元" :openOnFocus="true"/>
+</template>
+
+<script>
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+import {listConsUnitInfo} from "@/api/cons/consUnitInfo";
+
+export default {
+  name: "cons-unit-tree",
+  dicts: ['cons_unit_type'],
+  components: {Treeselect},
+  data() {
+    return {
+      consUnitOptions: [],
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 查询部门列表 */
+    getList() {
+      listConsUnitInfo({}).then(response => {
+        this.consUnitOptions = this.handleTree(response.rows, "id");
+      });
+    },
+    /** 转换部门数据结构 */
+    normalizer(node) {
+      if (node.children && !node.children.length) {
+        delete node.children;
+      }
+      return {
+        id: node.id,
+        label: node.name,
+        children: node.children
+      };
+    },
+    handleInput(event) {
+      this.$emit('input', event);
+    }
+  }
+};
+</script>

+ 48 - 0
src/views/cons/screen/ContentBlock.vue

@@ -0,0 +1,48 @@
+<template>
+  <div class="block-content">
+    <div class="container-title">
+      {{ title }}
+    </div>
+    <slot name="content"></slot>
+  </div>
+</template>
+
+<script>
+
+export default {
+  name: 'ContentBlock',
+  props: {
+    title: {
+      type: String,
+      default: '',
+    },
+  },
+  computed: {},
+  watch: {},
+};
+</script>
+<style lang="scss" scoped>
+.block-content {
+  padding: 10px 15px;
+  box-sizing: border-box;
+  background: rgba(1, 11, 33, 0.91);
+  border-radius: 6px;
+
+  > :not(:first-child) {
+    margin-top: 20px;
+  }
+
+  .container-title {
+    display: flex;
+    justify-content: left;
+    align-items: center;
+    color: #fefefe;
+    font-family: AlimamaShuHeiTi-Bold;
+    width: 100%;
+    height: 30px;
+    font-size: 14px;
+    background: url("./img/block-header-bg.png") 100% 100% no-repeat;
+    background-size: 100% 100%;
+  }
+}
+</style>

BIN
src/views/cons/screen/img/block-header-bg.png


BIN
src/views/cons/screen/img/screen-title-bg.png


+ 151 - 0
src/views/cons/screen/index.scss

@@ -0,0 +1,151 @@
+.screen-container {
+  position: relative;
+  width: 100%;
+  height: 100%;
+
+
+  .screen-title-container {
+    position: absolute;
+    left: 0;
+    top: 0;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    width: 100%;
+    height: 60px;
+    background: url("./img/screen-title-bg.png") 100% 100% no-repeat;
+    background-size: 100% 100%;
+
+    .title-content {
+      font-family: AlimamaShuHeiTi-Bold;
+      font-weight: 700;
+      font-size: 20px;
+      color: transparent;
+      letter-spacing: 3px;
+      text-align: center;
+      background-image: linear-gradient(to bottom, #fefefe 60%, #4E86AA);
+      -webkit-background-clip: text;
+      margin-bottom: 20px;
+    }
+  }
+
+  .screen-left-container {
+    padding: 10px 15px;
+    box-sizing: border-box;
+    background: rgba(1, 11, 33, 0.91);
+    border-radius: 6px;
+    position: absolute;
+    left: 1vw;
+    width: 23vw;
+    max-height: calc(100vh - 80px);
+    top: 60px;
+
+    > :not(:first-child) {
+      margin-top: 20px;
+    }
+
+    .container-title {
+      display: flex;
+      justify-content: left;
+      align-items: center;
+      color: #fefefe;
+      font-family: AlimamaShuHeiTi-Bold;
+      width: 100%;
+      height: 30px;
+      font-size: 14px;
+      background: url("./img/block-header-bg.png") 100% 100% no-repeat;
+      background-size: 100% 100%;
+
+    }
+
+    .control-content {
+      > :not(:first-child) {
+        margin-top: 5px;
+      }
+
+      .ctl-item {
+        font-size: 12px;
+
+        ::v-deep {
+          .el-input__inner {
+            background: transparent;
+            border: 1px solid #4EBBCD;
+            border-radius: 4px;
+            font-size: 12px;
+            color: #fefefe;
+          }
+
+          .el-input-group__append {
+            background-image: linear-gradient(180deg, #3AA8E9 0%, #4E7ACD 100%);
+            border: none;
+            color: #fefefe;
+          }
+
+          .vue-treeselect__control {
+            background: transparent;
+            border: 1px solid #4EBBCD;
+
+            .vue-treeselect__single-value {
+              color: #fefefe;
+            }
+          }
+        }
+      }
+    }
+
+    .machine-list {
+      box-shadow: inset 0 0 2px 1px #31b9fd66;
+      padding: 10px 10px 20px 10px;
+      box-sizing: border-box;
+
+
+      > div:not(:first-child) {
+        margin-top: 10px;
+      }
+
+      .list-container-title {
+        font-family: PingFangSC-SNaNpxibold;
+        font-weight: 600;
+        font-size: 14px;
+        color: #98CDFB;
+        letter-spacing: 0;
+      }
+
+      .content-list {
+        min-height: 250px;
+        max-height: 65vh;
+        overflow: hidden;
+        overflow-y: scroll;
+        color: #fefefe;
+
+        .list-item {
+          height: 25px;
+          font-size: 12px;
+          display: flex;
+          justify-content: flex-start;
+          align-items: center;
+          padding: 0 5px;
+          box-sizing: border-box;
+          letter-spacing: 1px;
+
+          &:nth-child(odd) {
+            background: #012748;
+          }
+        }
+
+        &::-webkit-scrollbar {
+          display: none;
+        }
+      }
+    }
+
+
+  }
+
+  .screen-right-container {
+    position: absolute;
+    right: 1vw;
+    width: 23vw;
+    top: 60px;
+  }
+}

+ 106 - 0
src/views/cons/screen/index.vue

@@ -0,0 +1,106 @@
+<template>
+  <div class="screen-container">
+    <bd-map :loaded="loaded"/>
+    <div class="screen-title-container"><span class="title-content">Digital Construction Dashboard</span></div>
+    <content-block title="Construction Management" class="screen-left-container">
+      <template v-slot:content>
+        <div class="control-content">
+          <div class="ctl-item">
+            <el-input placeholder="请输入内容" v-model="searchVal" class="input-with-select">
+              <el-button slot="append" icon="el-icon-search"></el-button>
+            </el-input>
+          </div>
+          <div class="ctl-item">
+            <cons-unit-tree v-model="consUnit"/>
+          </div>
+        </div>
+        <div class="machine-list">
+          <div class="list-container-title">
+            Machine List <span v-if="loading" style="font-size: 10px;color: #fefefe;margin-left: 10px">加载中...</span>
+          </div>
+          <div class="content-list infinite-list-wrapper"
+               v-infinite-scroll="load"
+               :infinite-scroll-disabled="disabled"
+          >
+            <div v-for="i in count" class="list-item">machine {{ i }}</div>
+            <p v-if="noMore">没有更多了</p>
+          </div>
+        </div>
+      </template>
+    </content-block>
+
+    <div class="screen-right-container">
+      <content-block title="Online Machinery" class="online-machine-block">
+        <template v-slot:content>
+          <div class="online-summery">
+          </div>
+          <div class="online-list">
+          </div>
+        </template>
+      </content-block>
+    </div>
+  </div>
+</template>
+
+<script>
+import BdMap from "@/components/map/index.vue";
+import Treeselect from "@riophae/vue-treeselect";
+import ConsUnitTree from "@/views/cons/consUnit/ConsUnitTree.vue";
+import ContentBlock from "@/views/cons/screen/ContentBlock.vue";
+
+export default {
+  components: {ContentBlock, ConsUnitTree, BdMap, Treeselect},
+  props: {
+    ws: {
+      type: String,
+      default: '',
+    },
+  },
+  computed: {
+    noMore() {
+      return this.count >= 100
+    },
+    disabled() {
+      return this.loading || this.noMore
+    }
+  },
+  watch: {
+    consUnit(val) {
+      console.log(val)
+    },
+  },
+  data() {
+    return {
+      consUnit: null,
+      searchVal: "",
+      count: 10,
+      loading: false
+    };
+  },
+  // 组件卸载前清空图层信息
+  beforeDestroy() {
+  },
+  created() {
+
+  },
+  mounted() {
+    this.init();
+  },
+  methods: {
+    init() {
+
+    },
+    loaded(map) {
+
+    },
+    load() {
+      this.loading = true
+      setTimeout(() => {
+        this.count += 2
+        this.loading = false
+      }, 2000)
+    }
+  },
+};
+</script>
+<style lang="scss" src="./index.scss" scoped/>

+ 2 - 2
src/views/park/inspectTaskTrail/trail-dialog.vue

@@ -17,8 +17,8 @@
 
 <script>
 
-import BdMap from '@/views/bd/map/index.vue';
-import maphandle from '@/views/bd/map/maphandle';
+import BdMap from '@/components/map/index.vue';
+import maphandle from '@/components/map/maphandle';
 import position from '@/views/bd/realtimeLocation/icon/position.png';
 import dayjs from 'dayjs';
 // import {uuid} from "@/utils";