Browse Source

Merge branch 'dev' of http://git.wisdomcity.com.cn/WisdomCity-Web/SaaS-DataScreen into feat-b2

wjc 2 weeks ago
parent
commit
2bce104c2a
79 changed files with 3873 additions and 316 deletions
  1. 2 0
      package.json
  2. 0 3
      src/App.vue
  3. 3 1
      src/api/index.js
  4. 11 0
      src/api/screen.js
  5. 0 1
      src/assets/css/element-variables.scss
  6. 122 0
      src/assets/css/mixin.scss
  7. 153 0
      src/assets/css/screen.scss
  8. 1 0
      src/assets/css/theme.scss
  9. 1 1
      src/assets/css/theme_1.scss
  10. 2 2
      src/assets/css/theme_2.scss
  11. BIN
      src/assets/images/hjkj-logo.png
  12. BIN
      src/assets/images/hjkj1.png
  13. BIN
      src/assets/images/hjkj2.png
  14. 279 0
      src/assets/js/province-positon.js
  15. 89 88
      src/components/digit-roll/index.vue
  16. 11 9
      src/components/digit-roll/utils/index.js
  17. 24 0
      src/libs/tools.js
  18. 6 1
      src/main.js
  19. 19 0
      src/route/index.js
  20. 40 0
      src/views/a1-screen/index.vue
  21. 45 0
      src/views/a2-screen/index.vue
  22. 2 0
      src/views/components/card/index.js
  23. 68 0
      src/views/components/card/index.vue
  24. 146 0
      src/views/components/community-map/components/map-list.vue
  25. BIN
      src/views/components/community-map/images/icon-title.png
  26. BIN
      src/views/components/community-map/images/map-mark-icon.png
  27. 2 0
      src/views/components/community-map/index.js
  28. 157 0
      src/views/components/community-map/index.vue
  29. 279 0
      src/views/components/community-map/province-positon.js
  30. 0 0
      src/views/components/community-type/components/bar.vue
  31. 343 0
      src/views/components/community-type/components/three-pie.vue
  32. BIN
      src/views/components/community-type/images/icon-title.png
  33. 2 0
      src/views/components/community-type/index.js
  34. 45 0
      src/views/components/community-type/index.vue
  35. BIN
      src/views/components/online-pay-day/images/icon-title.png
  36. 2 0
      src/views/components/online-pay-day/index.js
  37. 394 0
      src/views/components/online-pay-day/index.vue
  38. BIN
      src/views/components/online-pay-week/images/icon-title.png
  39. 2 0
      src/views/components/online-pay-week/index.js
  40. 369 0
      src/views/components/online-pay-week/index.vue
  41. BIN
      src/views/components/online-pay/images/icon-title.png
  42. BIN
      src/views/components/online-pay/images/icon-total.png
  43. 2 0
      src/views/components/online-pay/index.js
  44. 224 0
      src/views/components/online-pay/index.vue
  45. BIN
      src/views/components/online-water/images/icon-month.png
  46. BIN
      src/views/components/online-water/images/icon-once.png
  47. BIN
      src/views/components/online-water/images/icon-title.png
  48. BIN
      src/views/components/online-water/images/icon-total.png
  49. 2 0
      src/views/components/online-water/index.js
  50. 147 0
      src/views/components/online-water/index.vue
  51. BIN
      src/views/components/resident/images/icon-hfw.png
  52. BIN
      src/views/components/resident/images/icon-pay.png
  53. BIN
      src/views/components/resident/images/icon-qrcode.png
  54. BIN
      src/views/components/resident/images/icon-report.png
  55. BIN
      src/views/components/resident/images/icon-title.png
  56. 2 0
      src/views/components/resident/index.js
  57. 238 0
      src/views/components/resident/index.vue
  58. 3 0
      src/views/components/title/index.js
  59. 24 0
      src/views/components/title/index.vue
  60. BIN
      src/views/components/user/images/icon-car.png
  61. BIN
      src/views/components/user/images/icon-community.png
  62. BIN
      src/views/components/user/images/icon-house.png
  63. BIN
      src/views/components/user/images/icon-park.png
  64. BIN
      src/views/components/user/images/icon-resident.png
  65. BIN
      src/views/components/user/images/icon-title.png
  66. BIN
      src/views/components/user/images/icon-user.png
  67. 2 0
      src/views/components/user/index.js
  68. 100 0
      src/views/components/user/index.vue
  69. 34 16
      src/views/hui-jia/b1-screen/index.vue
  70. 35 20
      src/views/hui-jia/b2-screen/index.vue
  71. 254 30
      src/views/hui-jia/components/hardware.vue
  72. 3 3
      src/views/hui-jia/components/implementary/total.vue
  73. 133 133
      src/views/hui-jia/components/smart.vue
  74. 4 0
      src/views/index/index.scss
  75. BIN
      src/views/login/images/logo@3x.png
  76. 15 4
      src/views/login/index.scss
  77. 3 3
      src/views/login/index.vue
  78. 6 1
      vue.config.js
  79. 23 0
      yarn.lock

+ 2 - 0
package.json

@@ -11,6 +11,7 @@
     "test:unit": "vue-cli-service test:unit"
   },
   "dependencies": {
+    "@vue/composition-api": "^1.7.2",
     "axios": "^0.19.0",
     "babel-polyfill": "^6.26.0",
     "core-js": "^2.6.5",
@@ -22,6 +23,7 @@
     "vue-count-to": "^1.0.13",
     "vue-router": "^3.0.3",
     "vue-seamless-scroll": "^1.1.17",
+    "vue-tianditu": "2.7.6",
     "vuex": "^3.0.1"
   },
   "devDependencies": {

+ 0 - 3
src/App.vue

@@ -13,9 +13,6 @@
 <style lang="scss">
 @import '../src/assets/css/theme.scss';
 #app{
-  background: $big-bg;
-  background-repeat: no-repeat;
-  background-size: 100% 100%;
   width: 100vw;
   height: 100vh;
 }

+ 3 - 1
src/api/index.js

@@ -7,8 +7,10 @@
  */
 import api from './api'
 import totalSum from './total-sum'
+import screen from './screen'
 
 export {
   api,
-  totalSum
+  totalSum,
+  screen
 }

+ 11 - 0
src/api/screen.js

@@ -0,0 +1,11 @@
+import axios from '../assets/js/api.request'
+
+export default {
+  getProjectStatistics (data) {
+    return axios.request({
+      url: '/log/bi/project/statistics',
+      params: data,
+      method: 'get'
+    })
+  }
+}

+ 0 - 1
src/assets/css/element-variables.scss

@@ -1,7 +1,6 @@
 @import './theme.scss';
 
 /* 改变主题色变量 */
-$--color-primary: $primary-color;
 
 /* 改变 icon 字体路径变量,必需 */
 $--font-path: '~element-ui/lib/theme-chalk/fonts';

+ 122 - 0
src/assets/css/mixin.scss

@@ -60,3 +60,125 @@
 @mixin boxShadow() {
   box-shadow: 0px 2px 8px 0px rgba(0, 0, 0, 0.1);
 }
+
+// 天地图
+@mixin tiandituPointer {
+  .tdt-map-container {
+    .tdt-label {
+      background: transparent;
+      box-shadow: none;
+      border: none;
+      color: #2f61a6ff;
+      font-size: 12px;
+      padding: 0;
+      margin-left: 4px;
+      font-weight: 600;
+    }
+  }
+}
+
+@mixin initTianditu() {
+  .tdt-map-container {
+    width: 100%;
+    height: 100%;
+    .tdt-infowindow-content-wrapper {
+      padding: 0;
+      border-radius: 4px;
+      width: 100%;
+      height: 100%;
+      background: transparent;
+      .tdt-infowindow-content {
+        margin: 0;
+        padding: 2px;
+        width: 100% !important;
+        height: 100%;
+        .map-mark-container {
+          display: flex;
+          justify-content: space-between;
+          width: halfW(400);
+          height: halfH(90);
+          min-height: 80px;
+          border-radius: 6px;
+          // position: absolute;
+          overflow: hidden;
+          cursor: pointer;
+        
+          &.blue {
+            background: rgba(50, 129, 219, 0.6);
+            border: 1px solid rgba(50, 136, 233, 1);
+          }
+        
+          &.yellow {
+            background: rgba(230, 188, 116, 0.6);
+            border: 1px solid rgba(233, 175, 50, 1);
+          }
+        
+          &.green {
+            background: rgba(45, 158, 12, 0.6);
+            border: 1px solid rgba(45, 158, 12, 1);
+          }
+        
+          .left-side {
+            height: 100%;
+            width: halfW(76);
+            position: relative;
+        
+            &.blue {
+              background: #3281db;
+            }
+        
+            &.yellow {
+              background: #e4a537;
+            }
+        
+            &.green {
+              background: #2d9e0c;
+            }
+        
+            img {
+              position: absolute;
+              top: 50%;
+              left: 50%;
+              transform: translate(-50%, -50%);
+            }
+          }
+        
+          .right-side {
+            flex: 1;
+            padding: halfH(20) halfW(20);
+            .name-info {
+              display: flex;
+              justify-content: space-between;
+              align-items: flex-start;
+            }
+        
+            &-name {
+              width: 90%;
+              font-size: 18px;
+              font-weight: bold;
+              color: rgba(235, 244, 255, 1);
+            }
+        
+            &-local {
+              font-size: 16px;
+              font-weight: 400;
+              color: rgba(235, 244, 255, 1);
+              margin-top: halfH(10);
+            }
+        
+            &-time {
+              width: 10%;
+              text-align: right;
+              font-size: 14px;
+              font-weight: 400;
+              color: rgba(235, 244, 255, 1);
+            }
+          }
+        }
+      }
+    }
+    .tdt-infowindow-tip-container {
+      display: none;
+    }
+  }
+}

+ 153 - 0
src/assets/css/screen.scss

@@ -0,0 +1,153 @@
+@import "./function.scss";
+.display-flex{
+    display: flex;
+}
+.flex-1{
+    flex: 1;
+}
+.margin-l-30{
+    margin-left: halfW(30);
+}
+.margin-r-30{
+    margin-right: halfW(30);
+}
+.margin-t-30{
+    margin-top: halfH(30);
+}
+.margin-r-20{
+    margin-right: halfW(20);
+}
+.margin-t-10{
+    margin-top: halfH(10);
+}
+.border{
+    border: 1px solid rgba(0, 123, 211, 0.2);
+    border-radius: halfW(5);
+}
+.map-con{
+    width: halfW(660);
+    height: halfH(795);
+}
+.screen{
+    width: 100%;
+    height: 100%;
+    background: #070D19;
+    .screen-content{
+       margin: 0 halfW(30);
+    }
+}
+.tdt-map-container {
+    .tdt-label {
+      background: transparent;
+      box-shadow: none;
+      border: none;
+      color: #2f61a6ff;
+      font-size: 12px;
+      padding: 0;
+      margin-left: 4px;
+      font-weight: 600;
+    }
+  }
+  .tdt-map-container {
+    width: 100%;
+    height: 100%;
+    .tdt-infowindow-content-wrapper {
+      padding: 0;
+      border-radius: 4px;
+      width: 100%;
+      height: 100%;
+      background: transparent;
+      .tdt-infowindow-content {
+        margin: 0;
+        padding: 2px;
+        width: 100% !important;
+        height: 100%;
+        .map-mark-container {
+          display: flex;
+          justify-content: space-between;
+          width: halfW(400);
+          height: halfH(90);
+          min-height: 80px;
+          border-radius: 6px;
+          // position: absolute;
+          overflow: hidden;
+          cursor: pointer;
+        
+          &.blue {
+            background: rgba(50, 129, 219, 0.6);
+            border: 1px solid rgba(50, 136, 233, 1);
+          }
+        
+          &.yellow {
+            background: rgba(230, 188, 116, 0.6);
+            border: 1px solid rgba(233, 175, 50, 1);
+          }
+        
+          &.green {
+            background: rgba(45, 158, 12, 0.6);
+            border: 1px solid rgba(45, 158, 12, 1);
+          }
+        
+          .left-side {
+            height: 100%;
+            width: halfW(76);
+            position: relative;
+        
+            &.blue {
+              background: #3281db;
+            }
+        
+            &.yellow {
+              background: #e4a537;
+            }
+        
+            &.green {
+              background: #2d9e0c;
+            }
+        
+            img {
+              position: absolute;
+              top: 50%;
+              left: 50%;
+              transform: translate(-50%, -50%);
+            }
+          }
+        
+          .right-side {
+            flex: 1;
+            padding: halfH(20) halfW(20);
+            .name-info {
+              display: flex;
+              justify-content: space-between;
+              align-items: flex-start;
+            }
+        
+            &-name {
+              width: 90%;
+              font-size: 18px;
+              font-weight: bold;
+              color: rgba(235, 244, 255, 1);
+            }
+        
+            &-local {
+              font-size: 16px;
+              font-weight: 400;
+              color: rgba(235, 244, 255, 1);
+              margin-top: halfH(10);
+            }
+        
+            &-time {
+              width: 10%;
+              text-align: right;
+              font-size: 14px;
+              font-weight: 400;
+              color: rgba(235, 244, 255, 1);
+            }
+          }
+        }
+      }
+    }
+    .tdt-infowindow-tip-container {
+      display: none;
+    }
+  }

+ 1 - 0
src/assets/css/theme.scss

@@ -20,6 +20,7 @@ $left-width: 220px;
   --title-secondary: #a1a1a1;
   --content-bg: #0C1425;
   --primary: #007bd3;
