Browse Source

Merge branch 'master' of bls-dan/busRoute into master

Caner 2 years ago
parent
commit
d7254b8179

+ 10 - 0
src/assets/global-style.scss

@@ -42,4 +42,14 @@
       }
     }
   }
+}
+.n-date-picker{
+  .n-input{
+    background: none !important;
+    border: solid 1px #2185E8;
+   
+    .n-input__input-el{
+      color: #fff;
+    }
+  }
 }

+ 9 - 0
src/assets/img/1-6.svg

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="40px" height="40px" xmlns="http://www.w3.org/2000/svg">
+  <g transform="matrix(1 0 0 1 -91 -13 )">
+    <path d="M 91 13  L 131 13  L 131 53  L 91 53  L 91 13  " fill-rule="nonzero" fill="#cccccc" stroke="none" />
+    <path d="M 94 16  L 128 16  L 128 50  L 94 50  L 94 16  " fill-rule="nonzero" fill="#ffffff" stroke="none" />
+    <path d="M 114.8 25  C 113.12 25  111.8 23.68  111.8 22  C 111.8 20.32  113.12 19  114.8 19  C 116.48 19  117.8 20.32  117.8 22  C 117.8 23.68  116.48 25  114.8 25  " fill-rule="nonzero" fill="#cccccc" stroke="none" />
+    <path d="M 95 49  L 95 31.4  L 103 23.4  L 114.2 29.8  L 120.6 28.2  L 127 29.8  L 127 49  L 95 49  " fill-rule="nonzero" fill="#169bd5" stroke="none" />
+  </g>
+</svg>

+ 2 - 0
src/assets/native-plugin.ts

