Bladeren bron

服务单元分析静态页完成

刘洋 1 jaar geleden
bovenliggende
commit
ace74db0a7

+ 2 - 0
src/components/global/index.js

@@ -16,6 +16,7 @@ import {
   TitleComponent,
   GeoComponent,
   LegendScrollComponent,
+  ToolboxComponent,
 } from 'echarts/components';
 
 import Chart from './chart/index.vue';
@@ -38,6 +39,7 @@ use([
   TitleComponent,
   GeoComponent,
   LegendScrollComponent,
+  ToolboxComponent,
 ]);
 
 export default {

+ 141 - 40
src/utils/chart.js

@@ -46,35 +46,126 @@ const colorList = [
   '#585247',
   '#ff0000',
 ];
-//该方法生成双柱状图,后期再根据情况改造成根据数据循环成多柱状图
-export const createDoubleBarOption = (
-  { legendData, xData, yDatas },
-  extend = {}
-) => {
+
+//堆叠柱状图
+export const createStackingBarOption = ({ xData, seriesData }, extend = {}) => {
   return mergeParams(
     {
       tooltip: {
         trigger: 'axis',
+        axisPointer: {
+          type: 'shadow',
+        },
       },
       legend: [
         {
           icon: 'react',
-          right: '3%',
-          top: '3%',
+          right: '0%',
+          top: '1%',
           textStyle: {
             color: '#595959',
             fontSize: 12,
           },
           itemWidth: 8,
           itemHeight: 8,
-          data: legendData,
+          data: seriesData.map((item) => item.name),
         },
       ],
       grid: {
-        top: '22%',
-        right: '3%',
-        left: '16%',
-        bottom: '10%',
+        left: '1%',
+        right: '1%',
+        bottom: '1%',
+        containLabel: true,
+      },
+      xAxis: {
+        type: 'value',
+        axisLabel: {
+          formatter: '{value}',
+          color: '#8c8c8c',
+          textStyle: {
+            fontSize: 12,
+          },
+        },
+        axisLine: {
+          show: false,
+        },
+        axisTick: {
+          show: false,
+        },
+      },
+      yAxis: {
+        type: 'category',
+        data: xData,
+        axisLine: {
+          show: false,
+        },
+        axisTick: {
+          show: false,
+        },
+        axisLabel: {
+          margin: 6,
+          color: '#8c8c8c',
+          textStyle: {
+            fontSize: 12,
+          },
+        },
+      },
+      series: seriesData.map((item, index) => ({
+        name: item.name,
+        type: 'bar',
+        data: item.data,
+        barWidth: '8px',
+        stack: '总量',
+        // label: {
+        //   normal: {
+        //     show: true,
+        //     position: 'insideRight',
+        //   },
+        // },
+        itemStyle: {
+          normal: {
+            color: colorList[index % colorList.length],
+          },
+        },
+      })),
+    },
+    extend
+  );
+};
+
+//基础柱状图
+export const createBarOption = ({ xData, seriesData }, extend = {}) => {
+  return mergeParams(
+    {
+      tooltip: {
+        trigger: 'axis',
+        axisPointer: {
+          type: 'shadow',
+        },
+      },
+      legend: [
+        {
+          icon: 'react',
+          right: '0%',
+          top: '1%',
+          textStyle: {
+            color: '#595959',
+            fontSize: 12,
+          },
+          itemWidth: 8,
+          itemHeight: 8,
+          data: seriesData.map((item) => item.name),
+        },
+      ],
+      grid: {
+        // top: '22%',
+        // right: '3%',
+        // left: '16%',
+        // bottom: '10%',
+        left: '1%',
+        right: '1%',
+        bottom: '1%',
+        containLabel: true,
       },
       xAxis: [
         {
@@ -112,30 +203,41 @@ export const createDoubleBarOption = (
           },
         },
       ],
-      series: [
-        {
-          name: '当期',
-          type: 'bar',
-          data: yDatas[0],
-          barWidth: '12px',
-          itemStyle: {
-            normal: {
-              color: '#4080FF',
-            },
-          },
-        },
-        {
-          name: '同期',
-          type: 'bar',
-          data: yDatas[1],
-          barWidth: '12px',
-          itemStyle: {
-            normal: {
-              color: '#23C343',
-            },
+      series: seriesData.map((item, index) => ({
+        name: item.name,
+        type: 'bar',
+        data: item.data,
+        barWidth: '12px',
+        itemStyle: {
+          normal: {
+            color: colorList[index % colorList.length],
           },
         },
-      ],
+      })),
+      // series: [
+      //   {
+      //     name: '当期',
+      //     type: 'bar',
+      //     data: yDatas[0],
+      //     barWidth: '12px',
+      //     itemStyle: {
+      //       normal: {
+      //         color: '#4080FF',
+      //       },
+      //     },
+      //   },
+      //   {
+      //     name: '同期',
+      //     type: 'bar',
+      //     data: yDatas[1],
+      //     barWidth: '12px',
+      //     itemStyle: {
+      //       normal: {
+      //         color: '#23C343',
+      //       },
+      //     },
+      //   },
+      // ],
     },
     extend
   );
@@ -234,7 +336,6 @@ export const createCakePieOption = (
         show: true,
       },
       legend: {
-        type: 'scroll',
         orient: 'vertical',
         right: '1%',
         top: 'center',
@@ -264,7 +365,7 @@ export const createCakePieOption = (
 };
 //基础水球图
 export const createWaterBallOption = (
-  { data, title, center, color = '64,128,255' },
+  { data, title, center, radius = '90%', color = '64,128,255' },
   extend = {}
 ) => {
   return mergeParams(
@@ -311,7 +412,7 @@ export const createWaterBallOption = (
               left: '10',
               top: 'middle',
               style: {
-                fill: '#666',
+                fill: '#fff',
                 text: title,
                 font: '12px Microsoft YaHei',
               },
@@ -323,7 +424,7 @@ export const createWaterBallOption = (
         {
           name: 'test',
           type: 'liquidFill',
-          radius: '90%',
+          radius: radius,
           center: center || ['50%', '50%'],
           data: [data],
           label: {
@@ -336,9 +437,9 @@ export const createWaterBallOption = (
               },
             },
           },
-          color: ['#4080FF'],
+          color: [`rgba(${color},1)`],
           backgroundStyle: {
-            color: `rgba(${color},0.12)`,
+            color: `rgba(${color},0.26)`,
           },
           outline: {
             borderDistance: 0,

+ 15 - 8
src/views/report/dispatch-analysis/index.vue

@@ -47,7 +47,7 @@
             <div class="card chart6-box">
               <div class="title">教务处月度派单分布及对比备份</div>
               <div class="chart-wrap">
-                <my-chart :options="options2"></my-chart>
+                <my-chart :options="options3"></my-chart>
               </div>
             </div>
           </div>
@@ -155,7 +155,7 @@ import { ref, computed } from 'vue';
 import ChinaPointChart from '@/components/common/china-point-chart/index.vue';
 import TableLoop from '@/components/common/table-loop/index.vue';
 import {
-  createDoubleBarOption,
+  createBarOption,
   createRingPieOption,
   createCakePieOption,
 } from '@/utils/chart';
@@ -171,12 +171,18 @@ const options1 = createRingPieOption({
   seriesName: '客户类型',
 });
 
-const options2 = createDoubleBarOption({
-  legendData: ['当期', '同期'],
+const options2 = createBarOption({
   xData: ['23-01', '23-02', '23-03', '23-04', '23-05'],
-  yDatas: [
-    [322.1, 421.4, 100.9, 662, 200.03],
-    [990.84, 400, 343.5, 200.3, 552],
+  seriesData: [
+    { name: '当期', data: [322.1, 421.4, 100.9, 662, 200.03] },
+    { name: '同期', data: [990.84, 400, 343.5, 200.3, 552] },
+  ],
+});
+const options3 = createBarOption({
+  xData: ['23-01', '23-02', '23-03', '23-04', '23-05'],
+  seriesData: [
+    { name: '当期', data: [322.1, 421.4, 100.9, 662, 200.03] },
+    { name: '同期', data: [990.84, 400, 343.5, 200.3, 552] },
   ],
 });
 
@@ -199,6 +205,7 @@ const options4 = createCakePieOption({
     .scroll-content {
       height: 100%;
       min-height: 600px;
+      min-width: 1000px;
     }
     .row1 {
       height: calc((100% - 30px) * 2 / 3 + 15px);
@@ -270,7 +277,7 @@ const options4 = createCakePieOption({
           display: flex;
           flex-wrap: wrap;
           justify-content: space-between;
-          align-content: start;
+          align-content: flex-start;
         }
         .service-item {
           height: 54px;

+ 192 - 8
src/views/report/service-analysis/index.vue

@@ -65,27 +65,85 @@
                     <div class="value">39</div>
                   </div>
                 </div>
-                <div class="cover-range"></div>
+                <div class="desc-text">覆盖4个大区:北京、天津、武汉、广州</div>
               </div>
             </div>
-            <div></div>
           </div>
           <div
             class="card m-t-15px"
             style="height: calc((100% - 206px) * 4 / 7)"
-          ></div>
+          >
+            <div class="title">
+              <span class="label">项目角色待调配额盘点</span>
+            </div>
+            <div class="box4">
+              <div class="charts-box">
+                <div class="chart-item">
+                  <div class="chart-wrap">
+                    <my-chart :options="options4"></my-chart>
+                  </div>
+                  <div class="title-wrap">实施工程师</div>
+                </div>
+                <div class="chart-item">
+                  <div class="chart-wrap">
+                    <my-chart :options="options5"></my-chart>
+                  </div>
+                  <div class="title-wrap">区域协调人</div>
+                </div>
+                <div class="chart-item">
+                  <div class="chart-wrap">
+                    <my-chart :options="options6"></my-chart>
+                  </div>
+                  <div class="title-wrap">助理工程师</div>
+                </div>
+              </div>
+              <div class="desc-text">
+                <p>大区内同业务类型待划拨派单数量:3个</p>
+                <p>当前大区覆盖城市:2个</p>
+              </div>
+            </div>
+          </div>
           <div class="card m-t-15px" style="height: 80px">
             <div class="title">
               <span class="label">项目配额完成进度</span>
             </div>
+            <div class="bar-box flex items-center">
+              <div class="process-box">
+                <div class="process" :style="{ width: '20%' }"></div>
+              </div>
+              <span class="process-text m-l-10px">20%</span>
+            </div>
           </div>
           <div class="card m-t-15px" style="height: 80px">
             <div class="title">
               <span class="label">人员配额完成进度</span>
             </div>
+            <div class="bar-box flex items-center">
+              <div class="process-box">
+                <div class="process" :style="{ width: '90%' }"></div>
+              </div>
+              <span class="process-text m-l-10px">90%</span>
+            </div>
+          </div>
+        </div>
+        <div class="col3">
+          <div class="card">
+            <div class="title">
+              <span class="label">设备供应商设备使用占比</span>
+            </div>
+            <div style="height: calc(100% - 36px)">
+              <my-chart :options="options7"></my-chart>
+            </div>
+          </div>
+          <div class="card">
+            <div class="title">
+              <span class="label">大区在服务人数分布及对比</span>
+            </div>
+            <div style="height: calc(100% - 36px)">
+              <my-chart :options="options8"></my-chart>
+            </div>
           </div>
         </div>
-        <div class="col3"></div>
       </div>
     </div>
   </div>
@@ -98,12 +156,14 @@ import {
   createWaterBallOption,
   createRingPieOption,
   createCakePieOption,
+  createStackingBarOption,
 } from '@/utils/chart';
 const curTimeRange = ref([]);
 const serviceId = ref('');
 const options1 = createWaterBallOption({
   data: 23.5 / 100,
   title: '项目执行进度',
+  radius: '80%',
 });
 const options2 = createRingPieOption(
   {
@@ -120,17 +180,17 @@ const options2 = createRingPieOption(
       { name: 'HHHH', value: 72 },
     ],
     title: '派单数',
-    center: ['50%', '35%'],
+    center: ['50%', '25%'],
     seriesName: '数量',
-    radius: [45, 65],
+    radius: [40, 60],
   },
   {
     legend: {
-      type: 'scroll',
+      // type: 'scroll',
       orient: 'horizontal',
       top: null,
       right: null,
-      bottom: '10%',
+      bottom: '0%',
       left: 'center',
     },
   }
@@ -159,6 +219,70 @@ const options3 = createCakePieOption(
     // },
   }
 );
+
+const options4 = createWaterBallOption({
+  data: 65 / 100,
+  title: '剩130配额',
+  radius: '80%',
+});
+const options5 = createWaterBallOption({
+  data: 35 / 100,
+  title: '剩34配额',
+  radius: '80%',
+  color: '35, 195, 67',
+});
+const options6 = createWaterBallOption({
+  data: 55 / 100,
+  title: '剩14配额',
+  radius: '80%',
+  color: '255, 154, 46',
+});
+const options7 = createCakePieOption(
+  {
+    data: [
+      { name: 'AAAA', value: 32 },
+      { name: 'BBBB', value: 39 },
+      { name: 'CCCC', value: 69 },
+      { name: 'DDDD', value: 19 },
+      { name: 'EEEE', value: 69 },
+      { name: 'FFFF', value: 9 },
+    ],
+    radius: [0, 60],
+    center: ['50%', '30%'],
+    seriesName: '设备使用占比',
+  },
+  {
+    legend: {
+      // type: 'scroll',
+      orient: 'horizontal',
+      top: null,
+      right: null,
+      bottom: '0%',
+      left: 'center',
+    },
+  }
+);
+
+const options8 = createStackingBarOption(
+  {
+    xData: [
+      '北京',
+      '上海',
+      '武汉',
+      '天津',
+      '广州',
+      '南京',
+      '长沙',
+      '青海',
+      '福建',
+    ],
+    seriesData: [
+      { name: '阳光雨露', data: [322.1, 421.4, 100.9, 662, 200.03] },
+      { name: '软通智服', data: [990.84, 400, 343.5, 200.3, 552] },
+    ],
+  },
+  {}
+);
 </script>
 
 <style lang="less" scoped>
@@ -198,12 +322,72 @@ const options3 = createCakePieOption(
         width: calc(100% - 566px);
         margin-left: 15px;
         margin-right: 15px;
+        .process-text {
+          font-size: 12px;
+          color: #262626;
+          width: 40px;
+        }
+        .process-box {
+          flex: 1;
+          background-color: #d9d9d9;
+          height: 6px;
+          border-radius: 3px;
+          overflow: hidden;
+          .process {
+            background-color: #4080ff;
+            height: 100%;
+          }
+        }
+        .box4 {
+          height: calc(100% - 36px);
+          display: flex;
+          flex-direction: column;
+          .charts-box {
+            flex: 1;
+            display: flex;
+            justify-content: space-around;
+            .chart-item {
+              width: 33.3%;
+              height: 100%;
+              display: flex;
+              flex-direction: column;
+              .chart-wrap {
+                flex: 1;
+              }
+              .title-wrap {
+                text-align: center;
+                color: #595959;
+                font-size: 12px;
+              }
+            }
+          }
+          .desc-text {
+            margin-top: 10px;
+            background-color: #f7f7f7;
+            border-radius: 2px;
+            padding: 8px 15px;
+            font-size: 12px;
+            color: #262626;
+            height: 58px;
+            display: flex;
+            flex-direction: column;
+            justify-content: space-around;
+          }
+        }
         .box3 {
           height: calc(100% - 36px);
           .gird3-others {
             display: flex;
             flex-direction: column;
             justify-content: space-around;
+            .desc-text {
+              background-color: #f7f7f7;
+              border-radius: 2px;
+              padding: 8px 15px;
+              line-height: 1.4;
+              font-size: 12px;
+              color: #262626;
+            }
             .num-show {
               .desc {
                 .label {