+  --page-bg: #070D19;
 }
 .title-icon {
   width: halfW(28);

+ 1 - 1
src/assets/css/theme_1.scss

@@ -1,5 +1,5 @@
 $big-bg: #0748A2 url('./assets/images/logo.jpg');
-$primary-color: #0080FF;
+// $primary-color: #0080FF;
 $title: #39D6FE;
 $title-cent: linear-gradient(0deg,rgba(23,101,255,1) 0%, rgba(23,101,255,1) 0%, rgba(73,217,254,1) 54.931640625%, rgba(143,239,255,1) 80.322265625%);
 $title-bg: url('./images/dbl@3x.png');

+ 2 - 2
src/assets/css/theme_2.scss

@@ -1,5 +1,5 @@
-$big-bg: #050E21 url('./assets/images/2_logo.png');
-$primary-color: #050E21;
+$big-bg: #050E21 url('./images/2_logo.png');
+// $primary-color: #050E21;
 $title: #7FA4DF;
 $title-cent: linear-gradient(0deg,rgba(23,101,255,1) 0%, rgba(24,84,222,1) 0%, rgba(58,177,208,1) 54.931640625%, rgba(113,194,208,1) 80.322265625%);
 $title-bg: url(./images/2_dbl@3x.png);

BIN
src/assets/images/hjkj-logo.png


BIN
src/assets/images/hjkj1.png


BIN
src/assets/images/hjkj2.png


+ 279 - 0
src/assets/js/province-positon.js

@@ -0,0 +1,279 @@
+const provincePosition = [
+  // 23省
+  {
+    name: '甘肃',
+    abb: '甘',
+    geoCoord: [
+      103.73,
+      36.03
+    ]
+  },
+  {
+    name: '青海',
+    abb: '青',
+    geoCoord: [
+      101.74,
+      36.56
+    ]
+  },
+  {
+    name: '四川',
+    abb: '川',
+    geoCoord: [
+      104.06,
+      30.67
+    ]
+  },
+  {
+    name: '河北',
+    abb: '冀',
+    geoCoord: [
+      114.48,
+      38.03
+    ]
+  },
+  {
+    name: '云南',
+    abb: '滇',
+    geoCoord: [
+      102.73,
+      25.04
+    ]
+  },
+  {
+    name: '贵州',
+    abb: '黔',
+    geoCoord: [
+      106.71,
+      26.57
+    ]
+  },
+  {
+    name: '湖北',
+    abb: '鄂',
+    geoCoord: [
+      114.31,
+      30.52
+    ]
+  },
+  {
+    name: '河南',
+    abb: '豫',
+    geoCoord: [
+      113.65,
+      34.76
+    ]
+  },
+  {
+    name: '山东',
+    abb: '鲁',
+    geoCoord: [
+      117,
+      36.65
+    ]
+  },
+  {
+    name: '江苏',
+    abb: '苏',
+    geoCoord: [
+      118.78,
+      32.04
+    ]
+  },
+  {
+    name: '安徽',
+    abb: '皖',
+    geoCoord: [
+      117.27,
+      31.86
+    ]
+  },
+  {
+    name: '浙江',
+    abb: '浙',
+    geoCoord: [
+      120.19,
+      30.26
+    ]
+  },
+  {
+    name: '江西',
+    abb: '赣',
+    geoCoord: [
+      115.89,
+      28.68
+    ]
+  },
+  {
+    name: '福建',
+    abb: '闽',
+    geoCoord: [
+      119.3,
+      26.08
+    ]
+  },
+  {
+    name: '广东',
+    abb: '粤',
+    geoCoord: [
+      113.23,
+      23.16
+    ]
+  },
+  {
+    name: '湖南',
+    abb: '湘',
+    geoCoord: [
+      113,
+      28.21
+    ]
+  },
+  {
+    name: '海南',
+    abb: '琼',
+    geoCoord: [
+      110.35,
+      20.02
+    ]
+  },
+  {
+    name: '辽宁',
+    abb: '辽',
+    geoCoord: [
+      123.38,
+      41.8
+    ]
+  },
+  {
+    name: '吉林',
+    abb: '吉',
+    geoCoord: [
+      125.35,
+      43.88
+    ]
+  },
+  {
+    name: '黑龙江',
+    abb: '黑',
+    geoCoord: [
+      126.63,
+      45.75
+    ]
+  },
+  {
+    name: '山西',
+    abb: '晋',
+    geoCoord: [
+      112.53,
+      37.87
+    ]
+  },
+  {
+    name: '陕西',
+    abb: '陕',
+    geoCoord: [
+      108.95,
+      34.27
+    ]
+  },
+  {
+    name: '台湾',
+    abb: '台',
+    geoCoord: [
+      121.30,
+      25.03
+    ]
+  },
+  // 4直辖市
+  {
+    name: '北京',
+    abb: '京',
+    geoCoord: [
+      116.46,
+      39.92
+    ]
+  },
+  {
+    name: '上海',
+    abb: '沪',
+    geoCoord: [
+      121.48,
+      31.22
+    ]
+  },
+  {
+    name: '重庆',
+    abb: '渝',
+    geoCoord: [
+      106.54,
+      29.59
+    ]
+  },
+  {
+    name: '天津',
+    abb: '津',
+    geoCoord: [
+      117.2,
+      39.13
+    ]
+  },
+  // 5自治区
+  {
+    name: '内蒙古',
+    abb: '蒙',
+    geoCoord: [
+      111.65,
+      40.82
+    ]
+  },
+  {
+    name: '广西',
+    abb: '桂',
+    geoCoord: [
+      108.33,
+      22.84
+    ]
+  },
+  {
+    name: '西藏',
+    abb: '藏',
+    geoCoord: [
+      91.11,
+      29.97
+    ]
+  },
+  {
+    name: '宁夏',
+    abb: '宁',
+    geoCoord: [
+      106.27,
+      38.47
+    ]
+  },
+  {
+    name: '新疆',
+    abb: '新',
+    geoCoord: [
+      87.68,
+      43.77
+    ]
+  },
+  // 2特别行政区
+  {
+    name: '香港',
+    abb: '港',
+    geoCoord: [
+      114.17,
+      22.28
+    ]
+  },
+  {
+    name: '澳门',
+    abb: '澳',
+    geoCoord: [
+      113.54,
+      22.19
+    ]
+  }
+]
+export default provincePosition

+ 89 - 88
src/components/digit-roll/index.vue

@@ -7,55 +7,56 @@
       transitionTimingFunction: easing
     }"
   >
-    <template v-for="(item, index) in valueFormat">
-      <span
-        :key="index"
-        :class="[
-          'dr-element',
-          /\d+/.test(item)
-            ? 'dr-digit'
-            : item == resetFormat.radix
-            ? 'dr-radix-mark'
-            : 'dr-formatting-mark'
-        ]"
-      >
-        <span class="dr-spacer">
-          {{ /\d+/.test(item) ? 8 : item }}
-        </span>
-        <template v-if="/\d+/.test(item)">
-          <span
-            class="dr-roll"
-            :style="{
-              transform: state
-                ? 'translateY(' + -item * 10 + '%' + ')'
-                : 'translteY(0)'
-            }"
-          >
+    <template >
+      <div v-for="(item, index) in valueFormat" :key="index">
+        <span
+          :class="[
+            'dr-element',
+            /\d+/.test(item)
+              ? 'dr-digit'
+              : item == resetFormat.radix
+              ? 'dr-radix-mark'
+              : 'dr-formatting-mark'
+          ]"
+        >
+          <span class="dr-spacer">
+            {{ /\d+/.test(item) ? 8 : item }}
+          </span>
+          <template v-if="/\d+/.test(item)">
             <span
-              class="dr-roll-element"
-              v-for="(_item, _index) in 10"
-              :key="_index"
+              class="dr-roll"
+              :style="{
+                transform: state
+                  ? 'translateY(' + -item * 10 + '%' + ')'
+                  : 'translteY(0)'
+              }"
             >
-              {{ _index }}
+              <span
+                class="dr-roll-element"
+                v-for="(_item, _index) in 10"
+                :key="_index"
+              >
+                {{ _index }}
+              </span>
             </span>
-          </span>
-        </template>
-      </span>
+          </template>
+        </span>
+      </div>
     </template>
   </span>
 </template>
 
 <script>
-import _ from "./utils";
+import _ from './utils'
 