@@ -7,6 +7,7 @@ import {
   NDataTable,
   NPagination,
   NButton,
+  NInput,
   NSelect,
   NCheckboxGroup,
   NCheckbox,
@@ -22,6 +23,7 @@ const naive = create({
     NDataTable,
     NPagination,
     NButton,
+    NInput,
     NSelect,
     NCheckboxGroup,
     NCheckbox,

+ 55 - 0
src/components/Drag.vue

@@ -0,0 +1,55 @@
+<template>
+  <div
+    class="drag-container "
+    :class="className"
+  >
+    <slot />
+  </div>
+</template>
+
+<script setup lang="ts">
+import {
+  nextTick,
+  ref
+} from 'vue'
+
+const props = withDefaults(defineProps<{
+    domClassName: string,
+}>(), {
+  domClassName: ''
+})
+const className = ref(`drag-${Math.random() * 10000}`)
+nextTick(() => {
+  const dragDom = document.getElementsByClassName(className.value)[0] as HTMLElement
+  if (!dragDom) return
+  const targetDom = dragDom.getElementsByClassName(props.domClassName)[0] as HTMLElement
+  let isDrag = false
+  const mouseDown = (e: any) => {
+    if (!targetDom.contains(e.target)) return
+
+    isDrag = true
+    const X = e.clientX - dragDom.offsetLeft
+    const Y = e.clientY - dragDom.offsetTop
+    const move = (event: MouseEvent) => {
+      event.preventDefault()
+      if (isDrag) {
+        dragDom.style.left = `${event.clientX - X}px`
+        dragDom.style.top = `${event.clientY - Y}px`
+        dragDom.style.right = 'auto'
+      }
+    }
+    document.addEventListener('mousemove', move, false)
+    document.addEventListener('mouseup', () => {
+      isDrag = false
+      document.removeEventListener('mousemove', move)
+    })
+  }
+  dragDom.addEventListener('mousedown', mouseDown)
+})
+</script>
+<style scoped>
+.drag-container {
+  position: fixed !important;
+  z-index: 100;
+}
+</style>

+ 162 - 0
src/components/changeLine.vue

@@ -0,0 +1,162 @@
+<template>
+  <Drag :dom-class-name="'changeLine'">
+    <div class="changeLine">
+      <div class="title">
+        切换线路
+      </div>
+      <div
+        v-show="show"
+        class="content"
+      >
+        <n-input
+          v-model:value="seastr"
+          :bordered="false"
+          round
+          type="text"
+          placeholder="搜索"
+        />
+
+        <div class="list">
+          <div
+            v-for="item in lineList"
+            :key="item.lineId"
+            class="item"
+            :class="{'active': curLine.lineId === item.lineId}"
+            @click="changeLine(item)"
+          >
+            {{ item.lineName }}
+          </div>
+        </div>
+      </div>
+      <div class="footer">
+        <div class="cur">
+          当前:
+        </div>
+        <div> {{ curLine.lineName }}</div>
+      </div>
+      <div
+        class="check"
+        @click="show = !show"
+      >
+        {{ show ? '收起': '展开' }}
+      </div>
+    </div>
+  </Drag>
+</template>
+
+<script lang="ts" setup>
+import NetService from '@/services/net.service'
+import Drag from './Drag.vue'
+import { computed, ref } from 'vue'
+import useStore from '@/pages/store'
+const store = useStore()
+
+const show = ref(false)
+const seastr = ref('')
+const netService = new NetService()
+const originLineList = ref([] as any[])
+
+const lineList = computed(() => originLineList.value.filter((item: any) => item.lineName.includes(seastr.value)))
+
+const curLine = ref({} as any)
+
+function changeLine(item: any) {
+  curLine.value = item
+  store.setCurrentLineId(item.lineId)
+  store.setCurrentLinecode(item.lineCode)
+}
+async function getLine() {
+  const res = await netService.get('/busLine/getList?hasModel=0')
+  if (res.success) {
+    originLineList.value = res.data
+    // eslint-disable-next-line prefer-destructuring
+    curLine.value = res.data[0]
+    store.setCurrentLineId(res.data[0].lineId)
+    store.setCurrentLinecode(res.data[0].lineCode)
+  }
+}
+getLine()
+</script>
+
+<style lang="scss" scoped>
+.changeLine {
+  position: fixed;
+  color: #fff;
+  width: 400px;
+
+  border-radius: 5px;
+  border: 1px solid #1891FF;
+  background: #0F1A31;
+  box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.3137), inset 0px 1px 22px 0px #00BEFF;
+
+  .title {
+    height: 40px;
+    line-height: 40px;
+    text-align: center;
+    background: rgba(33, 133, 232, 0.298);
+  }
+
+  .content {
+    height: 260px;
+
+    .n-input {
+      margin: 10px 15px;
+      width: 370px;
+      background: none !important;
+      border: solid 1.5px #2185E8;
+
+      .n-input__input-el {
+        color: #fff;
+      }
+    }
+
+    .list {
+      height: 200px;
+      overflow-y: scroll;
+    }
+
+    .item {
+      height: 50px;
+      line-height: 50px;
+      text-align: center;
+      border-radius: 4px;
+      box-sizing: border-box;
+
+      &:hover {
+        box-shadow: inset 0px 1px 12px 0px #80FFFF, inset 0px 1px 12px 0px #80FFFF;
+      }
+      &.active {
+        background-color: #346274;
+        border: 1px solid #80FFFF;
+      }
+    }
+  }
+
+  .footer {
+    height: 55px;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    gap: 10px;
+
+    .cur {
+      color: #80FFFF;
+    }
+  }
+
+  .check {
+    position: absolute;
+    top: 0;
+    right: -54px;
+    width: 54px;
+    height: 40px;
+    line-height: 40px;
+    text-align: center;
+    border-radius: 3px;
+    border: 1px solid #1891FF;
+    background: rgba(33, 133, 232, 0.298);
+    cursor: pointer;
+
+  }
+}
+</style>

+ 4 - 4
src/components/selectDate.vue

@@ -18,10 +18,10 @@ const emit = defineEmits<{(evt: 'dateChange', type: number): void
 }>()
 const checkId = ref(1)
 const btns = [
-  { val: 3, label: '总', disabled: true },
-  { val: 2, label: '年', disabled: false },
-  { val: 1, label: '月', disabled: false },
-  { val: 0, label: '日', disabled: true }
+  { val: 4, label: '总', disabled: true },
+  { val: 3, label: '年', disabled: false },
+  { val: 2, label: '月', disabled: false },
+  { val: 1, label: '日', disabled: false }
 ]
 function changeFn(id: number) {
   checkId.value = id

File diff suppressed because it is too large
+ 1 - 1
src/pages/store/index.ts


+ 41 - 17
src/pages/views/home/components/CehicleOperation.vue

@@ -17,7 +17,7 @@
                   style="margin-right: 20px;"
                 />
                 <div class="name bold">
-                  1
+                  {{ store.currentLineCode }}
                 </div>
                 <div class="road">
@@ -215,6 +215,8 @@
                 v-for="item in odds"
                 :key="item.label"
                 class="odd"
+                :class="{ checkd: curOdd === item.key }"
+                @click="curOdd = item.key"
               >
                 {{ item.label }} {{ item.value }}
               </div>
@@ -499,10 +501,13 @@
 import Layout from '@/components/layout.vue'
 import Box from '@/components/box.vue'
 import Echart from '@/components/chart.vue'
-import { computed, ref } from 'vue'
+
+import { computed, ref, watch } from 'vue'
 import { graphic } from 'echarts'
 import CehicleOperationService from '../services/cehicleOperation.service'
+import useStore from '@/pages/store'
 
+const store = useStore()
 const cehicleOperationService = new CehicleOperationService()
 const typeMap :any = {
   0: '干线公交',
@@ -519,15 +524,16 @@ const starlist:any = ref([
   { label: '一星', value: '5' }
 ])
 const odds = ref([
-  { label: '全部', value: '' },
-  { label: '已完成', value: 1 },
-  { label: '执行中', value: 2 },
-  { label: '已处理', value: 3 },
-  { label: '已下发', value: 4 },
-  { label: '待发', value: 5 },
-  { label: '调停', value: 6 },
-  { label: '非运营', value: 7 }
+  { label: '全部', value: '', key: '' },
+  { label: '已完成', value: 1, key: 1 },
+  { label: '执行中', value: 2, key: 2 },
+  { label: '已处理', value: 3, key: 3 },
+  { label: '已下发', value: 4, key: 4 },
+  { label: '待发', value: 5, key: 5 },
+  { label: '调停', value: 6, key: 6 },
+  { label: '非运营', value: 7, key: 7 }
 ])
+const curOdd = ref('' as any)
 function findlabel(arr: any[], val: any) {
   return arr.find((item: { value: any }) => item.value === val)?.label
 }
@@ -922,7 +928,7 @@ const rightContent = ref({
 
   }
 })
-const lineID = '2168405945795840107'
+const currentLineId = computed(() => store.currentLineId)
 
 const busLineData = ref({
   type: '0', // 线路类型
@@ -944,11 +950,11 @@ const busLineData = ref({
 const driverTotal = ref(0)
 const carTotal = ref(0)
 async function getBusLineDetail() {
-  busLineData.value = await cehicleOperationService.getBusLineDetail(lineID)
+  busLineData.value = await cehicleOperationService.getBusLineDetail(currentLineId.value)
 }
 getBusLineDetail()
 async function getBusLineDriver() {
-  const driverArr = await cehicleOperationService.getBusLineDriver(lineID)
+  const driverArr = await cehicleOperationService.getBusLineDriver(currentLineId.value)
   let total = 0
   driverArr.forEach((item: { total: string | number; starType: number }) => {
     total += +item.total
@@ -958,7 +964,7 @@ async function getBusLineDriver() {
 }
 getBusLineDriver()
 async function getBusLineCar() {
-  const carArr = await cehicleOperationService.getBusLineCar(lineID)
+  const carArr = await cehicleOperationService.getBusLineCar(currentLineId.value)
   let total = 0
   carArr.forEach((item: { total: string | number; starType: number }) => {
     total += +item.total
@@ -971,13 +977,26 @@ async function getBusLineCar() {
 getBusLineCar()
 
 async function getBusLineOperate() {
-  const carArr = await cehicleOperationService.getBusLineOperate(lineID)
+  const params = {
+    lineId: currentLineId.value,
+    type: curOdd.value
+  }
+  const carArr = await cehicleOperationService.getBusLineOperate(params)
   upBusLineOperate.value = carArr.filter((item: { direction: number }) => item.direction === 1)
   downBusLineOperate.value = carArr.filter((item: { direction: number }) => item.direction === 2)
-  console.log(carArr, 'carArr')
 }
+watch(() => curOdd.value, () => {
+  getBusLineOperate()
+})
 getBusLineOperate()
 
+watch(() => store.currentLineId, () => {
+  getBusLineOperate()
+  getBusLineCar()
+  getBusLineDriver()
+  getBusLineDetail()
+})
+
 const nameMap:any = {
   1: '老年卡',
   2: '学生卡',
@@ -1062,7 +1081,7 @@ getVehicleStatusService()
           font-size: 18px;
 
           .name {
-            width: 63px;
+            width: 78px;
             height: 74px;
             line-height: 74px;
             text-align: center;
@@ -1502,4 +1521,9 @@ getVehicleStatusService()
   }
 
 }
+.changeLine{
+  position: absolute;
+  top: -100px;
+  z-index: 9999;
+}
 </style>

+ 8 - 8
src/pages/views/home/components/FacilityManagement.vue

@@ -217,35 +217,35 @@ const facilityStatistics = ref({
       {
         name: '车辆',
         type: 'bar',
-        barWidth: '40',
+        barMaxWidth: '40',
         stack: 'total',
         data: [ 10, 52, 200, 334, 390, 330, 220 ]
       },
       {
         name: '电子站牌',
         type: 'bar',
-        barWidth: '40',
+        barMaxWidth: '40',
         stack: 'total',
         data: [ 10, 52, 200, 334, 390, 330, 220 ]
       },
       {
         name: '洗车机',
         type: 'bar',
-        barWidth: '40',
+        barMaxWidth: '40',
         stack: 'total',
         data: [ 10, 52, 200, 334, 390, 330, 220 ]
       },
       {
         name: '充电桩',
         type: 'bar',
-        barWidth: '40',
+        barMaxWidth: '40',
         stack: 'total',
         data: [ 10, 52, 200, 334, 390, 330, 220 ]
       },
       {
         name: '车载部件',
         type: 'bar',
-        barWidth: '40',
+        barMaxWidth: '40',
         stack: 'total',
         data: [ 10, 52, 200, 334, 390, 330, 220 ]
       }
@@ -363,7 +363,7 @@ const carVehicle = ref({
       {
         name: '数量',
         type: 'bar',
-        barWidth: '40',
+        barMaxWidth: '40',
         itemStyle: {
           color: {
             type: 'linear',
@@ -488,7 +488,7 @@ const facilityStation = ref({
       {
         name: '数量',
         type: 'bar',
-        barWidth: '40',
+        barMaxWidth: '40',
         itemStyle: {
           color: {
             type: 'linear',
@@ -784,7 +784,7 @@ const vehicleComponents = ref({
       {
         name: '数量',
         type: 'bar',
-        barWidth: '40',
+        barMaxWidth: '40',
         itemStyle: {
           color: {
             type: 'linear',

+ 330 - 64
src/pages/views/home/components/LineAnalysis.vue

@@ -17,26 +17,43 @@
           class="left-bottom"
           :width="1370"
           :height="818"
-          :name="'近期线路调整'"
+          :name="'近期调整线路'"
         >
           <div class="content">
+            <div class="control">
+              <SelectDate
+                @date-change="selectDatechange"
+              />
+              <n-date-picker
+                v-model:value="lineAdjustData.range"
+                :bordered="false"
+                type="daterange"
+                style="width: 260px;"
+              />
+            </div>
             <div class="content-top">
               <div class="title">
-                <div class="icon" />
+                <icon
+                  :name="'1-6'"
+                  :size="30"
+                />
                 <div>线路调整总览</div>
               </div>
               <div class="overview">
                 <div
-                  v-for="item in leftContent.bData.overview"
-                  :key="item.name"
+                  v-for="item,key in lineAdjustData.overview"
+                  :key="key"
                   class="item"
                 >
-                  <div class="icon" />
+                  <icon
+                    :name="'1-6'"
+                    :size="40"
+                  />
                   <div class="name">
-                    {{ item.name }}
+                    {{ lineAdjustData.map[key] }}
                   </div>
                   <div class="num">
-                    {{ item.value }}
+                    {{ item }}
                   </div>
                 </div>
@@ -44,41 +61,19 @@
             </div>
             <div class="content-bottom">
               <div class="title">
-                <div class="icon" />
+                <icon
+                  :name="'1-6'"
+                  :size="30"
+                />
                 <div>线路调整详情</div>
               </div>
-              <n-table
+              <n-data-table
+                :columns="lineAdjustData.columns"
+                :data="lineAdjustData.tableData"
+                max-height="470"
                 striped
-                size="large"
-                :bordered="false"
-                single-column
-                :bottom-bordered="false"
                 class="table"
-              >
-                <thead>
-                  <tr>
-                    <th> 序号 </th>
-                    <th> 措施 </th>
-                    <th> 区域 </th>
-                    <th> 线路 </th>
-                    <th> 线路类型 </th>
-                    <th> 时间 </th>
-                  </tr>
-                </thead>
-                <tbody>
-                  <tr
-                    v-for="item in 10"
-                    :key="item"
-                  >
-                    <td>  {{ item }} </td>
-                    <td>  调整 </td>
-                    <td>  雨城区 </td>
-                    <td>  1路 </td>
-                    <td>  常规 </td>
-                    <td>  2023-01-01 </td>
-                  </tr>
-                </tbody>
-              </n-table>
+              />
             </div>
           </div>
         </Box>
@@ -104,6 +99,17 @@
           :name="'线路运行速度'"
         >
           <Echart :option="rightContent.center" />
+          <div class="control">
+            <SelectDate
+              @date-change="rankDatechange"
+            />
+            <n-date-picker
+              v-model:value="rankRange"
+              :bordered="false"
+              type="daterange"
+              style="width: 260px;"
+            />
+          </div>
         </Box>
         <Box
           class="right-bottom"
@@ -112,6 +118,17 @@
           :name="'站点客流排名'"
         >
           <Echart :option="rightContent.bottom" />
+          <div class="control">
+            <SelectDate
+              @date-change="stationRankchange"
+            />
+            <n-date-picker
+              v-model:value="stationRankRange"
+              :bordered="false"
+              type="daterange"
+              style="width: 260px;"
+            />
+          </div>
         </Box>
       </div>
     </template>
@@ -122,10 +139,16 @@
 import Layout from '@/components/layout.vue'
 import Box from '@/components/box.vue'
 import Echart from '@/components/chart.vue'
-import { ref } from 'vue'
+import SelectDate from '@/components/selectDate.vue'
+
+import {
+  Ref, h, ref, watch
+} from 'vue'
 import { graphic } from 'echarts'
+import LineAnalysisService from '../services/lineAnalysis.service'
+import { format, subDays } from 'date-fns'
 
-const leftContent = ref({
+const leftContent:Ref<any> = ref({
   tCharts: [
     {
       name: '线路类型',
@@ -307,25 +330,9 @@ const leftContent = ref({
         ]
       }
     }
-  ],
-  bData: {
-    overview: [
-      {
-        name: '新辟线路',
-        value: 10
-      },
-      {
-        name: '撤销线路',
-        value: 10
-      },
-      {
-        name: '调整线路',
-        value: 10
-      }
-    ]
-  }
+  ]
 })
-const rightContent = ref({
+const rightContent:Ref<any> = ref({
   tCharts: [
     {
       name: '线路长度分布',
@@ -371,7 +378,7 @@ const rightContent = ref({
         series: [
           {
             type: 'pie', // 图表类型为饼图
-            radius: [ '55%', '75%' ], // 控制内外圆环的半径,30%代表内圆,60%代表外圆
+            radius: [ '45%', '65%' ], // 控制内外圆环的半径,30%代表内圆,60%代表外圆
             avoidLabelOverlap: true, // 是否启用防止标签重叠策略
             showEmptyCircle: true, // 是否在无数据的时候显示一个占位圆
             label: {
@@ -434,7 +441,7 @@ const rightContent = ref({
         series: [
           {
             type: 'pie', // 图表类型为饼图
-            radius: [ '55%', '75%' ], // 控制内外圆环的半径,30%代表内圆,60%代表外圆
+            radius: [ '45%', '65%' ], // 控制内外圆环的半径,30%代表内圆,60%代表外圆
             avoidLabelOverlap: true, // 是否启用防止标签重叠策略
             showEmptyCircle: true, // 是否在无数据的时候显示一个占位圆
             label: {
@@ -524,7 +531,7 @@ const rightContent = ref({
     }
     ],
     series: [ {
-      name: '当前',
+      name: '常规',
       type: 'line',
       smooth: true,
       symbolSize: 0,
@@ -540,7 +547,7 @@ const rightContent = ref({
       data: [ 120, 132, 101, 134, 90, 230, 210, 182, 191, 234, 290, 330 ]
     },
     {
-      name: '环比',
+      name: '快线',
       type: 'line',
       smooth: true,
       symbolSize: 0,
@@ -556,7 +563,7 @@ const rightContent = ref({
       data: [ 220, 182, 191, 234, 290, 330, 310, 201, 154, 190, 330, 410 ]
     },
     {
-      name: '同比',
+      name: '特色线路',
       type: 'line',
       smooth: true,
       symbolSize: 0,
@@ -577,6 +584,7 @@ const rightContent = ref({
   bottom: {
     grid: {
       containLabel: true,
+      top: '35%',
       right: 30,
       left: 50,
       bottom: 0
@@ -588,7 +596,7 @@ const rightContent = ref({
       }
     },
     legend: {
-      top: 10,
+      top: 70,
       left: '50%',
       itemWidth: 18,
       itemHeight: 18,
@@ -699,6 +707,240 @@ const rightContent = ref({
     ]
   }
 })
+
+const lineAnalysisService = new LineAnalysisService()
+
+async function getAnalysisLineType() {
+  const res = await lineAnalysisService.getAnalysisLineType()
+  leftContent.value.tCharts[0].option.series[0].data = res.map((item:any) => ({
+    name: item.type,
+    value: item.number
+  }))
+}
+getAnalysisLineType()
+
+async function getAnalysisRegionFlow() {
+  const res = await lineAnalysisService.getAnalysisRegionFlow()
+  const yData = []
+  const seriesData = []
+
+  for (let i = 0; i < res.length; i++) {
+    const item = res[i]
+    yData.push(item.region)
+    seriesData.push(item.flow)
+  }
+
+  leftContent.value.tCharts[1].option.yAxis.data = yData
+  leftContent.value.tCharts[1].option.series[0].data = seriesData
+}
+getAnalysisRegionFlow()
+
+const lineAdjustData = ref({
+  range: [ subDays(Date.now(), 7), Date.now() ],
+  type: 4,
+  tableData: [] as any[],
+  columns: [
+    {
+      title: '序号',
+      render: (_: any, rowIndex: number) => h('span', rowIndex + 1)
+    },
+    {
+      title: '措施',
+      key: 'measure',
+      render: (_: any) => h('span', lineAdjustData.value.map[_.measure])
+    },
+    {
+      title: '区域',
+      key: 'region'
+    },
+    {
+      title: '线路',
+      key: 'lineName'
+    },
+    {
+      title: '线路类型',
+      key: 'lineType'
+    },
+    {
+      title: '时间',
+      key: 'time'
+    }
+  ],
+  overview: {
+    // 新辟
+    1: 0,
+    // 撤销
+    2: 0,
+    // 调整
+    3: 0
+  },
+  map: {
+    1: '新辟',
+    2: '撤销',
+    3: '调整'
+  }as any
+})
+async function getAnalysisLineAdjust(params:any) {
+  const res = await lineAnalysisService.getAnalysisLineAdjust(params)
+  let total1 = 0
+  let total2 = 0
+  let total3 = 0
+  for (let i = 0; i < res.length; i++) {
+    const item = res[i]
+    if (item.measure === 1) {
+      total1++
+    }
+    if (item.measure === 2) {
+      total2++
+    }
+    if (item.measure === 3) {
+      total3++
+    }
+  }
+  lineAdjustData.value.overview[1] = total1
+  lineAdjustData.value.overview[2] = total2
+  lineAdjustData.value.overview[3] = total3
+
+  lineAdjustData.value.tableData = res
+}
+
+function selectDatechange(type: number) {
+  lineAdjustData.value.type = type
+  const params = {
+    type: lineAdjustData.value.type
+  }
+  getAnalysisLineAdjust(params)
+}
+watch(() => lineAdjustData.value.range, () => {
+  const params = {
+    startTime: format(lineAdjustData.value.range[0], 'yyyy-MM-dd'),
+    endTime: format(lineAdjustData.value.range[1], 'yyyy-MM-dd')
+  }
+  getAnalysisLineAdjust(params)
+}, { immediate: true })
+
+async function getAnalysisLineLength() {
+  const res = await lineAnalysisService.getAnalysisLineLength()
+  const seriesData = []
+  let total = 0
+
+  for (let i = 0; i < res.length; i++) {
+    const item = res[i]
+    seriesData.push({
+      name: item.lengthType,
+      value: item.proportion
+    })
+    total += +item.proportion
+  }
+  rightContent.value.tCharts[0].option.series[0].data = seriesData
+  rightContent.value.tCharts[0].option.title.subtext = total
+}
+getAnalysisLineLength()
+
+async function getAnalysisLineDistance() {
+  const res = await lineAnalysisService.getAnalysisLineDistance()
+  const seriesData = []
+  let total = 0
+
+  for (let i = 0; i < res.length; i++) {
+    const item = res[i]
+    seriesData.push({
+      name: item.distanceType,
+      value: item.proportion
+    })
+    total += +item.proportion
+  }
+  rightContent.value.tCharts[1].option.series[0].data = seriesData
+  rightContent.value.tCharts[1].option.title.subtext = total
+}
+getAnalysisLineDistance()
+
+const rankRange = ref([ subDays(Date.now(), 7), Date.now() ])
+async function getAnalysisLineOperate(params:any) {
+  const res = await lineAnalysisService.getAnalysisLineOperate(params)
+
+  const xAxisData = []
+  const seriesData1 = []
+  const seriesData2 = []
+  const seriesData3 = []
+
+  for (let i = 0; i < res.length; i++) {
+    const item = res[i]
+    xAxisData.push(item.time)
+    seriesData1.push(item.conventionLine)
+    seriesData2.push(item.expressLine)
+    seriesData3.push(item.characteristicLine)
+  }
+
+  rightContent.value.center.xAxis[0].data = xAxisData
+  rightContent.value.center.series[0].data = seriesData1
+  rightContent.value.center.series[1].data = seriesData2
+  rightContent.value.center.series[2].data = seriesData3
+}
+
+function rankDatechange(type: number) {
+  const params = {
+    type
+  }
+  getAnalysisLineOperate(params)
+}
+watch(() => rankRange.value, () => {
+  const params = {
+    startTime: format(rankRange.value[0], 'yyyy-MM-dd'),
+    endTime: format(rankRange.value[1], 'yyyy-MM-dd')
+  }
+  getAnalysisLineOperate(params)
+}, { immediate: true })
+
+const stationRankRange = ref([ subDays(Date.now(), 7), Date.now() ])
+async function getAnalysisStationRank(params:any) {
+  const res = await lineAnalysisService.getAnalysisStationRank(params)
+  const groupData = groupBy(res, 'stationName')
+  console.log(groupData, 'groupData')
+  const xAxisData = []
+  const seriesData1 = []
+
+  for (const key in groupData) {
+    const item = groupData[key]
+    xAxisData.push(key)
+    const total = item.reduce((prev: any, item: { flow: number }) => {
+      prev += item.flow
+      return prev
+    }, 0)
+    seriesData1.push(total)
+  }
+
+  rightContent.value.bottom.xAxis.data = xAxisData
+  rightContent.value.bottom.series[0].data = seriesData1
+}
+
+function stationRankchange(type: number) {
+  const params = {
+    type
+  }
+  getAnalysisStationRank(params)
+}
+watch(() => stationRankRange.value, () => {
+  const params = {
+    startTime: format(stationRankRange.value[0], 'yyyy-MM-dd HH:mm:ss'),
+    endTime: format(stationRankRange.value[1], 'yyyy-MM-dd HH:mm:ss')
+  }
+  getAnalysisStationRank(params)
+}, { immediate: true })
+
+function groupBy(array: any[], id: string) {
+  const groups:any = {}
+  array.forEach((o) => {
+    let group = JSON.stringify(o[id])
+    if (typeof o[id] === 'string') {
+      group = o[id]
+    }
+    groups[group] = groups[group] || []
+    groups[group].push(o)
+  })
+  // return Object.values(groups);
+  return groups
+}
 </script>
 
 <style lang="scss" scoped>
@@ -712,6 +954,7 @@ const rightContent = ref({
     .content {
       width: 100%;
       padding: 35px;
+      position: relative;
 
       .title {
         display: flex;
@@ -759,10 +1002,21 @@ const rightContent = ref({
       .table{
           margin-top: 30px;
           text-align: center;
+          font-size: 16px;
           th{
             border: 0;
           }
         }
+
+        .control{
+          position: absolute;
+          top: 30px;
+          right: 125px;
+          .selectDate{
+            top: 0px;
+            left: -300px;
+          }
+        }
     }
 
   }
@@ -772,5 +1026,17 @@ const rightContent = ref({
     display: flex;
     justify-content: space-between;
   }
+  &-center,&-bottom {
+    position: relative;
+    .control{
+          position: absolute;
+          top: 60px;
+          right: 110px;
+          .selectDate{
+            top: 0px;
+            left: -300px;
+          }
+        }
+  }
 }
 </style>

+ 1 - 0
src/pages/views/home/components/MaintenanceDynamics.vue

@@ -50,6 +50,7 @@
         <n-date-picker
           v-model:value="leftContent.bottom.range"
           type="daterange"
+          :bordered="false"
           style="width: 260px;"
         />
 

+ 409 - 301
src/pages/views/home/components/StationManagement.vue

@@ -5,7 +5,7 @@
         <Box
           :width="665"
           :height="396"
-          :name="'安全行驶'"
+          :name="'区域分布'"
           style="margin-bottom: 25px;"
         >
           <div class="body">
@@ -14,10 +14,10 @@
                 src="../../../../assets/img/1-1.png"
                 alt=""
               >
-              <p>40</p>
+              <p>{{ region.total }}</p>
               <div>总量</div>
             </div>
-            <Echart :option="option" />
+            <Echart :option="region.option" />
           </div>
         </Box>
         <Box
@@ -34,7 +34,7 @@
               class="text"
             >
               站场总数
-              <p>100</p>
+              <p>{{ typeTotal }}</p>
             </div>
             <Echart
               v-if="item.option"
@@ -48,35 +48,19 @@
           :name="'使用情况'"
         >
           <div class="usage">
-            <div class="list">
-              <img
-                src="../../../../assets/img/1-1.png"
-                alt=""
-              >
-              <div class="value">
-                0
-              </div>
-              <p>规划</p>
-            </div>
-            <div class="list">
-              <img
-                src="../../../../assets/img/1-1.png"
-                alt=""
-              >
-              <div class="value">
-                0
-              </div>
-              <p>在建</p>
-            </div>
-            <div class="list">
+            <div
+              v-for="item, index in useData"
+              :key="index"
+              class="list"
+            >
               <img
                 src="../../../../assets/img/1-1.png"
                 alt=""
               >
               <div class="value">
-                0
+                {{ item.number }}
               </div>
-              <p>使用</p>
+              <p> {{ item.useType }}</p>
             </div>
           </div>
         </Box>
@@ -91,63 +75,36 @@
           style="margin-bottom: 23px;"
         >
           <div class="commercial">
-            <div class="commercial-vehicles">
-              <div class="title">
-                营运车
-              </div>
-              <div class="top">
-                <div class="list">
-                  <div>100 <span>辆/次</span></div>
-                  <p>进场车次</p>
-                </div>
-                <div class="list">
-                  <div>100 <span>辆/次</span></div>
-                  <p>出场车次</p>
-                </div>
-                <div class="list">
-                  <div>100 <span>辆/次</span></div>
-                  <p>泊车车次</p>
-                </div>
-              </div>
-              <div class="bottom">
-                <div class="list">
-                  <div>100 <span>辆/次</span></div>
-                  <p>凌晨两点泊车</p>
-                </div>
-                <div class="list">
-                  <div style="color: #E73D41;">
-                    100 <span>辆/次</span>
-                  </div>
-                  <p>长期滞留车辆(大于7天)</p>
-                </div>
-              </div>
-            </div>
-            <div class="commercial-vehicles">
+            <div
+              v-for="item in operateData"
+              :key="item.type"
+              class="commercial-vehicles"
+            >
               <div class="title">
-                非营运车
+                {{ item.type === 1 ? '营运车' : '非营运车' }}
               </div>
               <div class="top">
                 <div class="list">
-                  <div>100 <span>辆/次</span></div>
+                  <div>{{ item.inNum }} <span>辆/次</span></div>
                   <p>进场车次</p>
                 </div>
                 <div class="list">
-                  <div>100 <span>辆/次</span></div>
+                  <div>{{ item.outNum }} <span>辆/次</span></div>
                   <p>出场车次</p>
                 </div>
                 <div class="list">
-                  <div>100 <span>辆/次</span></div>
+                  <div>{{ item.parkingNum }} <span>辆/次</span></div>
                   <p>泊车车次</p>
                 </div>
               </div>
               <div class="bottom">
                 <div class="list">
-                  <div>100 <span>辆/次</span></div>
+                  <div>{{ item.amParkingNum }} <span>辆/次</span></div>
                   <p>凌晨两点泊车</p>
                 </div>
                 <div class="list">
                   <div style="color: #E73D41;">
-                    100 <span>辆/次</span>
+                    {{ item.retentionNum }} <span>辆/次</span>
                   </div>
                   <p>长期滞留车辆(大于7天)</p>
                 </div>
@@ -178,7 +135,7 @@
             <div class="airport">
               <div class="text">
                 站场总数
-                <p>100</p>
+                <p>{{ installedCapacityTotal }}</p>
               </div>
               <Echart :option="airportChart" />
             </div>
@@ -192,16 +149,16 @@
           >
             <ul class="hd">
               <li
-                v-for="item in 4"
-                :key="item"
+                v-for="item, index in chargingStatus"
+                :key="index"
               >
                 <img
                   src="../../../../assets/img/1-1.png"
                   alt=""
                 >
                 <div class="txt">
-                  <p>100</p>
-                  <div>进厂车次</div>
+                  <p>{{ item.number }}</p>
+                  <div>{{ item.chargingStatus }}</div>
                 </div>
               </li>
             </ul>
@@ -209,11 +166,13 @@
               <li>
                 <div class="tt">
                   <p>今日充电车次</p>
-                  <div>73 <span>/100</span> </div>
+                  <div>
+                    {{ chargingStatistics.chargingNum }} <span> /{{ chargingStatistics.totalChargingNum }}</span>
+                  </div>
                 </div>
                 <n-progress
                   type="line"
-                  :percentage="60"
+                  :percentage="(chargingStatistics.chargingNum / chargingStatistics.totalChargingNum * 100).toFixed(2)"
                   :show-indicator="false"
                   :indicator-placement="'inside'"
                   processing
@@ -223,11 +182,13 @@
               <li>
                 <div class="tt">
                   <p>今日充电电量 kw.h</p>
-                  <div>73 <span>/100</span> </div>
+                  <div>
+                    {{ chargingStatistics.electricityNum }} <span> /{{ chargingStatistics.totalElectricityNum }}</span>
+                  </div>
                 </div>
                 <n-progress
                   type="line"
-                  :percentage="60"
+                  :percentage="(chargingStatistics.electricityNum / chargingStatistics.totalElectricityNum * 100).toFixed(2)"
                   :show-indicator="false"
                   :indicator-placement="'inside'"
                   processing
@@ -242,14 +203,18 @@
             :name="'资源使用率'"
           >
             <ul class="btn">
-              <li>各场站入场率</li>
-              <li>各充电场站充电量</li>
-              <li>各维保场维修保养车辆数</li>
-              <li>运维驿站使用率</li>
+              <li
+                v-for="item,key in typeMap"
+                :key="key"
+                :class="{active:type === key}"
+                @click="type = key"
+              >
+                {{ item }}
+              </li>
             </ul>
             <n-data-table
               :columns="columns"
-              :data="data"
+              :data="tableData"
               max-height="200"
             />
           </Box>
@@ -262,9 +227,12 @@
 <script setup lang='ts'>
 import Layout from '@/components/layout.vue'
 import Box from '@/components/box.vue'
-import { ref } from 'vue'
+import {
+  Ref, computed, h, ref
+} from 'vue'
 import Echart from '@/components/chart.vue'
-const leftTitle = [ {
+import StationManagementService from '../services/stationManagement.service'
+const leftTitle: Ref<any[]> = ref([ {
   name: '类型分布',
   option: {
     color: [ 'rgb(86,137,239)', 'rgb(85,206,160)', 'rgb(88,107,141)', 'rgb(234,181,23)' ],
@@ -280,28 +248,25 @@ const leftTitle = [ {
         fontSize: 16
       }
     },
-    series: [
-      {
-        type: 'pie',
-        radius: [ '55%', '75%' ],
-        label: {
-          show: true,
-          color: '#fff',
-          formatter: '{b}: {c}个',
-          fontSize: 14
-        },
-        data: [
-          { value: 1048, name: '首末班' },
-          { value: 735, name: '枢纽站' },
-          { value: 580, name: '停车场' },
-          { value: 580, name: '保养场' }
-
-        ]
-
-      }
-    ]
+    series: {
+      type: 'pie',
+      radius: [ '55%', '75%' ],
+      label: {
+        show: true,
+        color: '#fff',
+        formatter: '{b}: {c}个',
+        fontSize: 14
+      },
+      data: [
+        { value: 1048, name: '首末班' },
+        { value: 735, name: '枢纽站' },
+        { value: 580, name: '停车场' },
+        { value: 580, name: '保养场' }
+      ]
+    }
   }
-}, {
+},
+{
   name: '面积分布',
   option: {
     color: [ 'rgb(86,137,239)', 'rgb(85,206,160)', 'rgb(88,107,141)', 'rgb(234,181,23)' ],
@@ -317,29 +282,26 @@ const leftTitle = [ {
         fontSize: 16
       }
     },
-    series: [
-      {
-        type: 'pie',
-        radius: '70%',
-        label: {
-          show: true,
-          color: '#fff',
-          formatter: '{b}: {c}个',
-          fontSize: 14
-        },
-        data: [
-          { value: 1048, name: '<=500m' },
-          { value: 735, name: '500~2000' },
-          { value: 580, name: '2000~5000' },
-          { value: 580, name: '5000~10000' }
-
-        ]
-
-      }
-    ]
+    series: {
+      type: 'pie',
+      radius: '70%',
+      label: {
+        show: true,
+        color: '#fff',
+        formatter: '{b}: {c}个',
+        fontSize: 14
+      },
+      data: [
+        { value: 1048, name: '<=500㎡' },
+        { value: 735, name: '500~2000㎡' },
+        { value: 580, name: '2000~5000㎡' },
+        { value: 580, name: '5000~10000㎡' }
+      ]
+    }
   }
-}, {
-  name: '战场权属分布',
+},
+{
+  name: '场站权属情况',
   option: {
     color: [ 'rgb(86,137,239)', 'rgb(85,206,160)', 'rgb(88,107,141)', 'rgb(234,181,23)' ],
     tooltip: {
@@ -354,31 +316,27 @@ const leftTitle = [ {
         fontSize: 16
       }
     },
-    series: [
-      {
-        type: 'pie',
-        radius: '70%',
-        label: {
-          show: true,
-          color: '#fff',
-          formatter: '{b}: {c}个',
-          fontSize: 14
-        },
-        data: [
-          { value: 1048, name: '自有' },
-          { value: 735, name: '临时使用' },
-          { value: 580, name: '先借后租' },
-          { value: 580, name: '租用' }
-
-        ]
-
-      }
-    ]
+    series: {
+      type: 'pie',
+      radius: '70%',
+      label: {
+        show: true,
+        color: '#fff',
+        formatter: '{b}: {c}个',
+        fontSize: 14
+      },
+      data: [
+        { value: 1048, name: '自有' },
+        { value: 735, name: '临时使用' },
+        { value: 580, name: '先借后租' },
+        { value: 580, name: '租用' }
+      ]
+    }
   }
-}, {
+},
+{
   name: '建设时间',
   option: {
-
     tooltip: {
       trigger: 'axis',
       axisPointer: {
@@ -396,94 +354,84 @@ const leftTitle = [ {
       textStyle: {
         color: '#fff'
       }
+    },
+    xAxis: {
+      type: 'category',
+      data: [ '超过十年', '5-7年', '近3年', '3-5年' ],
+      axisLabel: {
+        color: '#fff',
 
+        fontSize: 16
+      },
+      axisTick: {
+        alignWithLabel: true
+      },
+      splitLine: {
+        show: false
+      }
     },
-    xAxis: [
-      {
-        type: 'category',
-        data: [ '超过十年', '5-7年', '近3年', '3-5年' ],
-        axisLabel: {
-          color: '#fff',
-
-          fontSize: 16
-        },
-        axisTick: {
-          alignWithLabel: true
-        },
-        splitLine: {
-          show: false
+    yAxis: {
+      type: 'value',
+      axisLabel: {
+        color: '#fff'
+      },
+      splitLine: {
+        show: true,
+        lineStyle: {
+          color: 'rgb(34,43,57)'
         }
       }
-    ],
-    yAxis: [
-      {
-        type: 'value',
-        axisLabel: {
-          color: '#fff'
-        },
-        splitLine: {
-          show: true,
-          lineStyle: {
-            color: 'rgb(34,43,57)'
-          }
+    },
+    series: {
+      name: '数量',
+      type: 'bar',
+      barMaxWidth: '40',
+      itemStyle: {
+        color: {
+          type: 'linear',
+          x: 0,
+          y: 0,
+          x2: 0,
+          y2: 1,
+          colorStops: [ {
+            offset: 0, color: '#00fdff' // 0% 处的颜色
+          }, {
+            offset: 1, color: '#00aaff08' // 100% 处的颜色
+          } ],
+          global: false // 缺省为 false
         }
-      }
-    ],
-    series: [
-      {
-        name: '数量',
-        type: 'bar',
-        barWidth: '40%',
-        itemStyle: {
-          color: {
-            type: 'linear',
-            x: 0,
-            y: 0,
-            x2: 0,
-            y2: 1,
-            colorStops: [ {
-              offset: 0, color: '#00fdff' // 0% 处的颜色
-            }, {
-              offset: 1, color: '#00aaff08' // 100% 处的颜色
-            } ],
-            global: false // 缺省为 false
-          }
-        },
-        data: [ 10, 52, 200, 334, 390, 330, 220 ]
-      }
-
-    ]
+      },
+      data: [ 10, 52, 200, 334, 390, 330, 220 ]
+    }
   }
-} ]
+} ])
 // 区域分布
-const option = {
-
-  tooltip: {
-    trigger: 'axis',
-    axisPointer: {
-      type: 'shadow'
-    }
-  },
-  grid: {
-    left: '1%',
-    right: '4%',
-    bottom: '3%',
-    containLabel: true
-  },
-  legend: {
-    show: false,
-    textStyle: {
-      color: '#fff'
-    }
-
-  },
-  yAxis: [
-    {
+const region = ref({
+  total: 40,
+  option: {
+    tooltip: {
+      trigger: 'axis',
+      axisPointer: {
+        type: 'shadow'
+      }
+    },
+    grid: {
+      left: '1%',
+      right: '4%',
+      bottom: '3%',
+      containLabel: true
+    },
+    legend: {
+      show: false,
+      textStyle: {
+        color: '#fff'
+      }
+    },
+    yAxis: {
       type: 'category',
       data: [ '吊挂式', '独立式', '嵌入式' ],
       axisLabel: {
         color: '#fff',
-
         fontSize: 16
       },
       axisTick: {
@@ -492,10 +440,8 @@ const option = {
       splitLine: {
         show: false
       }
-    }
-  ],
-  xAxis: [
-    {
+    },
+    xAxis: {
       type: 'value',
       axisLabel: {
         color: '#fff'
@@ -507,13 +453,11 @@ const option = {
           color: 'rgb(34,43,57)'
         }
       }
-    }
-  ],
-  series: [
-    {
+    },
+    series: {
       name: '数量',
       type: 'bar',
-      barWidth: '40%',
+      barMaxWidth: '40',
       itemStyle: {
         color: 'rgb(86,137,239)',
         barBorderRadius: [ 0, 20, 20, 0 ]
@@ -525,10 +469,10 @@ const option = {
       },
       data: [ 10, 52, 200, 334, 390, 330, 220 ]
     }
+  }
+})
 
-  ]
-}
-const powerChart = {
+const powerChart = ref({
   tooltip: {
     trigger: 'axis'
   },
@@ -537,7 +481,6 @@ const powerChart = {
     boundaryGap: false,
     axisLabel: {
       color: '#fff',
-
       fontSize: 16
     },
     data: [ 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun' ]
@@ -560,31 +503,29 @@ const powerChart = {
     show: true,
     type: 'slider'
   },
-  series: [
-    {
-      data: [ 820, 932, 901, 934, 1290, 1330, 1320 ],
-      type: 'line',
-      areaStyle: {
-        color: {
-          type: 'linear',
-          x: 0,
-          y: 0,
-          x2: 0,
-          y2: 1,
-          colorStops: [ {
-            offset: 0, color: '#FFD35D ' // 0% 处的颜色
-          }, {
-            offset: 0.5, color: '#7ec2f3 ' // 100% 处的颜色
-          }, {
-            offset: 1, color: '#1890ff ' // 100% 处的颜色
-          } ],
-          global: false // 缺省为 false
-        }
+  series: {
+    data: [ 820, 932, 901, 934, 1290, 1330, 1320 ],
+    type: 'line',
+    areaStyle: {
+      color: {
+        type: 'linear',
+        x: 0,
+        y: 0,
+        x2: 0,
+        y2: 1,
+        colorStops: [ {
+          offset: 0, color: '#FFD35D ' // 0% 处的颜色
+        }, {
+          offset: 0.5, color: '#7ec2f3 ' // 100% 处的颜色
+        }, {
+          offset: 1, color: '#1890ff ' // 100% 处的颜色
+        } ],
+        global: false // 缺省为 false
       }
     }
-  ]
-}
-const airportChart = {
+  }
+})
+const airportChart = ref({
   color: [ 'rgb(86,137,239)', 'rgb(85,206,160)', 'rgb(88,107,141)', 'rgb(234,181,23)' ],
   tooltip: {
     trigger: 'item'
@@ -598,50 +539,213 @@ const airportChart = {
       fontSize: 16
     }
   },
-  series: [
-    {
-      type: 'pie',
-      radius: [ '55%', '75%' ],
-      label: {
-        show: true,
-        color: '#fff',
-        formatter: '{b}: {c}个',
-        fontSize: 14
-      },
-      data: [
-        { value: 1048, name: '<=500m' },
-        { value: 735, name: '500~2000' },
-        { value: 580, name: '2000~5000' },
-        { value: 580, name: '5000~10000' }
+  series: {
+    type: 'pie',
+    radius: [ '55%', '75%' ],
+    label: {
+      show: true,
+      color: '#fff',
+      formatter: '{b}: {c}个',
+      fontSize: 14
+    },
+    data: [
+      { value: 1048, name: '<=500m' },
+      { value: 735, name: '500~2000' },
+      { value: 580, name: '2000~5000' },
+      { value: 580, name: '5000~10000' }
 
-      ]
+    ]
 
-    }
-  ]
+  }
+})
+const originData = ref([ {
+  admissionRate: 0,
+  stationName: 'xxx'
+} ])
+const type = ref('admissionRate')
+const typeMap = {
+  admissionRate: '各场站入场率',
+  chargingCapacity: '各充电场站充电量',
+  maintenanceNum: '各维保场维修保养车辆数',
+  usageRate: '运维驿站使用率'
 }
-const data = [
-  { no: 3, title: 'Wonderwall', length: '4:18' },
-  { no: 4, title: "Don't Look Back in Anger", length: '4:48' },
-  { no: 12, title: 'Champagne Supernova', length: '7:27' },
-  { no: 12, title: 'Champagne Supernova', length: '7:27' },
-  { no: 12, title: 'Champagne Supernova', length: '7:27' },
-  { no: 12, title: 'Champagne Supernova', length: '7:27' },
-  { no: 12, title: 'Champagne Supernova', length: '7:27' },
-  { no: 12, title: 'Champagne Supernova', length: '7:27' },
-  { no: 12, title: 'Champagne Supernova', length: '7:27' },
-  { no: 12, title: 'Champagne Supernova', length: '7:27' },
-  { no: 12, title: 'Champagne Supernova', length: '7:27' }
-]
-const columns = [ {
-  title: '序号',
-  key: 'no'
-}, {
-  title: '场站',
-  key: 'title'
-}, {
-  title: '入场率',
-  key: 'length'
-} ]
+const tableData = computed(() => originData.value.map((item:any) => ({
+  stationName: item.stationName,
+  rate: item[type.value]
+})))
+const columns = [
+  {
+    title: '序号',
+    render: (_: any, rowIndex: number) => h('span', rowIndex + 1)
+  },
+  {
+    title: '场站',
+    key: 'stationName'
+  },
+  {
+    title: '入场率',
+    key: 'rate'
+  } ]
+
+const stationManagementService = new StationManagementService()
+
+async function getStationRegion() {
+  const res = await stationManagementService.getStationRegion()
+  const yData = []
+  const seriesData = []
+  let total = 0
+
+  for (let i = 0; i < res.length; i++) {
+    const item = res[i]
+    yData.push(item.region)
+    seriesData.push(item.passengerFlow)
+    total += item.passengerFlow
+  }
+
+  region.value.option.yAxis.data = yData
+  region.value.option.series.data = seriesData
+  region.value.total = total
+}
+getStationRegion()
+
+const typeTotal = ref(0)
+async function getStationTypes() {
+  const res = await stationManagementService.getStationTypes()
+  const seriesData = []
+  let total = 0
+
+  for (let i = 0; i < res.length; i++) {
+    const item = res[i]
+    seriesData.push({
+      name: item.type,
+      value: item.number
+    })
+    total += item.number
+  }
+  leftTitle.value[0].option.series.data = seriesData
+  typeTotal.value = total
+}
+getStationTypes()
+async function getStationArea() {
+  const res = await stationManagementService.getStationArea()
+  const seriesData = []
+  let total = 0
+
+  for (let i = 0; i < res.length; i++) {
+    const item = res[i]
+    seriesData.push({
+      name: item.areaType,
+      value: item.number
+    })
+    total += item.number
+  }
+  leftTitle.value[1].option.series.data = seriesData
+  typeTotal.value = total
+}
+getStationArea()
+async function getStationOwnership() {
+  const res = await stationManagementService.getStationOwnership()
+  const seriesData = []
+  let total = 0
+
+  for (let i = 0; i < res.length; i++) {
+    const item = res[i]
+    seriesData.push({
+      name: item.ownership,
+      value: item.number
+    })
+    total += item.number
+  }
+  leftTitle.value[2].option.series.data = seriesData
+  typeTotal.value = total
+}
+getStationOwnership()
+async function getStationConstruct() {
+  const res = await stationManagementService.getStationConstruct()
+  const xData = []
+  const seriesData = []
+
+  for (let i = 0; i < res.length; i++) {
+    const item = res[i]
+    xData.push(item.constructSituation)
+    seriesData.push(item.number)
+  }
+  leftTitle.value[3].option.xAxis.data = seriesData
+  leftTitle.value[3].option.series.data = seriesData
+}
+getStationConstruct()
+
+const useData = ref([] as any[])
+async function getStationUse() {
+  useData.value = await stationManagementService.getStationUse()
+}
+getStationUse()
+
+const operateData = ref([] as any[])
+async function getStationOperate() {
+  operateData.value = await stationManagementService.getStationOperate()
+}
+getStationOperate()
+
+async function getStationChargingTrends() {
+  const res = await stationManagementService.getStationChargingTrends()
+  const xData = []
+  const seriesData = []
+
+  for (let i = 0; i < res.length; i++) {
+    const item = res[i]
+    xData.push(item.time.slice(11))
+    seriesData.push(item.number)
+  }
+  powerChart.value.xAxis.data = xData
+  powerChart.value.series.data = seriesData
+}
+getStationChargingTrends()
+
+const installedCapacityTotal = ref(0)
+async function getStationInstalledCapacity() {
+  const res = await stationManagementService.getStationInstalledCapacity()
+  const seriesData = []
+  let total = 0
+
+  for (let i = 0; i < res.length; i++) {
+    const item = res[i]
+    seriesData.push({
+      name: item.type,
+      value: item.number
+    })
+    total += item.number
+  }
+  airportChart.value.series.data = seriesData
+  installedCapacityTotal.value = total
+}
+getStationInstalledCapacity()
+
+const chargingStatus = ref([
+  { chargingStatus: '空闲', number: 0 },
+  { chargingStatus: '充满', number: 0 },
+  { chargingStatus: '在充', number: 0 },
+  { chargingStatus: '故障', number: 0 }
+])
+async function getStationChargingStatus() {
+  const res = await stationManagementService.getStationChargingStatus()
+}
+getStationChargingStatus()
+
+const chargingStatistics = ref({
+  chargingNum: 1,
+  totalChargingNum: 2,
+  electricityNum: 1,
+  totalElectricityNum: 1
+})
+async function getStationChargingStatistics() {
+  chargingStatistics.value = await stationManagementService.getStationChargingStatistics()
+}
+getStationChargingStatistics()
+async function getStationResourceRate() {
+  originData.value = await stationManagementService.getStationResourceRate()
+}
+getStationResourceRate()
 </script>
 
 <style lang="scss" scoped>
@@ -896,6 +1000,7 @@ const columns = [ {
     .btn {
       display: flex;
       flex-wrap: wrap;
+
       // justify-content: space-between;
       li {
 
@@ -903,9 +1008,12 @@ const columns = [ {
         border-radius: 100px;
         border: 1px solid #80FFFF;
         padding: 0 10px;
-        margin:  10px;
+        margin: 10px;
         font-size: 20px;
         cursor: pointer;
+        &.active{
+          background: #2f64aa;
+        }
 
       }
     }

+ 37 - 1
src/pages/views/home/index.vue

@@ -7,6 +7,8 @@ import maintenanceDynamics from './components/MaintenanceDynamics.vue'
 import facilityManagement from './components/FacilityManagement.vue'
 import stationManagement from './components/StationManagement.vue'
 import passengerFlow from './components/PassengerFlow.vue'
+import ChangeLine from '@/components/changeLine.vue'
+
 import Map from '@/components/map/map.vue'
 import useStore from '@/pages/store'
 import HomeService from './services/homepage.service'
@@ -14,12 +16,16 @@ import CehicleOperationService from './services/cehicleOperation.service'
 import MaintenanceDynamicsService from './services/maintenanceDynamics.Service'
 import PassengerFlowService from './services/passengerFlow.service'
 import FacilityManagementService from './services/facilityManagement.service'
+import StationManagementService from './services/stationManagement.service'
+import LineAnalysisService from './services/lineAnalysis.service'
 
 const homeService = new HomeService()
 const cehicleOperationService = new CehicleOperationService()
 const passengerFlowService = new PassengerFlowService()
 const maintenanceDynamicsService = new MaintenanceDynamicsService()
 const facilityManagementService = new FacilityManagementService()
+const stationManagementService = new StationManagementService()
+const lineAnalysisService = new LineAnalysisService()
 
 const store = useStore()
 const menus = [
@@ -325,7 +331,7 @@ const menus = [
     }
   }
 ]
-const active = ref(4)
+const active = ref(0)
 const currentComponent = ref(menus[active.value].component)
 const weather = computed(() => store.weather)
 const warningMsg = ref({
@@ -416,6 +422,31 @@ async function getFacilityStatistics() {
   menus[4].count[4].value = vehicleComponentsNumTotal
 }
 getFacilityStatistics()
+
+async function getStationStatistics() {
+  const res = await stationManagementService.getStationStatistics()
+
+  menus[5].count[0].value = res.stationNum
+  menus[5].count[1].value = res.totalArea
+  menus[5].count[2].value = res.lineNum
+  menus[5].count[3].value = res.vehicleNum
+  menus[5].count[4].value = res.parkNum
+  menus[5].count[5].value = res.chargingNum
+  menus[5].count[6].value = res.chargeVehicle
+  menus[5].count[7].value = res.maintenanceNum
+}
+getStationStatistics()
+async function getAnalysisLineStatistics() {
+  const res = await lineAnalysisService.getAnalysisLineStatistics()
+
+  menus[6].count[0].value = res.lineNum
+  menus[6].count[1].value = res.stationNum
+  menus[6].count[2].value = res.lineLength
+  menus[6].count[3].value = res.lineDensity
+  menus[6].count[4].value = res.lineRepetition
+  menus[6].count[5].value = res.lineCoverageRate
+}
+getAnalysisLineStatistics()
 </script>
 <template>
   <div class="home">
@@ -493,6 +524,7 @@ getFacilityStatistics()
         </template>
       </div>
       <component :is="currentComponent" />
+      <ChangeLine v-show="active===1" />
     </div>
     <div class="home-bottom">
       雅安市公共交通集团有限公司
@@ -755,6 +787,10 @@ getFacilityStatistics()
         }
       }
     }
+    .drag-container{
+      left: 1581px;
+      top: 318px;
+    }
   }
 
   &-bottom {

+ 3 - 2
src/pages/views/home/services/cehicleOperation.service.ts

@@ -33,8 +33,9 @@ export default class CehicleOperationService extends Service {
   }
 
   /** 线路发班情况   /lineOperate/getBusLineOperate */
-  async getBusLineOperate(lineId:string) {
-    const { success, data } = await this.netService.get(`/lineOperate/getBusLineOperate?lineId=${lineId}`)
+  async getBusLineOperate(params:any) {
+    const { lineId, type } = params
+    const { success, data } = await this.netService.get(`/lineOperate/getBusLineOperate?lineId=${lineId}&type=${type}`)
     if (success) {
       return data?.list || []
     }

+ 82 - 0
src/pages/views/home/services/lineAnalysis.service.ts

@@ -0,0 +1,82 @@
+import NetService from '@/services/net.service'
+import { injectable, Service } from '@/services/service'
+
+@injectable
+export default class LineAnalysisService extends Service {
+  private netService = new NetService()
+
+  /** 线路类型  /getAnalysisLineType   */
+  async getAnalysisLineType() {
+    const { success, data } = await this.netService.get('/getAnalysisLineType')
+    if (success) {
+      return data || []
+    }
+    return []
+  }
+
+  /** 区域里程  /getAnalysisRegionFlow   */
+  async getAnalysisRegionFlow() {
+    const { success, data } = await this.netService.get('/getAnalysisRegionFlow')
+    if (success) {
+      return data || []
+    }
+    return []
+  }
+
+  /** 近期调整线路  /getAnalysisLineAdjust   */
+  async getAnalysisLineAdjust(params:any) {
+    const { startTime = '', endTime = '', type = '' } = params
+    const { success, data } = await this.netService.get(`/getAnalysisLineAdjust?startTime=${startTime}&endTime=${endTime}&type=${type}`)
+    if (success) {
+      return data || []
+    }
+    return []
+  }
+
+  /** 线路长度分布  /getAnalysisLineLength   */
+  async getAnalysisLineLength() {
+    const { success, data } = await this.netService.get('/getAnalysisLineLength')
+    if (success) {
+      return data || []
+    }
+    return []
+  }
+
+  /** 线路站距分布  /getAnalysisLineDistance   */
+  async getAnalysisLineDistance() {
+    const { success, data } = await this.netService.get('/getAnalysisLineDistance')
+    if (success) {
+      return data || []
+    }
+    return []
+  }
+
+  /** 线路运行速度  /getAnalysisLineOperate   */
+  async getAnalysisLineOperate(params:any) {
+    const { startTime = '', endTime = '', type = '' } = params
+    const { success, data } = await this.netService.get(`/getAnalysisLineOperate?startTime=${startTime}&endTime=${endTime}&type=${type}`)
+    if (success) {
+      return data || []
+    }
+    return []
+  }
+
+  /** 站点客流排名  /getAnalysisStationRank   */
+  async getAnalysisStationRank(params:any) {
+    const { startTime = '', endTime = '', type = '' } = params
+    const { success, data } = await this.netService.get(`/getAnalysisStationRank?startTime=${startTime}&endTime=${endTime}&type=${type}`)
+    if (success) {
+      return data || []
+    }
+    return []
+  }
+
+  /** 线路分析地图数据统计  /getAnalysisLineStatistics   */
+  async getAnalysisLineStatistics() {
+    const { success, data } = await this.netService.get('/getAnalysisLineStatistics')
+    if (success) {
+      return data || {}
+    }
+    return {}
+  }
+}

+ 124 - 0
src/pages/views/home/services/stationManagement.service.ts

@@ -0,0 +1,124 @@
+import NetService from '@/services/net.service'
+import { injectable, Service } from '@/services/service'
+
+@injectable
+export default class StationManagementService extends Service {
+  private netService = new NetService()
+
+  /** 区域分布  /getStationRegion   */
+  async getStationRegion() {
+    const { success, data } = await this.netService.get('/getStationRegion')
+    if (success) {
+      return data || []
+    }
+    return []
+  }
+
+  /** 类型分布  /getStationTypes   */
+  async getStationTypes() {
+    const { success, data } = await this.netService.get('/getStationTypes')
+    if (success) {
+      return data || []
+    }
+    return []
+  }
+
+  /** 面积分布  /getStationArea   */
+  async getStationArea() {
+    const { success, data } = await this.netService.get('/getStationArea')
+    if (success) {
+      return data || []
+    }
+    return []
+  }
+
+  /** 场站权属情况  /getStationOwnership   */
+  async getStationOwnership() {
+    const { success, data } = await this.netService.get('/getStationOwnership')
+    if (success) {
+      return data || []
+    }
+    return []
+  }
+
+  /** 建设时间  /getStationConstruct   */
+  async getStationConstruct() {
+    const { success, data } = await this.netService.get('/getStationConstruct')
+    if (success) {
+      return data || []
+    }
+    return []
+  }
+
+  /** 使用情况  /getStationUse   */
+  async getStationUse() {
+    const { success, data } = await this.netService.get('/getStationUse')
+    if (success) {
+      return data || []
+    }
+    return []
+  }
+
+  /** 运营保障  /getStationOperate   */
+  async getStationOperate() {
+    const { success, data } = await this.netService.get('/getStationOperate')
+    if (success) {
+      return data || []
+    }
+    return []
+  }
+
+  /** 充电趋势  /getStationChargingTrends   */
+  async getStationChargingTrends() {
+    const { success, data } = await this.netService.get('/getStationChargingTrends')
+    if (success) {
+      return data || []
+    }
+    return []
+  }
+
+  /** 场站装机容量  /getStationInstalledCapacity   */
+  async getStationInstalledCapacity() {
+    const { success, data } = await this.netService.get('/getStationInstalledCapacity')
+    if (success) {
+      return data || []
+    }
+    return []
+  }
+
+  /** 充电桩服务情况  /getStationChargingStatus   */
+  async getStationChargingStatus() {
+    const { success, data } = await this.netService.get('/getStationChargingStatus')
+    if (success) {
+      return data || []
+    }
+    return []
+  }
+
+  /** 今日充电统计  /getStationChargingStatistics   */
+  async getStationChargingStatistics() {
+    const { success, data } = await this.netService.get('/getStationChargingStatistics')
+    if (success) {
+      return data || []
+    }
+    return []
+  }
+
+  /** 资源使用率  /getStationResourceRate   */
+  async getStationResourceRate() {
+    const { success, data } = await this.netService.get('/getStationResourceRate')
+    if (success) {
+      return data || []
+    }
+    return []
+  }
+
+  /** 场站管理地图统计数据配置  /getStationStatistics   */
+  async getStationStatistics() {
+    const { success, data } = await this.netService.get('/getStationStatistics')
+    if (success) {
+      return data || []
+    }
+    return []
+  }
+}

Some files were not shown because too many files changed in this diff