-let DIGIT_FORMAT = "(,ddd).dd";
-let FORMAT_PARSER = /^\(?([^)]*)\)?(?:(.)(d+))?$/;
+let DIGIT_FORMAT = '(,ddd).dd'
+let FORMAT_PARSER = /^\(?([^)]*)\)?(?:(.)(d+))?$/
 
 export default {
-  name: "digit-roll",
+  name: 'digit-roll',
   model: {
-    prop: "value",
-    event: "change"
+    prop: 'value',
+    event: 'change'
   },
   props: {
     value: {
@@ -72,7 +73,7 @@ export default {
     },
     easing: {
       type: String,
-      default: "linear"
+      default: 'linear'
     },
     format: {
       type: String,
@@ -82,109 +83,109 @@ export default {
       // 小数位取整函数
       // ceil:向上取整 floor:向下取整 round:四舍五入
       type: String,
-      default: "round"
+      default: 'round'
     }
   },
   computed: {
-    resetFormat() {
-      let f = FORMAT_PARSER.exec(this.format).slice(1);
+    resetFormat () {
+      let f = FORMAT_PARSER.exec(this.format).slice(1)
 
       return {
         repeating: f[0],
         radix: f[1],
         precision: f[2].length
-      };
+      }
     },
-    valueFormat() {
-      const WFLAG = true;
-      let repeating = this.resetFormat.repeating;
-      let _arr = [];
+    valueFormat () {
+      // const WFLAG = true
+      let repeating = this.resetFormat.repeating
+      let _arr = []
       let initArr = this.createRound(this.math)(
         this.value,
         this.resetFormat.precision
       )
         .toString()
-        .split("")
-        .reverse();
-      if (this.value < 0) initArr = initArr.slice(0, -1);
+        .split('')
+        .reverse()
+      if (this.value < 0) initArr = initArr.slice(0, -1)
 
-      let radixFlag = !initArr.includes(this.resetFormat.radix);
+      let radixFlag = !initArr.includes(this.resetFormat.radix)
 
       initArr.forEach(item => {
-        let flag = false;
+        let flag = false
 
-        if (item == this.resetFormat.radix) {
-          radixFlag = true;
-          _arr.unshift(item);
+        if (item === this.resetFormat.radix) {
+          radixFlag = true
+          _arr.unshift(item)
         } else {
           if (radixFlag) {
-            flag = false;
+            flag = false
 
-            while (WFLAG) {
+            while (1 < 2) {
               if (!repeating.length) {
                 if (flag) {
-                  throw new Error("Bad odometer format without digits");
+                  throw new Error('Bad odometer format without digits')
                 }
-                repeating = this.resetFormat.repeating;
-                flag = true;
+                repeating = this.resetFormat.repeating
+                flag = true
               }
 
-              let chr = repeating[repeating.length - 1];
-              repeating = repeating.substring(0, repeating.length - 1);
-              if (chr === "d") {
-                break;
+              let chr = repeating[repeating.length - 1]
+              repeating = repeating.substring(0, repeating.length - 1)
+              if (chr === 'd') {
+                break
               }
 
-              _arr.unshift(chr);
+              _arr.unshift(chr)
             }
           }
 
-          _arr.unshift(item);
+          _arr.unshift(item)
         }
-      });
+      })
 
-      if (this.value < 0) _arr.unshift("-");
-      return _arr;
+      if (this.value < 0) _arr.unshift('-')
+      return _arr
     }
   },
   watch: {
     // 维护state,初始、新生成的dom有动画
     valueFormat: {
-      handler(nVal, oVal) {
-        this.state = false;
+      handler (nVal, oVal) {
+        this.state = false
         _.debounce(() => {
-          this.state = true;
-        }, 1)();
+          this.state = true
+        }, 1)()
       },
       immediate: true
     }
   },
-  data() {
+  data () {
     return {
       state: false
-    };
+    }
   },
-  mounted() {},
+  mounted () {},
   methods: {
-    getTime(time) {
-      return time ? `${parseFloat(time / 1000)}s` : time;
+    getTime (time) {
+      return time ? `${parseFloat(time / 1000)}s` : time
     },
-    createRound(methodName) {
-      let func = Math[methodName];
-      return function(number, precision) {
-        precision = precision == null ? 0 : Math.min(precision, 292);
+    createRound (methodName) {
+      let func = Math[methodName]
+      return function (number, precision) {
+        precision = precision == null ? 0 : Math.min(precision, 292)
         if (precision && number) {
-          let pair = (String(number) + "e").split("e"),
-            value = func(pair[0] + "e" + (+pair[1] + precision));
+          let pair = (String(number) + 'e').split('e')
+          let value = func(pair[0] + 'e' + (+pair[1] + precision))
 
-          pair = (String(value) + "e").split("e");
-          return +(pair[0] + "e" + (+pair[1] - precision));
+          pair = (String(value) + 'e').split('e')
+          return +(pair[0] + 'e' + (+pair[1] - precision))
         }
-        return func(number);
-      };
+        return func(number)
+      }
     }
   }
-};
+}
 </script>
 
 <style scoped>

+ 11 - 9
src/components/digit-roll/utils/index.js

@@ -6,19 +6,21 @@
  * @Description:
  */
 export default class {
-  constructor() { }
+  constructor () {
+    throw new Error('该类不能被实例化')
+  }
 
   // 防抖动
-  static debounce(fn, delay = 200) {
-    let timer = null;
+  static debounce (fn, delay = 200) {
+    let timer = null
     return function () {
-      let context = this;
-      let args = arguments;
+      let context = this
+      let args = arguments
 
-      clearTimeout(timer);
+      clearTimeout(timer)
       timer = setTimeout(function () {
-        fn.apply(context, args);
-      }, delay);
-    };
+        fn.apply(context, args)
+      }, delay)
+    }
   }
 }

+ 24 - 0
src/libs/tools.js

@@ -0,0 +1,24 @@
+/**
+ * @param {Number} money 大额数值
+ * @param {Number} fiexed 保留几位数
+ * @returns {Number} 无单位的数值
+ */
+export const getBigNumber = (money, fiexed = 2) => {
+  if (money >= 10000) {
+    return Number((Number(money) / 10000).toFixed(fiexed))
+  } else {
+    return Number(money)
+  }
+}
+/**
+ * @param {Number} money 大额数值
+ * @param {Number} fiexed 保留几位数
+ * @returns {String} 单位是万
+ */
+export const getBigNumberWithUint = (money, fiexed = 2) => {
+  if (money >= 10000) {
+    return getBigNumber(money, fiexed) + '万'
+  } else {
+    return money
+  }
+}

+ 6 - 1
src/main.js

@@ -12,7 +12,7 @@ import store from './store'
 import 'reset.css'
 import 'babel-polyfill'
 import * as filters from './filters'
-
+import VueTianditu from 'vue-tianditu'
 import ElementUI from 'element-ui'
 import 'element-ui/lib/theme-chalk/index.css'
 import '@/assets/css/element-variables.scss'
@@ -23,6 +23,11 @@ Object.keys(filters).forEach(key => {
   Vue.filter(key, filters[key])
 })
 
+Vue.use(VueTianditu, {
+  v: '4.0',
+  tk: 'c1dc742aa22263a258fdc7b2a9ae8172'
+})
+
 Vue.config.productionTip = false
 
 new Vue({

+ 19 - 0
src/route/index.js

@@ -7,6 +7,7 @@
  */
 import Vue from 'vue'
 import Router from 'vue-router'
+import _import from './_import'
 import whiteList from './white-list'
 import { filtersPermisList } from './permis-list'
 import store from '@/store'
@@ -17,6 +18,24 @@ const router = new Router({
   // mode: 'history',
   base: '/screen/',
   routes: [
+    {
+      path: '/a1-screen',
+      component: _import('a1-screen'),
+      meta: {
+        title: 'a1屏',
+        hideInMenu: false,
+        icon: ''
+      }
+    },
+    {
+      path: '/a2-screen',
+      component: _import('a2-screen'),
+      meta: {
+        title: 'a2屏',
+        hideInMenu: false,
+        icon: ''
+      }
+    },
     ...whiteList
   ]
 })

+ 40 - 0
src/views/a1-screen/index.vue

@@ -0,0 +1,40 @@
+<template>
+    <div class="screen">
+      <Title />
+      <div class="screen-content">
+        <div class="display-flex">
+          <OnlineWater class="online-water" />
+          <OnlinePay class="margin-l-30 flex-1" />
+        </div>
+        <div class="display-flex margin-t-30">
+          <OnlinePayWeek class="flex-1" />
+          <OnlinePayDay class="flex-1 margin-l-30" />
+        </div>
+      </div>
+    </div>
+</template>
+<script>
+import Title from '@/views/components/title'
+import OnlineWater from '../components/online-water'
+import OnlinePay from '../components/online-pay'
+import OnlinePayWeek from '../components/online-pay-week'
+import OnlinePayDay from '../components/online-pay-day'
+
+export default {
+  name: 'A1Screen',
+  components: {
+    Title,
+    OnlineWater,
+    OnlinePay,
+    OnlinePayWeek,
+    OnlinePayDay
+  }
+}
+</script>
+<style lang="scss">
+@import '@/assets/css/function.scss';
+@import '@/assets/css/screen.scss';
+.online-water.card{
+  width: halfW(690);
+}
+</style>

+ 45 - 0
src/views/a2-screen/index.vue

@@ -0,0 +1,45 @@
+<template>
+  <div class="screen">
+    <Title />
+    <div class="screen-content display-flex">
+       <div class="screen-l margin-r-30">
+        <CommunityMap class="community-map" />
+       </div>
+       <div class="screen-r flex-1">
+          <User />
+          <div class="display-flex margin-t-30">
+            <Resident class="margin-r-30"/>
+            <CommunityType />
+          </div>
+       </div>
+    </div>
+  </div>
+</template>
+<script>
+import Title from '@/views/components/title'
+import CommunityType from '@/views/components/community-type'
+import Resident from '@/views/components/resident'
+import User from '@/views/components/user'
+import CommunityMap from '@/views/components/community-map'
+
+export default {
+  name: 'A2Screen',
+  components: {
+    Title,
+    CommunityType,
+    Resident,
+    User,
+    CommunityMap
+
+  }
+}
+</script>
+<style lang="scss">
+@import '@/assets/css/function.scss';
+@import '@/assets/css/screen.scss';
+
+.screen-l{
+  width: halfW(710);
+}
+
+</style>

+ 2 - 0
src/views/components/card/index.js

@@ -0,0 +1,2 @@
+import Card from './index.vue'
+export default Card

+ 68 - 0
src/views/components/card/index.vue

@@ -0,0 +1,68 @@
+<template>
+    <div class="card">
+        <div class="card-header">
+            <div class="card-lf">
+              <img :src="icon" alt="icon" class="icon"/>
+              <span>{{ title }}</span>
+              <span v-if="subTitle" class="sub-title">({{subTitle}})</span>
+            </div>
+            <div class="card-rg"></div>
+        </div>
+        <div class="card-body">
+          <slot></slot>
+        </div>
+    </div>
+</template>
+
+<script>
+export default {
+  name: 'card',
+  props: {
+    title: {
+      type: String,
+      default: ''
+    },
+    subTitle: {
+      type: String,
+      default: ''
+    },
+    icon: {
+      type: String,
+      default: ''
+    }
+  }
+}
+</script>
+<style scoped lang="scss">
+@import '@/assets/css/function.scss';
+
+.card {
+    width: 100%;
+    height: 100%;
+    box-shadow: 0px 2px 5px 0px rgba(0, 0, 0, 0.4);
+    border-radius: 5px;
+    background: linear-gradient(180deg, rgba(14,22,41,1) 0%,rgba(14,22,41,0.6) 100%);
+    .card-header{
+      height: halfH(40);
+      color: rgba(185, 227, 244, 1);
+      font-size: halfW(14);
+      line-height: halfH(40);
+      padding: 0 halfW(20);
+      background: #111C30;
+      .icon{
+        width: halfW(24);
+        height: halfH(24);
+        vertical-align: middle;
+        margin-right: halfW(13);
+        margin-top: halfH(-4);
+      }
+      .sub-title{
+        font-size: halfW(12);
+      }
+    }
+    .card-body{
+      padding: halfH(30) halfW(30);
+      box-sizing: border-box;
+    }
+}
+</style>

+ 146 - 0
src/views/components/community-map/components/map-list.vue

@@ -0,0 +1,146 @@
+<!--
+ * @Author: Wzh
+ * @Date: 2020-01-23 10:48:49
+ * @LastEditors: Wzh
+ * @LastEditTime: 2020-02-19 15:10:29
+ * @Description: 地图左下列表
+ -->
+<template>
+    <div
+      ref="customOverlay"
+      class="map-list-container"
+      v-show="isShow"
+    >
+      <div class="header">
+          <p class="list-name inline-block" v-text="title"></p>
+          <p class="list-count inline-block right" v-text="extra"></p>
+      </div>
+
+      <!-- <WcScrollList :list="list" class="list">
+          <template v-slot:default="{ info }">
+          <p class="list-name inline-block" v-text="info.label"></p>
+          <p class="list-count inline-block right" v-text="info.content"></p>
+          </template>
+      </WcScrollList> -->
+    </div>
+</template>
+
+<script>
+// import WcScrollList from '_c/wc-scroll-list/wc-scroll-list.vue'
+
+export default {
+  components: {
+    // WcScrollList
+  },
+  name: 'MapList',
+  props: {
+    title: {
+      default: '省份'
+    },
+    extra: {
+      default: '数量'
+    },
+    list: {
+      default: function () {
+        return [
+          {
+            label: '',
+            content: ''
+          }
+        ]
+      }
+    },
+    /**
+     * 相对父元素左上角的绝对位置
+     */
+    position: {
+      default: function () {
+        return {
+          top: 0,
+          left: 0
+        }
+      }
+    },
+    isShow: {
+      default: true
+    }
+  },
+  watch: {
+    position: {
+      handler () {
+        this.draw()
+      },
+      deep: true
+    }
+  },
+  methods: {
+    draw () {
+      if (this.$refs.customOverlay) {
+        let el = this.$refs.customOverlay
+        for (const key in this.position) {
+          if (this.position.hasOwnProperty(key)) {
+            el.style[key] = this.position[key] + 'px'
+          }
+        }
+      }
+    }
+  },
+  mounted () {
+    this.draw()
+  }
+}
+</script>
+
+<style lang="scss">
+  @import "@/assets/css/theme.scss";
+  @import "@/assets/css/mixin.scss";
+.map-list-container {
+  position: absolute;
+  height: halfH(482);
+  width: halfW(330);
+  border-radius: 6px;
+  background:rgba(10,25,43,0.6);
+  border:1px solid rgba(19,51,88,1);
+  overflow: hidden;
+
+  .inline-block {
+    display: inline-block;
+  }
+
+  .right {
+    float: right;
+  }
+
+  .header {
+    height:halfH(58);
+    padding: 0px 20px;
+    line-height:halfH(58);
+    background:rgba(34,127,233,0.6);
+    font-size:20px;
+    font-family:Hiragino Sans GB;
+    font-weight:bold;
+    color:rgba(255,255,255,1);
+  }
+
+  .list {
+    padding: 20px;
+    top: halfH(58);
+    font-size:16px;
+    font-family:Hiragino Sans GB;
+    font-weight:normal;
+    color:rgba(255,255,255,1);
+
+    .list-name {
+      height: halfH(30);
+      width: 70%;
+      @include text-ellipsis;
+    }
+    .list-count {
+      text-align: right;
+      width: 30%;
+      white-space: nowrap;
+    }
+  }
+
+}
+</style>

BIN
src/views/components/community-map/images/icon-title.png


BIN
src/views/components/community-map/images/map-mark-icon.png


+ 2 - 0
src/views/components/community-map/index.js

@@ -0,0 +1,2 @@
+import CommunityMap from './index.vue'
+export default CommunityMap

+ 157 - 0
src/views/components/community-map/index.vue

@@ -0,0 +1,157 @@
+<template>
+    <Card :title="title" :icon="icon" class="community-map">
+      <div class="map-con">
+        <tdt-map style="position: relative;z-index: 0;" mapStyle="indigo" :center="[
+            105,
+            34,
+          ]"
+          :zoom="5"
+          :minZoom="5"
+          :maxZoom="5"
+          :controls="[
+            {
+              name: 'Scale',
+              position: 'topright'
+            },]"
+        >
+        <!-- <div v-if="provinceList.length"> -->
+
+          <tdt-marker-clusterer
+              v-for="item in provinceList"
+              :key="item.label + 'clusterer'"
+              :markers="[{
+                icon: {
+                  iconUrl: require('./images/map-mark-icon.png'),
+                  iconSize: [24, 24]
+                },
+                position: [item.point.lng, item.point.lat]
+              }]"
+              >
+            </tdt-marker-clusterer>
+            <tdt-label
+              v-for="(item, i) in provinceList"
+              :key="`${i}-label`"
+              :position="[item.point.lng, item.point.lat]"
+              :text="item.label">
+            </tdt-label>
+          <!-- </div> -->
+        </tdt-map>
+        <MapList title="省份" :isShow="provinceList.length" :list="provinceList" :position="{left: 30, bottom: 30}"></MapList>
+      </div>
+    </Card>
+  </template>
+<script>
+import provincePosition from './province-positon'
+// import { screen } from '@/api'
+import Card from '@/views/components/card'
+import icon from './images/icon-title.png'
+import MapList from './components/map-list.vue'
+export default {
+  name: 'CommunityMap',
+  components: {
+    Card,
+    MapList
+  },
+  data () {
+    return {
+      title: '项目地区分布',
+      icon: icon,
+      provinceList: [],
+      state: {
+        center: [113.280637, 23.125178],
+        zoom: 12
+      }
+    }
+  },
+  mounted () {
+    setTimeout(() => {
+      this.mapInit()
+    }, 500)
+    // this.getProjectStatistics()
+  },
+  methods: {
+    mapInit () {
+      const _data = [
+        {
+          provinceName: '海南省',
+          count: 100
+        },
+        {
+          provinceName: '广东省',
+          count: 200
+        },
+        {
+          provinceName: '四川省',
+          count: 300
+        },
+        {
+          provinceName: '贵州省',
+          count: 400
+        },
+        {
+          provinceName: '云南省',
+          count: 500
+        },
+        {
+          provinceName: '西藏自治区',
+          count: 600
+        },
+        {
+          provinceName: '陕西省',
+          count: 700
+        },
+        {
+          provinceName: '甘肃省',
+          count: 800
+        }
+      ]
+      let arr = []
+      _data.forEach((item, i) => {
+        let cName = item.provinceName.substring(0, 2)
+        let province = provincePosition.find(p => p.name.indexOf(cName) !== -1)
+        let ele = {
+          label: province.name,
+          content: item.count,
+          point: {
+            lng: province.geoCoord[0],
+            lat: province.geoCoord[1]
+          }
+        }
+        arr.push(ele)
+      })
+      this.provinceList = arr
+    }
+    // getProjectStatistics () {
+    //   this.provinceList = []
+    //   screen.getProjectStatistics()
+    //     .then(({ data }) => {
+    //       if (data.code === '200') {
+    //         let _data = data.data
+    //         let arr = []
+    //         _data.provinceStatistics.forEach((item, i) => {
+    //           let cName = item.provinceName.substring(0, 2)
+    //           let province = provincePosition.find(p => p.name.indexOf(cName) !== -1)
+    //           let ele = {
+    //             label: province.name,
+    //             content: item.count,
+    //             point: {
+    //               lng: province.geoCoord[0],
+    //               lat: province.geoCoord[1]
+    //             }
+    //           }
+    //           arr.push(ele)
+    //         })
+    //         this.provinceList = arr
+    //       }
+    //     })
+    // }
+  }
+}
+</script>
+<style lang="scss" scoped>
+  @import "@/assets/css/theme.scss";
+  @import "@/assets/css/mixin.scss";
+  .map-con {
+    position: relative;
+  }
+</style>

+ 279 - 0
src/views/components/community-map/province-positon.js

@@ -0,0 +1,279 @@
+const provincePosition = [
+  // 23省
+  {
+    name: '甘肃',
+    abb: '甘',
+    geoCoord: [
+      103.73,
+      36.03
+    ]
+  },
+  {
+    name: '青海',
+    abb: '青',
+    geoCoord: [
+      101.74,
+      36.56
+    ]
+  },
+  {
+    name: '四川',
+    abb: '川',
+    geoCoord: [
+      104.06,
+      30.67
+    ]
+  },
+  {
+    name: '河北',
+    abb: '冀',
+    geoCoord: [
+      114.48,
+      38.03
+    ]
+  },
+  {
+    name: '云南',
+    abb: '滇',
+    geoCoord: [
+      102.73,
+      25.04
+    ]
+  },
+  {
+    name: '贵州',
+    abb: '黔',
+    geoCoord: [
+      106.71,
+      26.57
+    ]
+  },
+  {
+    name: '湖北',
+    abb: '鄂',
+    geoCoord: [
+      114.31,
+      30.52
+    ]
+  },
+  {
+    name: '河南',
+    abb: '豫',
+    geoCoord: [
+      113.65,
+      34.76
+    ]
+  },
+  {
+    name: '山东',
+    abb: '鲁',
+    geoCoord: [
+      117,
+      36.65
+    ]
+  },
+  {
+    name: '江苏',
+    abb: '苏',
+    geoCoord: [
+      118.78,
+      32.04
+    ]
+  },
+  {
+    name: '安徽',
+    abb: '皖',
+    geoCoord: [
+      117.27,
+      31.86
+    ]
+  },
+  {
+    name: '浙江',
+    abb: '浙',
+    geoCoord: [
+      120.19,
+      30.26
+    ]
+  },
+  {
+    name: '江西',
+    abb: '赣',
+    geoCoord: [
+      115.89,
+      28.68
+    ]
+  },
+  {
+    name: '福建',
+    abb: '闽',
+    geoCoord: [
+      119.3,
+      26.08
+    ]
+  },
+  {
+    name: '广东',
+    abb: '粤',
+    geoCoord: [
+      113.23,
+      23.16
+    ]
+  },
+  {
+    name: '湖南',
+    abb: '湘',
+    geoCoord: [
+      113,
+      28.21
+    ]
+  },
+  {
+    name: '海南',
+    abb: '琼',
+    geoCoord: [
+      110.35,
+      20.02
+    ]
+  },
+  {
+    name: '辽宁',
+    abb: '辽',
+    geoCoord: [
+      123.38,
+      41.8
+    ]
+  },
+  {
+    name: '吉林',
+    abb: '吉',
+    geoCoord: [
+      125.35,
+      43.88
+    ]
+  },
+  {
+    name: '黑龙江',
+    abb: '黑',
+    geoCoord: [
+      126.63,
+      45.75
+    ]
+  },
+  {
+    name: '山西',
+    abb: '晋',
+    geoCoord: [
+      112.53,
+      37.87
+    ]
+  },
+  {
+    name: '陕西',
+    abb: '陕',
+    geoCoord: [
+      108.95,
+      34.27
+    ]
+  },
+  {
+    name: '台湾',
+    abb: '台',
+    geoCoord: [
+      121.30,
+      25.03
+    ]
+  },
+  // 4直辖市
+  {
+    name: '北京',
+    abb: '京',
+    geoCoord: [
+      116.46,
+      39.92
+    ]
+  },
+  {
+    name: '上海',
+    abb: '沪',
+    geoCoord: [
+      121.48,
+      31.22
+    ]
+  },
+  {
+    name: '重庆',
+    abb: '渝',
+    geoCoord: [
+      106.54,
+      29.59
+    ]
+  },
+  {
+    name: '天津',
+    abb: '津',
+    geoCoord: [
+      117.2,
+      39.13
+    ]
+  },
+  // 5自治区
+  {
+    name: '内蒙古',
+    abb: '蒙',
+    geoCoord: [
+      111.65,
+      40.82
+    ]
+  },
+  {
+    name: '广西',
+    abb: '桂',
+    geoCoord: [
+      108.33,
+      22.84
+    ]
+  },
+  {
+    name: '西藏',
+    abb: '藏',
+    geoCoord: [
+      91.11,
+      29.97
+    ]
+  },
+  {
+    name: '宁夏',
+    abb: '宁',
+    geoCoord: [
+      106.27,
+      38.47
+    ]
+  },
+  {
+    name: '新疆',
+    abb: '新',
+    geoCoord: [
+      87.68,
+      43.77
+    ]
+  },
+  // 2特别行政区
+  {
+    name: '香港',
+    abb: '港',
+    geoCoord: [
+      114.17,
+      22.28
+    ]
+  },
+  {
+    name: '澳门',
+    abb: '澳',
+    geoCoord: [
+      113.54,
+      22.19
+    ]
+  }
+]
+export default provincePosition

+ 0 - 0
src/views/components/community-type/components/bar.vue


+ 343 - 0
src/views/components/community-type/components/three-pie.vue

@@ -0,0 +1,343 @@
+<!--
+ * @Author: Wzh
+ * @Date: 2020-01-15 17:18:57
+ * @LastEditors: Wzh
+ * @LastEditTime: 2020-02-11 11:02:12
+ * @Description:
+ -->
+<template>
+    <div ref="dom" class="charts chart-pie"></div>
+</template>
+
+<script>
+import * as echarts from 'echarts'
+// import tdTheme from '_c/charts/theme.json'
+// import mixin from '_c/charts/mixin.js'
+// echarts.registerTheme('tdTheme', tdTheme)
+export default {
+  name: 'ChartPie',
+  // mixins: [mixin],
+  props: {
+    value: Array,
+    text: String,
+    subtext: String,
+    legendIcons: {
+      default: function () {
+        return []
+      }
+    }
+  },
+  watch: {
+    value: {
+      handler: function (val) {
+        this.updateValue()
+      },
+      deep: true
+    }
+  },
+  computed: {
+    legendIconsConvert () {
+      let arr = []
+      this.legendIcons.forEach((item, i) => {
+        if (item.indexOf('data:image/') === 0) {
+          arr.push('image://' + item)
+        } else {
+          arr.push(item)
+        }
+      })
+      return arr
+    },
+    all () {
+      return this.value.map(_ => _.value).reduce((all, item) => {
+        return Number(all) + Number(item)
+      })
+    }
+  },
+  data () {
+    return {
+      titleStyle: {
+        fontSize: 14,
+        fontFamily: 'Microsoft YaHei',
+        fontWeight: '400',
+        lineHeight: 14,
+        color: '#FFFFFF'
+      },
+      legendStyle: {
+        padding: [5, 0, 0, 20],
+        rich: {
+          title: {
+            fontSize: 17,
+            fontFamily: 'Microsoft YaHei',
+            fontWeight: '400',
+            color: '#5774A2',
+            align: 'left'
+          },
+          detail: {
+            align: 'left',
+            lineHeight: 25,
+            fontSize: 18,
+            fontFamily: 'Microsoft YaHei',
+            fontWeight: 'bold',
+            color: '#01DFFC'
+          }
+        }
+      },
+      dom: {}
+    }
+  },
+  methods: {
+    legendFormatter (name) {
+      // let all = 0
+      // for (const item of this.value) {
+      //   all += Number(item.value)
+      // }
+      let val = this.value.find(item => item.name === name).value
+      // let percent = ((Number(val) / all) * 100).toFixed(2) + '%'
+      return `{title|${name}}\n{detail|${val}}`
+    },
+    updateValue () {
+      let legend = this.value.map((_, i) => {
+        return { name: _.name, icon: this.legendIconsConvert[i] }
+      })
+      let percents = []
+      let radius = this.value.map(_ => _.value).map((num) => {
+        let nums = Math.round(this.all === 0 ? 0 : (Number(num) / this.all) * 100)
+        percents.push(nums)
+        return nums > 40 ? 40 : nums < 5 ? 5 : nums
+      })
+
+      let option = {
+        title: {
+          text: this.text,
+          subtext: this.subtext,
+          x: '19%',
+          y: '50%',
+          textAlign: 'center',
+          textVerticalAlign: 'middle',
+          textStyle: this.titleStyle
+        },
+        tooltip: {
+          trigger: 'item',
+          formatter: '{b} : {c} ({d}%)'
+        },
+        legend: {
+          orient: 'vertical',
+          right: '5%',
+          top: 'center',
+          data: legend,
+          itemHeight: 46,
+          itemWidth: 46,
+          itemGap: 20,
+          selectedMode: false,
+          formatter: this.legendFormatter,
+          textStyle: this.legendStyle
+        },
+        graphic: [
+          {
+            type: 'group',
+            left: '45%',
+            top: 'middle',
+            silent: true,
+            children: [
+              {
+                type: 'circle',
+                top: 'middle',
+                shape: {
+                  r: 2
+                },
+                style: {
+                  fill: '#5A729D'
+                }
+              },
+              {
+                type: 'line',
+                top: 'middle',
+                shape: {
+                  x1: 0,
+                  y1: 0,
+                  x2: 100,
+                  y2: 0
+                },
+                style: {
+                  stroke: '#5A729D'
+                }
+              },
+              {
+                type: 'circle',
+                top: 'middle',
+                position: [100, 0],
+                shape: {
+                  r: 2
+                },
+                style: {
+                  fill: '#5A729D'
+                }
+              }
+            ]
+          },
+          {
+            type: 'group',
+            left: '45%',
+            bottom: '60%',
+            silent: true,
+            rotation: -5.85,
+            children: [
+              {
+                type: 'circle',
+                top: 'middle',
+                shape: {
+                  r: 2
+                },
+                style: {
+                  fill: '#5A729D'
+                }
+              },
+              {
+                type: 'line',
+                top: 'middle',
+                shape: {
+                  x1: 0,
+                  y1: 0,
+                  x2: 110,
+                  y2: 0
+                },
+                style: {
+                  stroke: '#5A729D'
+                }
+              },
+              {
+                type: 'circle',
+                top: 'middle',
+                position: [110, 0],
+                shape: {
+                  r: 2
+                },
+                style: {
+                  fill: '#5A729D'
+                }
+              }
+            ]
+          },
+          {
+            type: 'group',
+            left: '45%',
+            top: '60%',
+            silent: true,
+            rotation: 5.85,
+            children: [
+              {
+                type: 'circle',
+                top: 'middle',
+                shape: {
+                  r: 2
+                },
+                style: {
+                  fill: '#5A729D'
+                }
+              },
+              {
+                type: 'line',
+                top: 'middle',
+                shape: {
+                  x1: 0,
+                  y1: 0,
+                  x2: 110,
+                  y2: 0
+                },
+                style: {
+                  stroke: '#5A729D'
+                }
+              },
+              {
+                type: 'circle',
+                top: 'middle',
+                position: [110, 0],
+                shape: {
+                  r: 2
+                },
+                style: {
+                  fill: '#5A729D'
+                }
+              }
+            ]
+          }
+        ],
+        series: [
+          {
+            type: 'pie',
+            color: ['#0D172A'],
+            radius: [radius[0] + '%', radius[0] + Math.min(percents[0] / 10 + 4, 10) + '%'],
+            center: ['32%', '31%'],
+            label: {
+              show: true,
+              color: '#fff',
+              position: 'center',
+              formatter: percents[0] + '%'
+            },
+            silent: true,
+            itemStyle: {
+              color: new echarts.graphic.LinearGradient(
+                0, 0, 0, 1, [
+                  { offset: 0, color: '#43D3C7' },
+                  { offset: 1, color: '#2D32F0' }
+                ])
+            },
+            data: [this.value[0]]
+          },
+          {
+            type: 'pie',
+            color: ['#0D172A'],
+            radius: [radius[1] + '%', radius[1] + Math.min(percents[1] / 10 + 4, 10) + '%'],
+            center: ['13%', '38%'],
+            label: {
+              show: true,
+              color: '#fff',
+              position: 'center',
+              formatter: percents[1] + '%'
+            },
+            silent: true,
+            itemStyle: {
+              color: new echarts.graphic.LinearGradient(
+                0, 0, 0, 1, [
+                  { offset: 0, color: '#2E38EE' },
+                  { offset: 1, color: '#EE9178' }
+                ])
+            },
+            data: [this.value[1]]
+          },
+          {
+            type: 'pie',
+            silent: true,
+            startAngle: 45,
+            clockwise: false,
+            minAngle: 10,
+            radius: [radius[2] + '%', radius[2] + Math.min(percents[2] / 10 + 4, 10) + '%'],
+            center: ['25%', '73%'],
+            itemStyle: {
+              color: new echarts.graphic.LinearGradient(
+                0, 0, 0, 1, [
+                  { offset: 0, color: '#D6595D' },
+                  { offset: 1, color: '#D0A971' }
+                ])
+            },
+            label: {
+              show: true,
+              color: '#fff',
+              position: 'center',
+              formatter: percents[2] + '%'
+            },
+            data: [this.value[2]]
+          }
+        ]
+      }
+      this.dom.setOption(option)
+    }
+  },
+  mounted () {
+    this.$nextTick(() => {
+      this.dom = echarts.init(this.$refs.dom, 'tdTheme')
+      this.updateValue()
+    })
+  }
+}
+</script>

BIN
src/views/components/community-type/images/icon-title.png


+ 2 - 0
src/views/components/community-type/index.js

@@ -0,0 +1,2 @@
+import CommunityType from './index.vue'
+export default CommunityType

+ 45 - 0
src/views/components/community-type/index.vue

@@ -0,0 +1,45 @@
+<template>
+    <Card :title="title" :icon="icon" class="community-type">
+      <ThreePie :value="value" :legendIcons="legendIcons" :text="text" :subtext="subtext"></ThreePie>
+    </Card>
+  </template>
+<script>
+// import echarts from 'echarts'
+import Card from '@/views/components/card'
+import icon from './images/icon-title.png'
+import ThreePie from './components/three-pie.vue'
+export default {
+  name: 'CommunityType',
+  components: {
+    Card,
+    ThreePie
+  },
+  data () {
+    return {
+      title: '项目类型',
+      icon: icon,
+      value: [
+        {
+          value: 100,
+          name: '项目类型1'
+        },
+        {
+          value: 200,
+          name: '项目类型2'
+        },
+        {
+          value: 300,
+          name: '项目类型3'
+        }
+      ],
+      legendIcons: [
+        'images/icon-1.png',
+        'images/icon-2.png',
+        'images/icon-3.png'
+      ],
+      text: '项目类型',
+      subtext: '项目类型占比'
+    }
+  }
+}
+</script>

BIN
src/views/components/online-pay-day/images/icon-title.png


+ 2 - 0
src/views/components/online-pay-day/index.js

@@ -0,0 +1,2 @@
+import OnlinePayDay from './index.vue'
+export default OnlinePayDay

+ 394 - 0
src/views/components/online-pay-day/index.vue

@@ -0,0 +1,394 @@
+<template>
+    <Card :title="title" :subTitle="subTitle" :icon="icon" class="online-pay-day">
+      <div class="info margin-r-20">
+        <div class="title">
+          <p class="p1">线上缴费</p>
+          <p class="p2">日热度统计</p>
+          <p class="p3">(近12月日平均)</p>
+        </div>
+        <div class="legend">
+          <p class="legend1">
+            <span class="legend1-color"></span>
+            <span>时段缴费</span>
+          </p>
+          <p class="legend2">
+            <span class="legend2-color"></span>
+            <span>时段占比</span>
+          </p>
+          <p class="legend3">
+            <span class="legend3-color"><b class="inner"></b></span>
+            <span>时段比例</span>
+          </p>
+        </div>
+      </div>
+      <div ref="onlinePayDayBar" class="online-pay-day-bar"></div>
+    </Card>
+  </template>
+<script>
+import * as echarts from 'echarts'
+// import { getBigNumberWithUint } from '@/libs/tools.js'
+import Card from '@/views/components/card'
+import icon from './images/icon-title.png'
+
+export default {
+  name: 'OnlinePayDay',
+  components: {
+    Card
+  },
+  data () {
+    return {
+      title: '线上缴费日热度',
+      subTitle: '近12个月',
+      icon: icon
+    }
+  },
+  mounted () {
+    this.initChart()
+  },
+  methods: {
+    /**
+     * 获取一个和max最接近的能被5整除的无零头整数
+     */
+    getMax (max) {
+      if (max <= 10) return 10
+
+      let pow = max.toString().length - 2
+      pow = Math.pow(10, pow)
+      max = Math.ceil(max / pow / 10) * 10 * pow
+      return max
+    },
+    initChart () {
+      const myChart = echarts.init(this.$refs.onlinePayDayBar)
+      const xAxisData = ['01:00', '04:00', '07:00', '10:00', '13:00', '16:00', '19:00', '22:00']
+      const seriesData = [10, 20, 36, 10, 10, 20, 40, 25]
+      let all = seriesData.reduce((total, num) => {
+        return Number(total) + Number(num)
+      })
+      let markPointData = []
+
+      seriesData.forEach((item, i) => {
+        const value = (all > 0 ? (Number(item) / all) * 100 : 0).toFixed(1) + '%'
+        markPointData.push({
+          value,
+          xAxis: i,
+          yAxis: item,
+          itemStyle: {
+            opacity: xAxisData[i].indexOf('hide') !== -1 ? 0 : 1
+          }
+        })
+      })
+      let lineData = []
+
+      let min = seriesData.reduce((min, num) => {
+        return Math.min(Number(min), Number(num))
+      })
+
+      let max = seriesData.reduce((min, num) => {
+        return Math.max(Number(min), Number(num))
+      })
+
+      seriesData.forEach((item, i) => {
+        lineData.push(Number(item) - min * 0.5)
+      })
+      const textSize = (text, fontSize) => {
+        var span = document.createElement('span')
+        var result = {
+          'width': span.offsetWidth,
+          'height': span.offsetHeight
+        }
+        span.style.visibility = 'hidden'
+        span.style.fontSize = fontSize || '14px'
+        document.body.appendChild(span)
+
+        if (typeof span.textContent !== 'undefined') { span.textContent = text || '国' } else span.innerText = text || '国'
+
+        result.width = span.offsetWidth - result.width
+        result.height = span.offsetHeight - result.height
+        span.parentNode.removeChild(span)
+        return result
+      }
+      const option = {
+        tooltip: {},
+        legend: {
+          show: false
+        },
+        grid: {
+          top: '40px',
+          bottom: '0px',
+          left: '0px',
+          right: '0px',
+          containLabel: true
+        },
+        xAxis: {
+          axisLabel: {
+            color: '#fff',
+            margin: 15,
+            fontSize: 14,
+            formatter: function (val, idx) {
+              let value = xAxisData[idx]
+              return value
+            }
+          },
+          axisLine: {
+            show: true,
+            lineStyle: {
+              color: '#666',
+              opacity: 1,
+              cap: 'round'
+            }
+          },
+          boundaryGap: false,
+          axisTick: {
+            alignWithLabel: true,
+            length: 7,
+            lineStyle: {
+              width: 3,
+              color: '#fff',
+              opacity: 0.5
+            }
+          },
+          splitLine: {
+            show: true,
+            lineStyle: {
+              color: '#fff',
+              opacity: 0.3,
+              cap: 'round',
+              type: [5, 10]
+            }
+          },
+          max: function (value) { // x轴左侧留白
+            return value.max + 0.3
+          },
+          min: function (value) { // x轴左侧留白
+            return -0.3
+          },
+          data: xAxisData
+        },
+        yAxis: [
+          {
+            axisLabel: {
+              color: '#fff',
+              margin: 25,
+              fontSize: 14
+            },
+            axisLine: {
+              show: false,
+              lineStyle: {
+                color: '#fff'
+              }
+            },
+            axisTick: {
+              length: 14,
+              lineStyle: {
+                width: 2,
+                fontSize: 16
+              }
+            },
+            splitLine: {
+              show: true,
+              lineStyle: {
+                color: '#fff',
+                opacity: 0.3,
+                cap: 'round',
+                type: 'dashed',
+                dashOffset: 5
+              }
+            }
+          },
+          {
+            type: 'value',
+            position: 'right',
+            axisLabel: {
+              show: false
+            },
+            axisTick: {
+              show: true,
+              length: 14,
+              lineStyle: {
+                width: 2,
+                fontSize: 16
+              }
+            },
+            axisLine: {
+              show: false
+            }
+          }
+        ],
+        series: [
+          {
+            type: 'line',
+            silent: true,
+            symbolSize: 10,
+            yAxisIndex: 0,
+            itemStyle: {
+              color: '#FFE1D4',
+              borderColor: 'rgba(255, 162, 41, 0.7)',
+              borderWidth: 3
+            },
+            lineStyle: {
+              opacity: 0
+            },
+            markPoint: {
+              symbol: 'path://m 0,0 h 48 a 5 5 0 0 1 4 4 v 20 a 5 5 0 0 1 -4 4 h -18 l -5,5 l -5,-5 h -18 a 5 5 0 0 1 -4 -4 v -20 a 5 5 0 0 1 4 -4 z', // 带下箭头的圆角矩形
+              symbolSize: function (val) {
+                return [textSize(val, '14px').width + 20, 35] // 设置宽高
+              },
+              itemStyle: {
+                color: '#262BB3' // %值的背景颜色
+              },
+              symbolOffset: ['0', '-70%'], // 相对位置
+              symbolKeepAspect: true, // 是否保持宽高比
+              label: {
+                position: 'insideTop',
+                fontSize: 14,
+                distance: 10
+              },
+              data: markPointData,
+              silent: true
+            },
+            areaStyle: {
+              color: {
+                type: 'linear',
+                x: 0,
+                y: 0,
+                x2: 0,
+                y2: 1,
+                colorStops: [{
+                  offset: 0, color: 'rgba(21, 147, 222, 1)' // 0% 处的颜色
+                }, {
+                  offset: max ? (max - min) / max : 1, color: 'rgba(61,123,248,0)' // 50% 处的颜色
+                }, {
+                  offset: 1, color: 'rgba(61,123,248,0)' // 100% 处的颜色
+                }],
+                global: false // 缺省为 false
+              }
+            },
+            data: lineData
+          },
+          {
+            type: 'bar',
+            barWidth: '25%',
+            labelLine: {
+              show: false
+            },
+            itemStyle: {
+              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+                { offset: 0, color: '#491CC7' },
+                { offset: 1, color: '#E29163' }
+              ])
+            },
+            data: seriesData
+          }]
+      }
+      myChart.setOption(option)
+    }
+  }
+}
+</script>
+<style lang="scss">
+@import '@/assets/css/function.scss';
+.online-pay-day-bar {
+  width: 100%;
+  height: halfH(350);
+}
+.online-pay-day {
+  .card-body{
+    display: flex;
+  }
+  .total{
+    height: halfH(24);
+    line-height: halfH(24);
+    padding: halfH(18) halfW(18);
+    color: #fff;
+    float: left;
+    font-size: halfW(14);
+    border-radius: 5px;
+    background-color: rgba(17, 28, 48, 1);
+    text-align: center;
+    border: 1px solid rgba(0, 123, 211, 0.2);
+  }
+  .img{
+    width: halfW(40);
+    height: halfH(40);
+    margin-right: halfW(27);
+    margin-top: halfH(-7);
+    padding: halfH(8) halfW(8);
+    box-sizing: border-box;
+    background: #12223C;
+    border-radius: 50%;
+    .icon{
+      width: 100%;
+      height: 100%;
+    }
+  }
+  .info{
+      width: halfW(160);
+      height: halfH(350);
+      border: 1px solid rgba(0, 123, 211, 0.2);
+      border-radius: halfW(5) halfH(5);
+      display: flex;
+      flex-direction: column;
+      .p1{
+        font-size: halfW(14);
+        color: #B9E3F4;
+      }
+      .p2{
+        font-size: halfW(18);
+        color: #fff;
+      }
+      .p3{
+        font-size: halfW(12);
+        color: #9FA5B7;
+      }
+    }
+    .title,.legend{
+      padding: halfH(30) halfW(16);
+    }
+    .title{
+      // height: halfH(125);
+      flex: 1;
+      line-height: halfH(40);
+
+    }
+    .legend{
+      color: #808BAD;
+      background: #111C30;
+      font-size: halfW(14);
+      flex: 1;
+      line-height: halfH(40);
+      .legend1-color, .legend2-color{
+        display: inline-block;
+        width: halfW(20);
+        height: halfH(8);
+        margin-right: halfW(10);
+        vertical-align: middle;
+      }
+      .legend1-color{
+        background: linear-gradient(90deg, #FEA373 0%, #FF678B 100%);
+      }
+      .legend2-color{
+        background: linear-gradient(90deg, #0F67F8 0%, #98D7F1 50%, #77ECED 100%);
+      }
+      .legend3-color{
+        display: inline-block;
+        width: halfW(20);
+        height: halfH(20);
+        background: linear-gradient(90deg, #F6D1A7 0%, #F5BD7C 50%, #F4A850 100%);
+        border-radius: 50%;
+        margin-right: halfW(10);
+        position: relative;
+        .inner{
+          display: inline-block;
+          width: halfW(10);
+          height: halfH(10);
+          background: linear-gradient(90deg, #C9FFBF 0%, #FFB0BE 100%);
+          border-radius: 50%;
+          position: absolute;
+          top: 50%;
+          left: 50%;
+          transform: translate(-50%, -50%);
+        }
+      }
+    }
+}
+</style>

BIN
src/views/components/online-pay-week/images/icon-title.png


+ 2 - 0
src/views/components/online-pay-week/index.js

@@ -0,0 +1,2 @@
+import OnlinePayWeek from './index.vue'
+export default OnlinePayWeek

+ 369 - 0
src/views/components/online-pay-week/index.vue

@@ -0,0 +1,369 @@
+<template>
+    <Card :title="title" :subTitle="subTitle" :icon="icon" class="online-pay-week">
+      <div class="info margin-r-20">
+        <div class="title">
+          <p class="p1">线上缴费</p>
+          <p class="p2">周热度统计</p>
+          <p class="p3">(近12月周平均)</p>
+        </div>
+        <div class="legend">
+          <p class="legend1">
+            <span class="legend1-color"></span>
+            <span>日线上缴费</span>
+          </p>
+          <p class="legend2">
+            <span class="legend2-color"></span>
+            <span>日占比</span>
+          </p>
+          <p class="legend3">
+            <span class="legend3-color"><b class="inner"></b></span>
+            <span>日比例</span>
+          </p>
+        </div>
+      </div>
+      <div ref="onlinePayWeekBar" class="online-pay-week-bar"></div>
+    </Card>
+  </template>
+<script>
+import * as echarts from 'echarts'
+// import { getBigNumberWithUint } from '@/libs/tools.js'
+import Card from '@/views/components/card'
+import icon from './images/icon-title.png'
+
+export default {
+  name: 'OnlinePayWeek',
+  components: {
+    Card
+  },
+  data () {
+    return {
+      title: '线上缴费周热度',
+      subTitle: '近12个月',
+      icon: icon
+    }
+  },
+  mounted () {
+    this.initChart()
+  },
+  methods: {
+    /**
+     * 获取一个和max最接近的能被5整除的无零头整数
+     */
+    getMax (max) {
+      if (max <= 10) return 10
+
+      let pow = max.toString().length - 2
+      pow = Math.pow(10, pow)
+      max = Math.ceil(max / pow / 10) * 10 * pow
+      return max
+    },
+    initChart () {
+      const myChart = echarts.init(this.$refs.onlinePayWeekBar)
+      const xAxisData = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
+      const seriesData = [5, 20, 36, 10, 10, 20, 40]
+      let all = seriesData.reduce((total, num) => {
+        return Number(total) + Number(num)
+      })
+      let markPointData = []
+
+      seriesData.forEach((item, i) => {
+        const value = (all > 0 ? (Number(item) / all) * 100 : 0).toFixed(1) + '%'
+        markPointData.push({
+          value,
+          xAxis: i,
+          yAxis: item,
+          itemStyle: {
+            opacity: xAxisData[i].indexOf('hide') !== -1 ? 0 : 1
+          }
+        })
+      })
+      let lineData = []
+
+      let min = seriesData.reduce((min, num) => {
+        return Math.min(Number(min), Number(num))
+      })
+
+      let max = seriesData.reduce((min, num) => {
+        return Math.max(Number(min), Number(num))
+      })
+
+      seriesData.forEach((item, i) => {
+        lineData.push(Number(item) - min * 0.5)
+      })
+      const textSize = (text, fontSize) => {
+        var span = document.createElement('span')
+        var result = {
+          'width': span.offsetWidth,
+          'height': span.offsetHeight
+        }
+        span.style.visibility = 'hidden'
+        span.style.fontSize = fontSize || '14px'
+        document.body.appendChild(span)
+
+        if (typeof span.textContent !== 'undefined') { span.textContent = text || '国' } else span.innerText = text || '国'
+
+        result.width = span.offsetWidth - result.width
+        result.height = span.offsetHeight - result.height
+        span.parentNode.removeChild(span)
+        return result
+      }
+      const option = {
+        tooltip: {},
+        legend: {
+          show: false
+        },
+        grid: {
+          top: '40px',
+          bottom: '0px',
+          left: '0px',
+          right: '0px',
+          containLabel: true
+        },
+        xAxis: {
+          axisLabel: {
+            color: '#fff',
+            margin: 15,
+            fontSize: 14,
+            formatter: function (val, idx) {
+              let value = xAxisData[idx]
+              return value
+            }
+          },
+          axisLine: {
+            show: true,
+            lineStyle: {
+              color: '#666',
+              opacity: 1,
+              cap: 'round'
+            }
+          },
+          boundaryGap: false,
+          axisTick: {
+            alignWithLabel: true,
+            length: 7,
+            lineStyle: {
+              width: 3,
+              color: '#fff',
+              opacity: 0.5
+            }
+          },
+          splitLine: {
+            show: true,
+            lineStyle: {
+              color: '#fff',
+              opacity: 0.3,
+              cap: 'round',
+              type: [5, 10]
+            }
+          },
+          max: function (value) { // x轴左侧留白
+            return value.max + 0.3
+          },
+          min: function (value) { // x轴左侧留白
+            return -0.3
+          },
+          data: xAxisData
+        },
+        yAxis: [
+          {
+            axisLabel: {
+              color: '#fff',
+              margin: 25,
+              fontSize: 14
+            },
+            axisLine: {
+              show: false,
+              lineStyle: {
+                color: '#fff'
+              }
+            },
+            axisTick: {
+              length: 14,
+              lineStyle: {
+                width: 2,
+                fontSize: 16
+              }
+            },
+            splitLine: {
+              show: true,
+              lineStyle: {
+                color: '#fff',
+                opacity: 0.3,
+                cap: 'round',
+                type: 'dashed',
+                dashOffset: 5
+              }
+            }
+          },
+          {
+            type: 'value',
+            position: 'right',
+            axisLabel: {
+              show: false
+            },
+            axisTick: {
+              show: true,
+              length: 14,
+              lineStyle: {
+                width: 2,
+                fontSize: 16
+              }
+            },
+            axisLine: {
+              show: false
+            }
+          }
+        ],
+        series: [
+          {
+            type: 'line',
+            silent: true,
+            symbolSize: 10,
+            yAxisIndex: 0,
+            itemStyle: {
+              color: '#FFE1D4',
+              borderColor: 'rgba(255, 162, 41, 0.7)',
+              borderWidth: 3
+            },
+            lineStyle: {
+              opacity: 0
+            },
+            markPoint: {
+              symbol: 'path://m 0,0 h 48 a 5 5 0 0 1 4 4 v 20 a 5 5 0 0 1 -4 4 h -18 l -5,5 l -5,-5 h -18 a 5 5 0 0 1 -4 -4 v -20 a 5 5 0 0 1 4 -4 z', // 带下箭头的圆角矩形
+              symbolSize: function (val) {
+                return [textSize(val, '14px').width + 20, 35] // 设置宽高
+              },
+              itemStyle: {
+                color: '#262BB3' // 背景颜色
+              },
+              symbolOffset: ['0', '-70%'], // 相对位置
+              symbolKeepAspect: true, // 是否保持宽高比
+              label: {
+                position: 'insideTop',
+                fontSize: 14,
+                distance: 10
+              },
+              data: markPointData,
+              silent: true
+            },
+            areaStyle: {
+              color: {
+                type: 'linear',
+                x: 0,
+                y: 0,
+                x2: 0,
+                y2: 1,
+                colorStops: [{
+                  offset: 0, color: 'rgba(21, 147, 222, 1)' // 0% 处的颜色
+                }, {
+                  offset: max ? (max - min) / max : 1, color: 'rgba(61,123,248,0)' // 50% 处的颜色
+                }, {
+                  offset: 1, color: 'rgba(61,123,248,0)' // 100% 处的颜色
+                }],
+                global: false // 缺省为 false
+              }
+            },
+            data: lineData
+          },
+          {
+            name: '线上流水',
+            type: 'bar',
+            barWidth: '23%',
+            labelLine: {
+              show: false
+            },
+            itemStyle: {
+              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+                { offset: 0, color: '#FEA373' },
+                { offset: 1, color: '#FF678B' }
+              ])
+            },
+            data: seriesData
+          }]
+      }
+      myChart.setOption(option)
+    }
+  }
+}
+</script>
+<style lang="scss">
+@import '@/assets/css/function.scss';
+.online-pay-week-bar {
+  width: 100%;
+  height: halfH(350);
+}
+.online-pay-week {
+  .card-body{
+    display: flex;
+    .info{
+      width: halfW(160);
+      height: halfH(350);
+      border: 1px solid rgba(0, 123, 211, 0.2);
+      border-radius: halfW(5) halfH(5);
+      display: flex;
+      flex-direction: column;
+      .p1{
+        font-size: halfW(14);
+        color: #B9E3F4;
+      }
+      .p2{
+        font-size: halfW(18);
+        color: #fff;
+      }
+      .p3{
+        font-size: halfW(12);
+        color: #9FA5B7;
+      }
+    }
+    .title,.legend{
+      padding: halfH(30) halfW(16);
+    }
+    .title{
+      // height: halfH(125);
+      flex: 1;
+      line-height: halfH(40);
+
+    }
+    .legend{
+      color: #808BAD;
+      background: #111C30;
+      font-size: halfW(14);
+      flex: 1;
+      line-height: halfH(40);
+      .legend1-color, .legend2-color{
+        display: inline-block;
+        width: halfW(20);
+        height: halfH(8);
+        margin-right: halfW(10);
+        vertical-align: middle;
+      }
+      .legend1-color{
+        background: linear-gradient(90deg, #FEA373 0%, #FF678B 100%);
+      }
+      .legend2-color{
+        background: linear-gradient(90deg, #0F67F8 0%, #98D7F1 50%, #77ECED 100%);
+      }
+      .legend3-color{
+        display: inline-block;
+        width: halfW(20);
+        height: halfH(20);
+        background: linear-gradient(90deg, #F6D1A7 0%, #F5BD7C 50%, #F4A850 100%);
+        border-radius: 50%;
+        margin-right: halfW(10);
+        position: relative;
+        .inner{
+          display: inline-block;
+          width: halfW(10);
+          height: halfH(10);
+          background: linear-gradient(90deg, #C9FFBF 0%, #FFB0BE 100%);
+          border-radius: 50%;
+          position: absolute;
+          top: 50%;
+          left: 50%;
+          transform: translate(-50%, -50%);
+        }
+      }
+    }
+  }
+}
+</style>

BIN
src/views/components/online-pay/images/icon-title.png


BIN
src/views/components/online-pay/images/icon-total.png


+ 2 - 0
src/views/components/online-pay/index.js

@@ -0,0 +1,2 @@
+import OnlinePay from './index.vue'
+export default OnlinePay

+ 224 - 0
src/views/components/online-pay/index.vue

@@ -0,0 +1,224 @@
+<template>
+    <Card :title="title" :subTitle="subTitle" :icon="icon" class="online-pay">
+      <div class="total display-flex">
+        <div class="img">
+          <img src="./images/icon-total.png" alt="" class="icon">
+        </div>
+        <div>
+          总缴费(近12个月):¥234554
+        </div>
+      </div>
+      <div ref="onlinePayBar" class="online-pay-bar"></div>
+    </Card>
+  </template>
+<script>
+import * as echarts from 'echarts'
+// import { getBigNumberWithUint } from '@/libs/tools.js'
+import Card from '@/views/components/card'
+import icon from './images/icon-title.png'
+
+export default {
+  name: 'OnlinePay',
+  components: {
+    Card
+  },
+  data () {
+    return {
+      title: '线上缴费统计',
+      subTitle: '近12个月',
+      icon: icon
+    }
+  },
+  mounted () {
+    this.initChart()
+  },
+  methods: {
+    /**
+     * 获取一个和max最接近的能被5整除的无零头整数
+     */
+    getMax (max) {
+      if (max <= 10) return 10
+
+      let pow = max.toString().length - 2
+      pow = Math.pow(10, pow)
+      max = Math.ceil(max / pow / 10) * 10 * pow
+      return max
+    },
+    initChart () {
+      const myChart = echarts.init(this.$refs.onlinePayBar)
+      const xAxisData = ['十二月', '一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月']
+      const seriesData = [5, 20, 36, 10, 10, 20, 40, 25, 30, 45, 50, 60]
+      // let max = 0
+      // max = seriesData.reduce((max, num) => {
+      //   return Math.max(Number(max), Number(num))
+      // })
+      // max = this.getMax(max)
+      const option = {
+        tooltip: {},
+        legend: {
+          right: '0',
+          top: '20px',
+          textStyle: {
+            color: '#fff'
+          }
+        },
+        grid: {
+          top: '80px',
+          bottom: '0px',
+          left: '0px',
+          right: '0px',
+          containLabel: true
+        },
+        xAxis: {
+          axisLabel: {
+            color: '#fff',
+            margin: 15,
+            fontSize: 14,
+            formatter: function (val, idx) {
+              let value = xAxisData[idx]
+              return value
+            }
+          },
+          axisLine: {
+            show: true,
+            lineStyle: {
+              color: '#666',
+              opacity: 1,
+              cap: 'round'
+            }
+          },
+          boundaryGap: false,
+          axisTick: {
+            alignWithLabel: true,
+            length: 7,
+            lineStyle: {
+              width: 3,
+              color: '#fff',
+              opacity: 0.5
+            }
+          },
+          splitLine: {
+            show: true,
+            lineStyle: {
+              color: '#fff',
+              opacity: 0.3,
+              cap: 'round',
+              type: [5, 10]
+            }
+          },
+          max: function (value) { // x轴左侧留白
+            return value.max + 0.3
+          },
+          min: function (value) { // x轴左侧留白
+            return -0.3
+          },
+          data: xAxisData
+        },
+        yAxis: [
+          {
+            axisLabel: {
+              color: '#fff',
+              margin: 25,
+              fontSize: 14
+            },
+            axisLine: {
+              show: false,
+              lineStyle: {
+                color: '#fff'
+              }
+            },
+            axisTick: {
+              length: 14,
+              lineStyle: {
+                width: 2,
+                fontSize: 16
+              }
+            },
+            splitLine: {
+              show: true,
+              lineStyle: {
+                color: '#fff',
+                opacity: 0.3,
+                cap: 'round',
+                type: 'dashed',
+                dashOffset: 5
+              }
+            }
+          },
+          {
+            type: 'value',
+            position: 'right',
+            axisLabel: {
+              show: false
+            },
+            axisTick: {
+              show: true,
+              length: 14,
+              lineStyle: {
+                width: 2,
+                fontSize: 16
+              }
+            },
+            axisLine: {
+              show: false
+            }
+          }
+        ],
+        series: [{
+          name: '线上流水',
+          type: 'bar',
+          barWidth: '20%',
+          labelLine: {
+            show: false
+          },
+          itemStyle: {
+            color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+              { offset: 0, color: '#0F67F8' },
+              { offset: 0.5, color: '#98D7F1' },
+              { offset: 1, color: '#77ECED' }
+            ]),
+            barBorderRadius: [10, 10, 0, 0]
+          },
+          data: seriesData
+        }]
+      }
+      myChart.setOption(option)
+    }
+  }
+}
+</script>
+<style lang="scss">
+@import '@/assets/css/function.scss';
+.online-pay-bar {
+  width: 100%;
+  height: halfH(363);
+}
+.online-pay {
+  .total{
+    height: halfH(24);
+    line-height: halfH(24);
+    padding: halfH(18) halfW(18);
+    color: #fff;
+    float: left;
+    font-size: halfW(14);
+    border-radius: 5px;
+    background-color: rgba(17, 28, 48, 1);
+    text-align: center;
+    border: 1px solid rgba(0, 123, 211, 0.2);
+  }
+  .img{
+    width: halfW(40);
+    height: halfH(40);
+    margin-right: halfW(27);
+    margin-top: halfH(-7);
+    padding: halfH(8) halfW(8);
+    box-sizing: border-box;
+    background: #12223C;
+    border-radius: 50%;
+    .icon{
+      width: 100%;
+      height: 100%;
+    }
+  }
+}
+</style>

BIN
src/views/components/online-water/images/icon-month.png


BIN
src/views/components/online-water/images/icon-once.png


BIN
src/views/components/online-water/images/icon-title.png


BIN
src/views/components/online-water/images/icon-total.png


+ 2 - 0
src/views/components/online-water/index.js

@@ -0,0 +1,2 @@
+import OnlineWater from './index.vue'
+export default OnlineWater

+ 147 - 0
src/views/components/online-water/index.vue

@@ -0,0 +1,147 @@
+<template>
+  <Card :title="title" :icon="icon" class="online-water">
+    <div class="con-top display-flex border">
+      <div class="img">
+        <img src="./images/icon-total.png" alt="" class="icon">
+      </div>
+      <div class="info">
+        <p class="title">线上流水总额</p>
+        <p class="num">34656444444.55</p>
+      </div>
+    </div>
+    <div class="con-bottom display-flex">
+      <div class="con-item flex-1 border">
+        <div class="top display-flex">
+          <div class="img">
+            <img src="./images/icon-once.png" alt="" class="icon">
+          </div>
+          <div class="flex-1">
+            <p class="title">单笔缴费金额</p>
+            <p class="num">344.55</p>
+            <p class="desc">(近12个月平均值)</p>
+          </div>
+        </div>
+        <div class="bottom display-flex">
+          <span class="title">单笔最大值</span>
+          <span class="num">346544.55</span>
+        </div>
+
+      </div>
+      <div class="con-item flex-1 border">
+        <div class="top display-flex">
+          <div class="img">
+            <img src="./images/icon-month.png" alt="" class="icon">
+          </div>
+          <div class="flex-1">
+            <p class="title">月在线缴费次数</p>
+            <p class="num">346564</p>
+            <p class="desc">(近12个月平均值)</p>
+          </div>
+        </div>
+        <div class="bottom display-flex">
+          <span class="title">单笔最大值</span>
+          <span class="num">346544.55</span>
+        </div>
+      </div>
+    </div>
+  </Card>
+</template>
+<script>
+import Card from '@/views/components/card'
+import icon from './images/icon-title.png'
+
+export default {
+  name: 'OnlineWater',
+  components: {
+    Card
+  },
+  data () {
+    return {
+      title: '线上流水数据',
+      icon: icon
+    }
+  }
+}
+</script>
+<style lang="scss">
+@import '@/assets/css/function.scss';
+.online-water {
+  .img{
+    width: halfW(70);
+    height: halfH(70);
+    margin-right: halfW(27);
+    padding: halfH(14) halfW(14);
+    box-sizing: border-box;
+    background: #12223C;
+    border-radius: 50%;
+    .icon{
+      width: 100%;
+      height: 100%;
+    }
+  }
+  .con-top{
+    padding: halfH(20) halfW(30);
+    background: #0E1629;
+    .info{
+      .title{
+        font-size: halfW(18);
+        line-height: halfH(24);
+        color: #82D1F6;
+      }
+      .num{
+        font-size: halfW(48);
+        line-height: halfH(48);
+        color: #9BE3E0;
+      }
+    }
+  }
+  .con-bottom{
+    margin-top: halfH(30) ;
+    .con-item{
+      // padding: halfH(30) halfW(30);
+      box-sizing: border-box;
+      &:first-child{
+        margin-right: halfW(30);
+      }
+      .top{
+        padding: halfH(30) halfW(30);
+        .title{
+          font-size: halfW(20);
+          line-height: halfH(22);
+          color: #82D1F6;
+          margin-bottom: halfH(8);
+        }
+        .num{
+          font-size: halfW(28);
+          line-height: halfH(38);
+          color: #F6F7FC;
+          margin-bottom: halfH(8);
+        }
+        .desc{
+          font-size: halfW(14);
+          line-height: halfH(16);
+          color: #9FA5B7;
+        }
+      }
+      .bottom{
+        justify-content: space-between;
+        align-items: center;
+        height: halfH(3);
+        line-height: halfH(63);
+        background: #111C30;
+        padding: halfH(30) halfW(30);
+        .title{
+          font-size: halfW(14);
+          line-height: halfH(20);
+          color: #9FA5B7;
+        }
+        .num{
+          font-size: halfW(20);
+          line-height: halfH(24);
+          color: #F6F7FC;
+        }
+      }
+    }
+  }
+}
+</style>

BIN
src/views/components/resident/images/icon-hfw.png


BIN
src/views/components/resident/images/icon-pay.png


BIN
src/views/components/resident/images/icon-qrcode.png


BIN
src/views/components/resident/images/icon-report.png


BIN
src/views/components/resident/images/icon-title.png


+ 2 - 0
src/views/components/resident/index.js

@@ -0,0 +1,2 @@
+import Resident from './index.vue'
+export default Resident

+ 238 - 0
src/views/components/resident/index.vue

@@ -0,0 +1,238 @@
+<template>
+    <Card :title="title" :icon="icon" class="resident">
+      <div class="display-flex">
+        <div class="gauge margin-r-30">
+          <div ref="dom" class="hfw-gauge"></div>
+        </div>
+        <div class="num display-flex flex-1">
+          <div v-for="item in residentData" :key="item.title" class="resident-item flex-1">
+            <div class="content">
+              <div class="title">{{ item.title }}</div>
+              <div class="value">{{ item.value }}</div>
+            </div>
+          </div>
+        </div>
+      </div>
+      <div class="operate display-flex">
+        <div v-for="item in operateData" :key="item.title" class="operate-item flex-1">
+          <div class="icon margin-t-30">
+            <img :src="item.icon" alt="" class="img">
+          </div>
+          <div class="content">
+            <div class="title">{{ item.title }}</div>
+            <div class="value">{{ item.value }}</div>
+          </div>
+        </div>
+      </div>
+    </Card>
+  </template>
+<script>
+import * as echarts from 'echarts'
+import Card from '@/views/components/card'
+import icon from './images/icon-title.png'
+import iconReport from './images/icon-report.png'
+import iconQrcode from './images/icon-qrcode.png'
+import iconPay from './images/icon-pay.png'
+
+export default {
+  name: 'Resident',
+  components: {
+    Card
+  },
+  data () {
+    return {
+      title: '用户信息',
+      icon: icon,
+      residentData: [
+        {
+          title: '公众号关注数',
+          value: 1000
+        },
+        {
+          title: '绘服务绑定数',
+          value: 1000
+        },
+        {
+          title: '日活跃数(近1月)',
+          value: 1000
+        }
+      ],
+      operateData: [
+        {
+          title: '绘服务缴费次数',
+          value: 1000,
+          icon: iconPay
+        },
+        {
+          title: '绘服务扫码次数',
+          value: 1000,
+          icon: iconQrcode
+        },
+        {
+          title: '绘服务报事次数',
+          value: 1000,
+          icon: iconReport
+        }
+      ],
+      colorArr: ['#182744', '#82D1F6', '#02338C']
+    }
+  },
+  mounted () {
+    this.initChart()
+  },
+  methods: {
+    initChart () {
+      const myChart = echarts.init(this.$refs.dom)
+      const option = {
+        name: '仪表盘',
+        grid: {
+          top: '0px',
+          bottom: '5px',
+          left: '0px',
+          right: '0px'
+        },
+        title: {
+          show: true,
+          text: [`{titleBg|关注率}`],
+          left: 'center',
+          bottom: '0',
+          textStyle: {
+            rich: {
+              titleBg: {
+                backgroundColor: '#14223C',
+                borderRadius: 4,
+                height: 26,
+                width: 70,
+                color: '#00CAFF',
+                fontSize: 16
+              }
+            }
+          }
+        },
+        series: [
+          {
+            type: 'gauge',
+            radius: '100%',
+            name: '绘服务',
+            axisLine: {
+              show: true,
+              lineStyle: {
+                width: 15,
+                color: [
+                  [
+                    0,
+                    new echarts.graphic.LinearGradient(0, 1, 0, 0, [
+                      {
+                        offset: 0,
+                        color: this.colorArr[1]
+                      },
+                      {
+                        offset: 1,
+                        color: this.colorArr[2]
+                      }
+                    ])
+                  ],
+                  [
+                    1, this.colorArr[0]
+                  ]
+                ]
+              }
+            },
+            splitLine: {
+              show: false
+            },
+            axisTick: {
+              show: false
+            },
+            axisLabel: {
+              show: false
+            },
+            pointer: {
+              show: false
+            },
+            title: {
+              offsetCenter: [0, '25%'],
+              fontSize: 14,
+              fontFamily: 'Microsoft YaHei',
+              fontWeight: '400',
+              color: '#5774A2'
+            },
+            detail: {
+              formatter: '{value}%',
+              offsetCenter: [0, '-10%'],
+              fontSize: 22,
+              fontFamily: 'DS-Digital',
+              fontWeight: 'bold',
+              color: '#00D2ED'
+            },
+            data: [{ value: 75, name: '' }]
+          }
+        ]
+      }
+      myChart.setOption(option)
+    }
+  }
+}
+</script>
+<style lang="scss">
+@import '@/assets/css/function.scss';
+@import '@/assets/css/screen.scss';
+
+.resident{
+  .gauge{
+    width: halfW(220);
+    padding-top: halfH(30);
+    .hfw-gauge{
+      width: halfW(193);
+      height: halfH(193);
+    }
+  }
+  .num{
+    flex-direction: column;
+    text-align: center;
+    line-height: halfH(35);
+    padding-left: halfW(30);
+    .title{
+      font-size: halfH(14);
+      color: #82D1F6;
+      text-align: left;
+    }
+    .value{
+      font-size: halfH(20);
+      color: #FFFFFF;
+      margin-left: halfW(50);
+    }
+  }
+  .operate{
+    height: halfH(210);
+    text-align: center;
+    border-radius: 5px;
+    background-color: rgba(17, 28, 48, 1);
+    border: 1px solid rgba(0, 123, 211, 0.2);
+    padding: halfH(20) 0;
+    line-height: halfH(40);
+    margin-top: halfH(60);
+    .operate-item{
+      border-right: 1px solid rgba(0, 123, 211, 0.2);
+    }
+    .operate-item:last-child{
+      border-right: none;
+    }
+    .img{
+      width: halfW(48);
+      height: halfH(48);
+    }
+    .content{
+      margin-top: halfH(25);
+    }
+    .title{
+      font-size: halfH(20);
+      color: #82D1F6;
+    }
+    .value{
+      font-size: halfH(20);
+      color: #FFFFFF;
+    }
+  }
+}
+</style>

+ 3 - 0
src/views/components/title/index.js

@@ -0,0 +1,3 @@
+import Title from './index.vue'
+
+export default Title

+ 24 - 0
src/views/components/title/index.vue

@@ -0,0 +1,24 @@
+<template>
+    <div class="title">
+        <img src="../../../assets/images/hjkj-logo.png" alt="绘家科技" class="img" />
+    </div>
+</template>
+<script>
+export default {
+  name: 'Title'
+}
+</script>
+<style scoped lang="scss">
+@import "@/assets/css/screen.scss";
+@import "@/assets/css/function.scss";
+@import "@/assets/css/mixin.scss";
+.title{
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    .img{
+        width: halfW(350);
+    }
+
+}
+</style>

BIN
src/views/components/user/images/icon-car.png


BIN
src/views/components/user/images/icon-community.png


BIN
src/views/components/user/images/icon-house.png


BIN
src/views/components/user/images/icon-park.png


BIN
src/views/components/user/images/icon-resident.png


BIN
src/views/components/user/images/icon-title.png


BIN
src/views/components/user/images/icon-user.png


+ 2 - 0
src/views/components/user/index.js

@@ -0,0 +1,2 @@
+import User from './index.vue'
+export default User

+ 100 - 0
src/views/components/user/index.vue

@@ -0,0 +1,100 @@
+<template>
+    <Card :title="title" :icon="icon" class="user">
+      <div class="display-flex margin-t-10">
+        <div v-for="item in userData" :key="item.title" class="user-item flex-1">
+          <div class="icon">
+            <img :src="item.icon" alt="" class="img">
+          </div>
+          <div class="content">
+            <div class="title">{{ item.title }}</div>
+            <div class="value">{{ item.value }}</div>
+          </div>
+        </div>
+      </div>
+    </Card>
+  </template>
+<script>
+import Card from '@/views/components/card'
+import icon from './images/icon-title.png'
+import iconPark from './images/icon-park.png'
+import iconCommunity from './images/icon-community.png'
+import iconResident from './images/icon-resident.png'
+import iconCar from './images/icon-car.png'
+import iconUser from './images/icon-user.png'
+import iconHouse from './images/icon-house.png'
+
+export default {
+  name: 'User',
+  components: {
+    Card
+  },
+  data () {
+    return {
+      title: '客户数量',
+      icon: icon,
+      userData: [
+        {
+          title: '客户数',
+          value: 1000,
+          icon: iconUser
+        },
+        {
+          title: '项目数',
+          value: 1000,
+          icon: iconCommunity
+        },
+        {
+          title: '房屋数',
+          value: 1000,
+          icon: iconHouse
+        },
+        {
+          title: '住户数',
+          value: 1000,
+          icon: iconResident
+        },
+        {
+          title: '车位数',
+          value: 1000,
+          icon: iconPark
+        },
+        {
+          title: '车辆数',
+          value: 1000,
+          icon: iconCar
+        }
+
+      ]
+    }
+  }
+}
+</script>
+<style lang="scss">
+@import '@/assets/css/function.scss';
+@import '@/assets/css/screen.scss';
+
+.user.card{
+  height: halfH(270);
+}
+.user{
+  align-items: center;
+  .user-item{
+    text-align: center;
+    line-height: halfH(50);
+  }
+  .img{
+    width: halfW(44);
+    height: halfH(44);
+    object-fit: cover;
+  }
+  .title{
+    font-size: halfH(18);
+    color: #9BDAFF;
+  }
+  .value{
+    font-size: halfH(28);
+    color: #fff;
+  }
+}
+
+</style>

+ 34 - 16
src/views/hui-jia/b1-screen/index.vue

@@ -1,18 +1,23 @@
 <template>
   <div class="b1-screen">
-    <div style="color: #fff" class="item-1">1</div>
-    <div class="middle-wrap">
-      <div style="color: #fff" class="item-2">2</div>
-      <div style="color: #fff" class="item-3">3</div>
-      <div style="color: #fff" class="item-4">4</div>
+    <div class="logo">
+      <img src="@/assets/images/hjkj1.png" class="logo-img" />
     </div>
-    <div class="right-wrap">
-      <Market />
-      <implementationTotal />
-    </div>
-    <div class="bottom-wrap">
-      <implementationIng />
-      <implementationNowYear />
+    <div class="b1-screen-content">
+      <div style="color: #fff" class="item-1">1</div>
+      <div class="middle-wrap">
+        <div style="color: #fff" class="item-2">2</div>
+        <div style="color: #fff" class="item-3">3</div>
+        <div style="color: #fff" class="item-4">4</div>
+      </div>
+      <div class="right-wrap">
+        <Market />
+        <implementationTotal />
+      </div>
+      <div class="bottom-wrap">
+        <implementationIng />
+        <implementationNowYear />
+      </div>
     </div>
   </div>
 </template>
@@ -35,15 +40,28 @@
 </script>
 
 <style lang="scss" scoped>
-  $gap-padding: 8px;
+  @import "@/assets/css/theme.scss";
 
+  $gap-padding: halfW(8);
   .b1-screen {
     height: 100vh;
     width: 100vw;
+    background: var(--page-bg);
+    .logo {
+      text-align: right;
+      padding: halfH(10) 0;
+      .logo-img {
+        height: halfH(64);
+      }
+    }
+  }
+  .b1-screen-content {
+    height: calc(100% - halfH(64) - halfH(28));
+    width: 100%;
     display: flex;
     flex-wrap: wrap;
     justify-content: flex-start;
-    gap: 16px;
+    gap: halfW(16);
     .item-1 {
       width: calc(25% - $gap-padding);
       height: calc(64% - $gap-padding);
@@ -54,7 +72,7 @@
       height: calc(64% - $gap-padding);
       display: flex;
       flex-wrap: wrap;
-      gap: 16px;
+      gap: halfW(16);
       justify-content: flex-start;
       .item-2 {
         flex: 0 0 100%;
@@ -91,7 +109,7 @@
     .bottom-wrap {
       display: flex;
       justify-content: space-around;
-      gap: 16px;
+      gap: halfW(16);
       width: 100%;
       height: calc(36% - $gap-padding);
       .now-year-container {

+ 35 - 20
src/views/hui-jia/b2-screen/index.vue

@@ -2,25 +2,30 @@
  * @Author: wjc
  * @Date: 2025-11-19 16:09:12
  * @LastEditors: wjc
- * @LastEditTime: 2025-11-19 17:01:02
+ * @LastEditTime: 2025-11-20 10:58:02
  * @Description: 
 -->
 <template>
   <div class="b2-screen">
-    <div class="left-wrap">
-      <div style="color: #fff" class="item-1">1</div>
-      <Smart />
+    <div class="logo">
+      <img src="@/assets/images/hjkj2.png" class="logo-img" />
     </div>
-    <div class="middle-wrap">
-      <div class="top">
-        <div class="top-left">
-          <div style="color: #fff" class="item-2">2</div>
-          <div style="color: #fff" class="item-3">3</div>
-          <div style="color: #fff" class="item-4">4</div>
+    <div class="b2-screen-content">
+      <div class="left-wrap">
+        <div style="color: #fff" class="item-1">1</div>
+        <Smart />
+      </div>
+      <div class="middle-wrap">
+        <div class="top">
+          <div class="top-left">
+            <div style="color: #fff" class="item-2">2</div>
+            <div style="color: #fff" class="item-3">3</div>
+            <div style="color: #fff" class="item-4">4</div>
+          </div>
+          <Hardware />
         </div>
-        <Hardware />
+        <WorkCard />
       </div>
-      <WorkCard />
     </div>
   </div>
 </template>
@@ -41,19 +46,32 @@
 </script>
 
 <style lang="scss" scoped>
-  $gap-padding: 8px;
+  @import "@/assets/css/theme.scss";
 
+  $gap-padding: halfW(8);
   .b2-screen {
     height: 100vh;
     width: 100vw;
+    background: var(--page-bg);
+    .logo {
+      text-align: left;
+      padding: halfH(10) 0;
+      .logo-img {
+        height: halfH(64);
+      }
+    }
+  }
+  .b2-screen-content {
+    height: calc(100% - halfH(64) - halfH(28));
+    width: 100%;
     display: flex;
     flex-wrap: wrap;
     justify-content: flex-start;
-    gap: 16px;
+    gap: halfW(16);
     .left-wrap {
       display: flex;
       flex-direction: column;
-      gap: 16px;
+      gap: halfW(16);
       width: calc(25% - $gap-padding);
       .item-1 {
         width: 100%;
@@ -70,7 +88,7 @@
       height: 100%;
       display: flex;
       flex-wrap: wrap;
-      gap: 16px;
+      gap: halfW(16);
       justify-content: flex-start;
       .top {
         flex: 1 1 0%;
@@ -83,29 +101,26 @@
           flex-direction: column;
           width: 50%;
           height: 100%;
+          gap: halfW(16);
           .item-2 {
             flex: 1 1 0%;
             width: 100%;
-            // height: calc(25% - $gap-padding);
             background: #f5f5f5;
           }
           .item-3 {
             flex: 1 1 0%;
             background: green;
             width: 100%;
-            // height: calc(25% - $gap-padding);
           }
           .item-4 {
             flex: 1 1 0%;
             width: 100%;
-            // height: calc(25% - $gap-padding);
             background: green;
           }
         }
         .hardware-data {
           width: 50%;
           height: 100%;
-        //   height: calc(75% - $gap-padding);
         }
       }
       .work-card-container {

+ 254 - 30
src/views/hui-jia/components/hardware.vue

@@ -96,42 +96,265 @@
 </template>
 
 <script>
-  import * as echarts from "echarts"
-  export default {
-    name: "HardwareData",
-    data() {
-      return {
-        powerChartInstance: null,
-        waterChartInstance: null,
-        // 模拟月度数据
-        monthlyData: [
-          { month: "十二月", power: 220000, water: 180000 },
-          { month: "一月", power: 210000, water: 170000 },
-          { month: "二月", power: 230000, water: 190000 },
-          { month: "三月", power: 225000, water: 185000 },
-          { month: "四月", power: 215000, water: 175000 },
-          { month: "五月", power: 200000, water: 160000 },
-          { month: "六月", power: 205000, water: 165000 },
-          { month: "七月", power: 210000, water: 170000 },
-          { month: "八月", power: 215000, water: 175000 },
-          { month: "九月", power: 220000, water: 180000 },
-          { month: "十月", power: 225000, water: 185000 },
-          { month: "十一月", power: 230000, water: 190000 },
-        ],
+import * as echarts from 'echarts'
+export default {
+  name: 'HardwareData',
+  data () {
+    return {
+      powerChartInstance: null,
+      waterChartInstance: null,
+      // 模拟月度数据
+      monthlyData: [
+        { month: '十二月', power: 220000, water: 180000 },
+        { month: '一月', power: 210000, water: 170000 },
+        { month: '二月', power: 230000, water: 190000 },
+        { month: '三月', power: 225000, water: 185000 },
+        { month: '四月', power: 215000, water: 175000 },
+        { month: '五月', power: 200000, water: 160000 },
+        { month: '六月', power: 205000, water: 165000 },
+        { month: '七月', power: 210000, water: 170000 },
+        { month: '八月', power: 215000, water: 175000 },
+        { month: '九月', power: 220000, water: 180000 },
+        { month: '十月', power: 225000, water: 185000 },
+        { month: '十一月', power: 230000, water: 190000 }
+      ]
+    }
+  },
+  mounted () {
+    this.initPowerChart()
+    this.initWaterChart()
+    window.addEventListener('resize', this.handleResize)
+  },
+  beforeDestroy () {
+    window.removeEventListener('resize', this.handleResize)
+    if (this.powerChartInstance) {
+      this.powerChartInstance.dispose()
+    }
+    if (this.waterChartInstance) {
+      this.waterChartInstance.dispose()
+    }
+  },
+  methods: {
+    // 初始化用电量柱状图
+    initPowerChart () {
+      this.powerChartInstance = echarts.init(this.$refs.powerChart)
+
+      const option = {
+        tooltip: {
+          trigger: 'axis',
+          backgroundColor: 'rgba(0, 0, 0, 0.8)',
+          borderColor: 'rgba(64, 158, 255, 0.3)',
+          textStyle: {
+            color: '#fff'
+          },
+          formatter: (params) => {
+            let result = ``
+            params.forEach((param) => {
+              result += `${param.name}<br/>${
+                param.seriesName
+              }: ${param.value.toLocaleString()}<br/>`
+            })
+            return result
+          }
+        },
+        grid: {
+          left: '1%',
+          right: '1%',
+          top: '5%',
+          bottom: '2%',
+          containLabel: true
+        },
+        xAxis: {
+          type: 'category',
+          data: this.monthlyData.map((item) => item.month),
+          axisLine: {
+            lineStyle: {
+              color: 'rgba(160, 179, 214, 0.3)',
+              type: 'dashed'
+            }
+          },
+          axisLabel: {
+            color: 'rgba(160, 179, 214, 0.7)',
+            fontSize: 11,
+            interval: 0
+          },
+          axisTick: {
+            show: false
+          },
+          splitLine: {
+            show: true,
+            // 将坐标轴内的线设置为虚线
+            lineStyle: {
+              color: 'rgba(160, 179, 214, 0.3)',
+              type: 'dashed'
+            }
+          }
+        },
+        yAxis: {
+          type: 'value',
+          axisLine: {
+            show: false
+          },
+          axisLabel: {
+            color: 'rgba(160, 179, 214, 0.7)',
+            fontSize: 11
+          },
+          axisTick: {
+            show: false
+          },
+          splitLine: {
+            lineStyle: {
+              color: 'rgba(160, 179, 214, 0.1)',
+              type: 'dashed',
+              width: 1
+            }
+          }
+        },
+        series: [
+          {
+            name: '用电量',
+            type: 'bar',
+            data: this.monthlyData.map((item) => item.power),
+            barWidth: '30%',
+            itemStyle: {
+              color: new echarts.graphic.LinearGradient(1, 1, 0, 0, [
+                { offset: 0, color: '#FCE2B4' },
+                { offset: 1, color: '#F66757' }
+              ]),
+              borderRadius: [20, 20, 0, 0]
+            },
+            label: {
+              show: true,
+              position: 'top',
+              color: '#fff',
+              fontSize: 10,
+              formatter: (params) =>
+                params.value >= 10000
+                  ? (params.value / 10000).toFixed(1) + '万'
+                  : params.value
+            }
+          }
+        ]
       }
+
+      this.powerChartInstance.setOption(option)
     },
-    mounted() {
-      this.initPowerChart()
-      this.initWaterChart()
-      window.addEventListener("resize", this.handleResize)
+
+    // 初始化用水量柱状图
+    initWaterChart () {
+      this.waterChartInstance = echarts.init(this.$refs.waterChart)
+
+      const option = {
+        tooltip: {
+          trigger: 'axis',
+          backgroundColor: 'rgba(0, 0, 0, 0.8)',
+          borderColor: 'rgba(64, 158, 255, 0.3)',
+          textStyle: {
+            color: '#fff'
+          },
+          formatter: (params) => {
+            let result = ``
+            params.forEach((param) => {
+              result += `${param.name}<br/>${
+                param.seriesName
+              }: ${param.value.toLocaleString()}<br/>`
+            })
+            return result
+          }
+        },
+        grid: {
+          left: '1%',
+          right: '1%',
+          top: '2%',
+          bottom: '5%',
+          containLabel: true
+        },
+        xAxis: {
+          type: 'category',
+          data: this.monthlyData.map((item) => item.month),
+          axisLine: {
+            lineStyle: {
+              color: 'rgba(160, 179, 214, 0.3)',
+              type: 'dashed'
+            }
+          },
+          axisLabel: {
+            color: 'rgba(160, 179, 214, 0.7)',
+            fontSize: 11,
+            interval: 0,
+            show: false
+          },
+          axisTick: {
+            show: false
+          },
+          splitLine: {
+            show: true,
+            // 将坐标轴内的线设置为虚线
+            lineStyle: {
+              color: 'rgba(160, 179, 214, 0.3)',
+              type: 'dashed'
+            }
+          }
+        },
+        yAxis: {
+          type: 'value',
+          // 反转 y 轴的 min 和 max,实现“倒立”
+          min: 400000,
+          max: 0,
+          axisLine: {
+            show: false
+          },
+          axisLabel: {
+            color: 'rgba(160, 179, 214, 0.7)',
+            fontSize: 11
+          },
+          axisTick: {
+            show: false
+          },
+          splitLine: {
+            lineStyle: {
+              color: 'rgba(160, 179, 214, 0.1)',
+              type: 'dashed',
+              width: 1
+            }
+          }
+        },
+        series: [
+          {
+            name: '用水量',
+            type: 'bar',
+            data: this.monthlyData.map((item) => item.water),
+            barWidth: '30%',
+            itemStyle: {
+              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+                { offset: 0, color: '#3AB3E3' },
+                { offset: 1, color: '#1620D4' }
+              ]),
+              borderRadius: [0, 0, 20, 20]
+            },
+            label: {
+              show: true,
+              position: 'bottom',
+              color: '#fff',
+              fontSize: 10,
+              formatter: (params) =>
+                params.value >= 10000
+                  ? (params.value / 10000).toFixed(1) + '万'
+                  : params.value
+            }
+          }
+        ]
+      }
+
+      this.waterChartInstance.setOption(option)
     },
-    beforeDestroy() {
-      window.removeEventListener("resize", this.handleResize)
+
+    handleResize () {
       if (this.powerChartInstance) {
-        this.powerChartInstance.dispose()
+        this.powerChartInstance.resize()
       }
       if (this.waterChartInstance) {
-        this.waterChartInstance.dispose()
+        this.waterChartInstance.resize()
       }
     },
     methods: {
@@ -361,6 +584,7 @@
       },
     },
   }
+}
 </script>
 
 <style lang="scss" scoped>

+ 3 - 3
src/views/hui-jia/components/implementary/total.vue

@@ -136,10 +136,10 @@
     }
 
     .total-grid {
-      padding: halfH(10) halfW(10);
+      padding: 0 halfW(10);
       display: grid;
-      grid-template-columns: repeat(2, 1fr);
-      grid-template-rows: repeat(4, 1fr);
+      grid-template-columns: repeat(4, 1fr);
+      grid-template-rows: repeat(2, 1fr);
       gap: halfH(16);
       height: calc(100% - halfH(84));
       align-items: center;

+ 133 - 133
src/views/hui-jia/components/smart.vue

@@ -33,149 +33,149 @@
 </template>
 
 <script>
-  export default {
-    name: "SmartDoor",
-    data() {
-      return {
-        doorDevices: "921",
-        activeProjects: "92",
-        accessTimes: "900000",
-        chartInstance: null,
-        // 模拟的通行流量数据
-        trafficData: [
-          { time: "01:00", count: 150 },
-          { time: "04:00", count: 250 },
-          { time: "07:00", count: 420 },
-          { time: "10:00", count: 380 },
-          { time: "13:00", count: 320 },
-          { time: "16:00", count: 230 },
-          { time: "19:00", count: 220 },
-          { time: "22:00", count: 300 },
-        ],
-      }
-    },
-    mounted() {
-      this.initChart()
-      window.addEventListener("resize", this.handleResize)
-    },
-    beforeDestroy() {
-      window.removeEventListener("resize", this.handleResize)
-      if (this.chartInstance) {
-        this.chartInstance.dispose()
-      }
-    },
-    methods: {
-      initChart() {
-        const echarts = require("echarts")
-        this.chartInstance = echarts.init(this.$refs.trafficChart)
+export default {
+  name: 'SmartDoor',
+  data () {
+    return {
+      doorDevices: '921',
+      activeProjects: '92',
+      accessTimes: '900000',
+      chartInstance: null,
+      // 模拟的通行流量数据
+      trafficData: [
+        { time: '01:00', count: 150 },
+        { time: '04:00', count: 250 },
+        { time: '07:00', count: 420 },
+        { time: '10:00', count: 380 },
+        { time: '13:00', count: 320 },
+        { time: '16:00', count: 230 },
+        { time: '19:00', count: 220 },
+        { time: '22:00', count: 300 }
+      ]
+    }
+  },
+  mounted () {
+    this.initChart()
+    window.addEventListener('resize', this.handleResize)
+  },
+  beforeDestroy () {
+    window.removeEventListener('resize', this.handleResize)
+    if (this.chartInstance) {
+      this.chartInstance.dispose()
+    }
+  },
+  methods: {
+    initChart () {
+      const echarts = require('echarts')
+      this.chartInstance = echarts.init(this.$refs.trafficChart)
 
-        const option = {
-          tooltip: {
-            trigger: "axis",
-            backgroundColor: "rgba(0, 0, 0, 0.8)",
-            borderColor: "rgba(64, 158, 255, 0.3)",
-            textStyle: {
-              color: "#fff",
-            },
-            formatter: (params) => {
-              return `${params[0].name}<br/>${params[0].seriesName}: ${params[0].value}`
-            },
+      const option = {
+        tooltip: {
+          trigger: 'axis',
+          backgroundColor: 'rgba(0, 0, 0, 0.8)',
+          borderColor: 'rgba(64, 158, 255, 0.3)',
+          textStyle: {
+            color: '#fff'
           },
-          legend: {
-            data: ["开门次数"],
-            textStyle: {
-              color: "#fff",
-            },
-            top: "0%",
-            right: "0%",
+          formatter: (params) => {
+            return `${params[0].name}<br/>${params[0].seriesName}: ${params[0].value}`
+          }
+        },
+        legend: {
+          data: ['开门次数'],
+          textStyle: {
+            color: '#fff'
           },
-          grid: {
-            left: "3%",
-            right: "4%",
-            bottom: "10%",
-            top: "20%",
-            containLabel: true,
+          top: '0%',
+          right: '0%'
+        },
+        grid: {
+          left: '3%',
+          right: '4%',
+          bottom: '10%',
+          top: '20%',
+          containLabel: true
+        },
+        xAxis: {
+          type: 'category',
+          data: this.trafficData.map((item) => item.time),
+          axisLine: {
+            lineStyle: {
+              color: 'rgba(160, 179, 214, 0.6)'
+            }
           },
-          xAxis: {
-            type: "category",
-            data: this.trafficData.map((item) => item.time),
-            axisLine: {
-              lineStyle: {
-                color: "rgba(160, 179, 214, 0.6)",
-              },
-            },
-            axisLabel: {
-              color: "rgba(160, 179, 214, 0.7)",
-              fontSize: 14,
-            },
-            axisTick: {
-              show: false,
-            },
-            splitLine: {
-              show: true,
-              // 将坐标轴内的线设置为虚线
-              lineStyle: {
-                color: "rgba(160, 179, 214, 0.3)",
-                type: "dashed",
-              },
-            },
+          axisLabel: {
+            color: 'rgba(160, 179, 214, 0.7)',
+            fontSize: 14
           },
-          yAxis: {
-            type: "value",
-            axisLine: {
-              show: false,
-            },
-            axisLabel: {
-              color: "rgba(160, 179, 214, 0.7)",
-              fontSize: 12,
-            },
-            axisTick: {
-              show: false,
-            },
-            splitLine: {
-              // 将坐标轴内的线设置为虚线
-              lineStyle: {
-                color: "rgba(160, 179, 214, 0.3)",
-                type: "dashed",
-              },
-            },
+          axisTick: {
+            show: false
+          },
+          splitLine: {
+            show: true,
+            // 将坐标轴内的线设置为虚线
+            lineStyle: {
+              color: 'rgba(160, 179, 214, 0.3)',
+              type: 'dashed'
+            }
+          }
+        },
+        yAxis: {
+          type: 'value',
+          axisLine: {
+            show: false
+          },
+          axisLabel: {
+            color: 'rgba(160, 179, 214, 0.7)',
+            fontSize: 12
           },
-          series: [
-            {
-              name: "开门次数",
-              type: "bar",
-              data: this.trafficData.map((item) => item.count),
-              barWidth: "30%",
-              // 添加标签配置,设置颜色为白色
-              label: {
-                show: true,
-                position: "top",
-                color: "#fff",
-                fontSize: 14,
-              },
-              itemStyle: {
-                color: new echarts.graphic.LinearGradient(0, 1, 0, 0, [
-                  { offset: 0, color: "#F6688B" },
-                  { offset: 1, color: "#F89877" },
-                ]),
-              },
+          axisTick: {
+            show: false
+          },
+          splitLine: {
+            // 将坐标轴内的线设置为虚线
+            lineStyle: {
+              color: 'rgba(160, 179, 214, 0.3)',
+              type: 'dashed'
+            }
+          }
+        },
+        series: [
+          {
+            name: '开门次数',
+            type: 'bar',
+            data: this.trafficData.map((item) => item.count),
+            barWidth: '30%',
+            // 添加标签配置,设置颜色为白色
+            label: {
+              show: true,
+              position: 'top',
+              color: '#fff',
+              fontSize: 14
             },
-          ],
-        }
+            itemStyle: {
+              color: new echarts.graphic.LinearGradient(0, 1, 0, 0, [
+                { offset: 0, color: '#F6688B' },
+                { offset: 1, color: '#F89877' }
+              ])
+            }
+          }
+        ]
+      }
 
-        this.chartInstance.setOption(option)
-      },
-      handleResize() {
-        if (this.chartInstance) {
-          this.chartInstance.resize()
-        }
-      },
-      // 模拟数据更新方法
-      updateData() {
-        // 这里可以根据实际需求从API获取数据
-      },
+      this.chartInstance.setOption(option)
     },
+    handleResize () {
+      if (this.chartInstance) {
+        this.chartInstance.resize()
+      }
+    },
+    // 模拟数据更新方法
+    updateData () {
+      // 这里可以根据实际需求从API获取数据
+    }
   }
+}
 </script>
 
 <style lang="scss" scoped>

+ 4 - 0
src/views/index/index.scss

@@ -1,6 +1,10 @@
 @import "@/assets/css/function.scss";
 @import "@/assets/css/mixin.scss";
+
 .index{
+  background: url('../../assets/images/2_logo.png');
+  background-repeat: no-repeat;
+  background-size: 100% 100%;
   .main{
     position: relative;
     height: halfH(1080 - 60);

BIN
src/views/login/images/logo@3x.png


+ 15 - 4
src/views/login/index.scss

@@ -1,11 +1,19 @@
 @import '@/assets/css/function';
-
+ 
 .login{
+  width: 100%;
+  height: 100%;
+  background: url('../../assets/images/2_logo.png');
+  background-repeat: no-repeat;
+  background-size: 100% 100%;
   color: #fff;
   .login-form{
     width: halfW(400);
-    padding: halfW(40);
-    background: #959FCD;
+    padding: halfH(40) halfW(40);
+    background: url('./images/logo@3x.png');
+    background-repeat: no-repeat;
+    background-size: 100% 100%;
+    // background: #959FCD;
     position: absolute;
     left: 50%;
     top: 50%;
@@ -13,8 +21,11 @@
     border-radius: halfW(10);
     .login-form-label{
       padding-bottom: halfH(40);
-      font-size: halfH(32);
+      font-size: halfH(36);
       text-align: center;
     }
+    .login-btn{
+      // font-size: halfH(20);
+    }
   }
 }

+ 3 - 3
src/views/login/index.vue

@@ -9,14 +9,14 @@
   <div class="login">
     <el-form class="login-form" :model="formRule" :rules="rules" ref="formRule">
       <h1 class="login-form-label">绘管家落地数据大屏</h1>
-      <el-form-item prop="user">
+      <el-form-item prop="user" class="input-item">
         <el-input v-model="formRule.user" placeholder="请输入用户名"></el-input>
       </el-form-item>
-      <el-form-item prop="pwd">
+      <el-form-item prop="pwd" class="input-item">
         <el-input v-model="formRule.pwd" show-password placeholder="请输入登录密码"></el-input>
       </el-form-item>
       <el-form-item>
-        <el-button type="primary" v-loading="isLoading" style="width: 100%" @click="onSubmit">登录</el-button>
+        <el-button type="primary" v-loading="isLoading" style="width: 100%; " @click="onSubmit" class="login-btn">登录</el-button>
       </el-form-item>
     </el-form>
   </div>

+ 6 - 1
vue.config.js

@@ -50,6 +50,11 @@ module.exports = {
   },
   css: {
     // 开启样式追溯
-    sourceMap: true
+    sourceMap: true,
+    loaderOptions: {
+      scss: {
+        prependData: `@import "@/assets/css/mixin.scss";`
+      }
+    }
   }
 }

+ 23 - 0
yarn.lock

@@ -1191,6 +1191,11 @@
   optionalDependencies:
     prettier "^1.18.2 || ^2.0.0"
 
+"@vue/composition-api@^1.7.2":
+  version "1.7.2"
+  resolved "https://registry.npmmirror.com/@vue/composition-api/-/composition-api-1.7.2.tgz#0b656f3ec39fefc2cf40aaa8c12426bcfeae1b44"
+  integrity sha512-M8jm9J/laYrYT02665HkZ5l2fWTK4dcVg3BsDHm/pfz+MjDYwX+9FUaZyGwEyXEDonQYRCo0H7aLgdklcIELjw==
+
 "@vue/eslint-config-standard@^4.0.0":
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/@vue/eslint-config-standard/-/eslint-config-standard-4.0.0.tgz#6be447ee674e3b0f733c584098fd9a22e6d76fcd"
@@ -6249,6 +6254,11 @@ mississippi@^3.0.0:
     stream-each "^1.1.0"
     through2 "^2.0.0"
 
+mitt@^3.0.0:
+  version "3.0.1"
+  resolved "https://registry.npmmirror.com/mitt/-/mitt-3.0.1.tgz#ea36cf0cc30403601ae074c8f77b7092cdab36d1"
+  integrity sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==
+
 mixin-deep@^1.2.0:
   version "1.3.2"
   resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566"
@@ -9343,6 +9353,11 @@ vue-count-to@^1.0.13:
   resolved "https://registry.yarnpkg.com/vue-count-to/-/vue-count-to-1.0.13.tgz#3e7573ea6e64c2b2972f64e0a2ab2e23c7590ff3"
   integrity sha512-6R4OVBVNtQTlcbXu6SJ8ENR35M2/CdWt3Jmv57jOUM+1ojiFmjVGvZPH8DfHpMDSA+ITs+EW5V6qthADxeyYOQ==
 
+vue-demi@^0.12.1:
+  version "0.12.5"
+  resolved "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.12.5.tgz#8eeed566a7d86eb090209a11723f887d28aeb2d1"
+  integrity sha512-BREuTgTYlUr0zw0EZn3hnhC3I6gPWv+Kwh4MCih6QcAeaTlaIX0DwOVN0wHej7hSvDPecz4jygy/idsgKfW58Q==
+
 vue-eslint-parser@^2.0.3:
   version "2.0.3"
   resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-2.0.3.tgz#c268c96c6d94cfe3d938a5f7593959b0ca3360d1"
@@ -9416,6 +9431,14 @@ vue-template-es2015-compiler@^1.9.0:
   resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825"
   integrity sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==
 
+vue-tianditu@2.7.6:
+  version "2.7.6"
+  resolved "https://registry.npmmirror.com/vue-tianditu/-/vue-tianditu-2.7.6.tgz#c48425c49306300cae9664182dd170c626a38371"
+  integrity sha512-Yvcxg0IAgGB3ZY8zlC5ayjo9f85fa8PFTaifguTNpri76g67GO9toaRWMjBKi39yYHMBADaT3P6bEkJx87X8MQ==
+  dependencies:
+    mitt "^3.0.0"
+    vue-demi "^0.12.1"
+
 vue@^2.6.10:
   version "2.7.16"
   resolved "https://registry.yarnpkg.com/vue/-/vue-2.7.16.tgz#98c60de9def99c0e3da8dae59b304ead43b967c9"