Kaynağa Gözat

业务解析,服务解析

wlf 1 yıl önce
ebeveyn
işleme
dfbd8dc589

+ 47 - 43
package-lock.json

@@ -365,19 +365,19 @@
       "integrity": "sha512-nB678VEGG3FkrvkDDFADAKjLQIeXzITEYqey5oeOpbf0vT5jOa55lQDyJDZ79cK8PmU/Hz6VPeSb3CNQBA+/FQ=="
     },
     "@antv/g6": {
-      "version": "4.8.23",
-      "resolved": "https://registry.npmmirror.com/@antv/g6/-/g6-4.8.23.tgz",
-      "integrity": "sha512-tsnJzlZCiOKvwAULGom6ppARutRmoAgV1wZzkOmDRm8ZdokUkpEYfb3faV6802VMs82DLP0zZ0KavapoK1q8hQ==",
+      "version": "4.8.24",
+      "resolved": "https://registry.npmmirror.com/@antv/g6/-/g6-4.8.24.tgz",
+      "integrity": "sha512-bgj7sZ+z45JmOngIpYpwmSIg7SboMLZBoAlX0+RoAETZB3/xvZO0MXT3lCSyAhIgm5Sb68pekKi7OStuo04NyQ==",
       "requires": {
-        "@antv/g6-pc": "0.8.23"
+        "@antv/g6-pc": "0.8.24"
       }
     },
     "@antv/g6-core": {
-      "version": "0.8.23",
-      "resolved": "https://registry.npmmirror.com/@antv/g6-core/-/g6-core-0.8.23.tgz",
-      "integrity": "sha512-JWdnba5Bx4/hLhbIQeyvdgh68SDYZisveukuBifxLKODCNJNKTopmWf1w6tU+RxAT2k5ByXkTGWQE1IkIL8O+Q==",
+      "version": "0.8.24",
+      "resolved": "https://registry.npmmirror.com/@antv/g6-core/-/g6-core-0.8.24.tgz",
+      "integrity": "sha512-rgI3dArAD8uoSz2+skS4ctN4x/Of33ivTIKaEYYvClxgkLZWVz9zvocy+5AWcVPBHZsAXkZcdh9zndIoWY/33A==",
       "requires": {
-        "@antv/algorithm": "^0.1.8",
+        "@antv/algorithm": "^0.1.26",
         "@antv/dom-util": "^2.0.1",
         "@antv/event-emitter": "~0.1.0",
         "@antv/g-base": "^0.5.1",
@@ -386,7 +386,7 @@
         "@antv/path-util": "^2.0.3",
         "@antv/util": "~2.0.5",
         "ml-matrix": "^6.5.0",
-        "tslib": "^2.1.0"
+        "tslib": "^2.6.2"
       },
       "dependencies": {
         "@antv/util": {
@@ -406,13 +406,14 @@
       }
     },
     "@antv/g6-element": {
-      "version": "0.8.23",
-      "resolved": "https://registry.npmmirror.com/@antv/g6-element/-/g6-element-0.8.23.tgz",
-      "integrity": "sha512-KdJOiu4D7UExsYjKOJUcd7YCD/gCfxqHOlS01zkyOqsaindWVLdshBAZWXc2zgzVwHS/fadxwUI+DcllsRkH0g==",
+      "version": "0.8.24",
+      "resolved": "https://registry.npmmirror.com/@antv/g6-element/-/g6-element-0.8.24.tgz",
+      "integrity": "sha512-61FXkt9LY+6EOUtSam1iFTOW2AM59sPVcV1BuPj4dXiD0dluLE+R7d8B/94g1tKDw9tsjhfUQGC7hTXscJRJFw==",
       "requires": {
         "@antv/g-base": "^0.5.1",
-        "@antv/g6-core": "0.8.23",
-        "@antv/util": "~2.0.5"
+        "@antv/g6-core": "0.8.24",
+        "@antv/util": "~2.0.5",
+        "tslib": "^2.6.2"
       },
       "dependencies": {
         "@antv/util": {
@@ -432,21 +433,21 @@
       }
     },
     "@antv/g6-pc": {
-      "version": "0.8.23",
-      "resolved": "https://registry.npmmirror.com/@antv/g6-pc/-/g6-pc-0.8.23.tgz",
-      "integrity": "sha512-8H5n1U8T4pyBcoaEKB8g4TRKycHtONSA+qOeFMq7XIDh1DCn0tUF1uLvwj096Zp+/bUXtAfaRvg+n1KKyCVZ0w==",
+      "version": "0.8.24",
+      "resolved": "https://registry.npmmirror.com/@antv/g6-pc/-/g6-pc-0.8.24.tgz",
+      "integrity": "sha512-nf0y1lrp8J5DotqRryXd2S/J30COW8spVcLF9gUqywGqQAHfE00Ywkqr+PZBnsfCZXsXCi9o0+CE9NrkWs4SBQ==",
       "requires": {
         "@ant-design/colors": "^4.0.5",
-        "@antv/algorithm": "^0.1.8",
+        "@antv/algorithm": "^0.1.26",
         "@antv/dom-util": "^2.0.1",
         "@antv/event-emitter": "~0.1.0",
         "@antv/g-base": "^0.5.1",
         "@antv/g-canvas": "^0.5.2",
         "@antv/g-math": "^0.1.1",
         "@antv/g-svg": "^0.5.1",
-        "@antv/g6-core": "^0.8.23",
-        "@antv/g6-element": "0.8.23",
-        "@antv/g6-plugin": "0.8.23",
+        "@antv/g6-core": "0.8.24",
+        "@antv/g6-element": "0.8.24",
+        "@antv/g6-plugin": "0.8.24",
         "@antv/hierarchy": "^0.6.10",
         "@antv/layout": "^0.3.0",
         "@antv/matrix-util": "^3.1.0-beta.3",
@@ -456,7 +457,8 @@
         "d3-force": "^2.0.1",
         "dagre": "^0.8.5",
         "insert-css": "^2.0.0",
-        "ml-matrix": "^6.5.0"
+        "ml-matrix": "^6.5.0",
+        "tslib": "^2.6.2"
       },
       "dependencies": {
         "@antv/util": {
@@ -476,16 +478,16 @@
       }
     },
     "@antv/g6-plugin": {
-      "version": "0.8.23",
-      "resolved": "https://registry.npmmirror.com/@antv/g6-plugin/-/g6-plugin-0.8.23.tgz",
-      "integrity": "sha512-DwhSuUc0a0foIM4nrhXR/+ooZafkVve0IEErldhsygKWLDSz/c9HRLON66OEdzQX7Ed1uE0SMcBUsIDe+wPQrw==",
+      "version": "0.8.24",
+      "resolved": "https://registry.npmmirror.com/@antv/g6-plugin/-/g6-plugin-0.8.24.tgz",
+      "integrity": "sha512-ZIOnwLTC7SM2bFiJZ3vYFWnkyOCWKqnU96i/fBh1qAoY5slDS3hatenZWEXUtOcqaKw1h+5A5f72MRXqBBVn0g==",
       "requires": {
         "@antv/dom-util": "^2.0.2",
         "@antv/g-base": "^0.5.1",
         "@antv/g-canvas": "^0.5.2",
         "@antv/g-svg": "^0.5.2",
-        "@antv/g6-core": "0.8.23",
-        "@antv/g6-element": "0.8.23",
+        "@antv/g6-core": "0.8.24",
+        "@antv/g6-element": "0.8.24",
         "@antv/matrix-util": "^3.1.0-beta.3",
         "@antv/path-util": "^2.0.3",
         "@antv/scale": "^0.3.4",
@@ -559,9 +561,9 @@
       }
     },
     "@antv/layout": {
-      "version": "0.3.24",
-      "resolved": "https://registry.npmmirror.com/@antv/layout/-/layout-0.3.24.tgz",
-      "integrity": "sha512-r7AQBXw73u6RGc3q7ApAjcHHG26U5c78zcDFCutopC8lMltF8bUFiO37xrBieLm96vhHYz/W0zOXdPeC+LG+ZQ==",
+      "version": "0.3.25",
+      "resolved": "https://registry.npmmirror.com/@antv/layout/-/layout-0.3.25.tgz",
+      "integrity": "sha512-d29Aw1PXoAavMRZy7iTB9L5rMBeChFEX0BJ9ELP4TI35ySdCu07YbmPo9ju9OH/6sG2/NB3o85Ayxrre3iwX/g==",
       "requires": {
         "@antv/g-webgpu": "0.7.2",
         "@antv/graphlib": "^1.0.0",
@@ -569,20 +571,27 @@
         "d3-force": "^2.1.1",
         "d3-quadtree": "^2.0.0",
         "dagre-compound": "^0.0.11",
-        "ml-matrix": "^6.5.0"
+        "ml-matrix": "6.5.0"
       },
       "dependencies": {
         "@antv/util": {
-          "version": "3.3.5",
-          "resolved": "https://registry.npmmirror.com/@antv/util/-/util-3.3.5.tgz",
-          "integrity": "sha512-bVv1loamL/MgUEN9dNt7VKAsghO4Wgb+kzr8B9TgkM5tHgKk++xiTwi3pejIdgU8DDkzcyaRsO+VTOXJt8jLng==",
+          "version": "3.3.6",
+          "resolved": "https://registry.npmmirror.com/@antv/util/-/util-3.3.6.tgz",
+          "integrity": "sha512-Oj2uAwBWEpEKbYcYgSJ/B6zv7t515L+JZzSpnkZeez/qwvDbS6s80lQRuzWzVhWCTHKSPLkgImxhkV9nzLmv4Q==",
           "requires": {
             "fast-deep-equal": "^3.1.3",
-            "flru": "^1.0.2",
             "gl-matrix": "^3.3.0",
             "tslib": "^2.3.1"
           }
         },
+        "ml-matrix": {
+          "version": "6.5.0",
+          "resolved": "https://registry.npmmirror.com/ml-matrix/-/ml-matrix-6.5.0.tgz",
+          "integrity": "sha512-sms732Dge+rs5dU4mnjE0oqLWm1WujvR2fr38LgUHRG2cjXjWlO3WJupLYaSz3++2iYr0UrGDK72OAivr3J8dg==",
+          "requires": {
+            "ml-array-rescale": "^1.3.1"
+          }
+        },
         "tslib": {
           "version": "2.6.2",
           "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.6.2.tgz",
@@ -10933,11 +10942,6 @@
       "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==",
       "dev": true
     },
-    "flru": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmmirror.com/flru/-/flru-1.0.2.tgz",
-      "integrity": "sha512-kWyh8ADvHBFz6ua5xYOPnUroZTT/bwWfrCeL0Wj1dzG4/YOmOcfJ99W8dOVyyynJN35rZ9aCOtHChqQovV7yog=="
-    },
     "flush-write-stream": {
       "version": "1.1.1",
       "resolved": "https://registry.npmmirror.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz",
@@ -16222,9 +16226,9 @@
       }
     },
     "ml-matrix": {
-      "version": "6.10.8",
-      "resolved": "https://registry.npmmirror.com/ml-matrix/-/ml-matrix-6.10.8.tgz",
-      "integrity": "sha512-AOWniClvQMbGx2V0mqzOScINLe+PjAjpjTN3zYRG7gV5Zp29fu9b2E0PfTdnupN03USOQMvkjT9/8yB4hEEahg==",
+      "version": "6.11.0",
+      "resolved": "https://registry.npmmirror.com/ml-matrix/-/ml-matrix-6.11.0.tgz",
+      "integrity": "sha512-7jr9NmFRkaUxbKslfRu3aZOjJd2LkSitCGv+QH9PF0eJoEG7jIpjXra1Vw8/kgao8+kHCSsJONG6vfWmXQ+/Eg==",
       "requires": {
         "is-any-array": "^2.0.1",
         "ml-array-rescale": "^1.3.7"

+ 1 - 1
package.json

@@ -45,7 +45,7 @@
     "url": "https://github.com/go-admin-team/go-admin/issues"
   },
   "dependencies": {
-    "@antv/g6": "^4.8.22",
+    "@antv/g6": "^4.8.24",
     "@opentelemetry/api": "^1.7.0",
     "@opentelemetry/auto-instrumentations-web": "^0.33.2",
     "@opentelemetry/context-zone": "^1.17.1",

+ 82 - 0
src/api/service.js

@@ -0,0 +1,82 @@
+import request from '@/utils/request'
+
+
+// 服务列表/api/v1/service 1和2是一套,拿到1的id请求2的接口,两套数据进行整合。
+export function listService(query) {
+  return request({
+    url: '/api/v1/service',
+    method: 'get',
+    params: query
+  })
+}
+
+// 2./api/v1/service/stats 服务统计数据:针对服务列表补充的统计数据,用于加快服务列表响应速度
+export function listServiceStats(query) {
+  return request({
+    url: '/api/v1/service/stats',
+    method: 'get',
+    params: query
+  })
+}
+// 数字视图/api/v1/service/digits
+export function digitsService(query) {
+  return request({
+    url: '/api/v1/service/digits',
+    method: 'get',
+    params: query
+  })
+}
+
+// 4. SPAN列表  同可观测平台4.8接口一致 /api/v1/service/spans
+export function serviceSpans(query) {
+  return request({
+    url: '/api/v1/service/spans',
+    method: 'get',
+    params: query
+  })
+}
+
+//更新服务信息 /api/v1/service/{service_id}   put
+export function updateService(data, id) {
+  return request({
+    url: '/api/v1/service/' + id,
+    method: 'put',
+    data: data
+  })
+}
+
+//创建服务信息  /api/v1/service  post
+export function addService(data) {
+  return request({
+    url: '/api/v1/service',
+    method: 'post',
+    data: data
+  })
+}
+
+//活跃度 /api/v1/service/compare/liveness
+export function serviceCompare(query) {
+  return request({
+    url: '/api/v1/service/compare/liveness',
+    method: 'get',
+    params: query
+  })
+}
+//错误率
+export function serviceErrors(query) {
+  return request({
+    url: '/api/v1/service/compare/errors',
+    method: 'get',
+    params: query
+  })
+}
+
+//8. 服务列表柱状视图
+export function serviceBar(query,app_alias) {
+  return request({
+    url: `/api/v1/apps_score/${app_alias}/svrs`,
+    method: 'get',
+    params: query
+  })
+}
+

+ 36 - 16
src/layout/components/Navbar.vue

@@ -394,27 +394,47 @@ export default {
 
                       }
                     }
-                    eventNums(this.queryNums).then((res)=>{
-                      if(res.code == 200){
-                        if(res.data.list.length!=0){
-                          for(let i=0;i<arr.length;i++){
-                            for(let j=0;j<res.data.list.length;j++){
-                              if(arr[i].id == res.data.list[j].app_id){
-                                arr[i] = Object.assign({},arr[i], res.data.list[j])
-                              }else{
-                                arr[i].exception_num = 0;
-                              }
-                              console.log(arr[i].exception_num,'exception_num')
-                            }
-                          }
+                    // eventNums(this.queryNums).then((res)=>{
+                    //   if(res.code == 200){
+                    //     if(res.data.list.length!=0){
+                    //       for(let i=0;i<arr.length;i++){
+                    //         for(let j=0;j<res.data.list.length;j++){
+                    //           if(arr[i].id == res.data.list[j].app_id){
+                    //             arr[i] = Object.assign({},arr[i], res.data.list[j])
+                    //           }else{
+                    //             arr[i].exception_num = 0;
+                    //           }
+                    //           console.log(arr[i].exception_num,'exception_num')
+                    //         }
+                    //       }
+                    //     }
+                    //   }
+                    //   this.appList=arr; 
+                    // })
+                  }
+                }
+              })
+              
+            }
+
+            if(app_ids.length>0){
+              eventNums(this.queryNums).then((res)=>{
+                if(res.code == 200){
+                  if(res.data.list.length!=0){
+                    for(let i=0;i<arr.length;i++){
+                      for(let j=0;j<res.data.list.length;j++){
+                        if(arr[i].id == res.data.list[j].app_id){
+                          arr[i] = Object.assign({},arr[i], res.data.list[j])
+                        }else{
+                          arr[i].exception_num = 0;
                         }
+                        console.log(arr[i].exception_num,'exception_num')
                       }
-                      this.appList=arr; 
-                    })
+                    }
                   }
                 }
+                this.appList=arr; 
               })
-              
             }
               
           }

+ 2 - 2
src/layout/components/TimeRange.vue

@@ -25,11 +25,11 @@
             <el-button :type="timeType=='5m'?'primary':''" size='mini' @click="timeChange('5m')">Last 5m</el-button>
             <el-button :type="timeType=='20m'?'primary':''" size='mini' @click="timeChange('20m')">20m</el-button>
             <el-button :type="timeType=='1h'?'primary':''" size='mini' @click="timeChange('1h')">1h</el-button>
-            <el-button :type="timeType=='3h'?'primary':''" size='mini' @click="timeChange('3h')">3h</el-button>
+            <!-- <el-button :type="timeType=='3h'?'primary':''" size='mini' @click="timeChange('3h')">3h</el-button> -->
             <el-button :type="timeType=='6h'?'primary':''" size='mini' @click="timeChange('6h')">6h</el-button>
             <el-button :type="timeType=='12h'?'primary':''" size='mini' @click="timeChange('12h')">12h</el-button>
             <el-button :type="timeType=='1d'?'primary':''" size='mini' @click="timeChange('1d')">1d</el-button>
-            <el-button :type="timeType=='2d'?'primary':''" size='mini' @click="timeChange('2d')">2d</el-button>
+            <!-- <el-button :type="timeType=='2d'?'primary':''" size='mini' @click="timeChange('2d')">2d</el-button> -->
           </el-button-group>
         </div>
         <div style="margin-left:12px" class='box'>

+ 1 - 1
src/main.js

@@ -71,7 +71,7 @@ Vue.use(VueContextMenu)
 
 
 //opentelemetry
-import './lib/index'
+// import './lib/index'
 
 
 

+ 128 - 66
src/views/business-analysis/analysis/components/ServiceMap.vue → src/views/business-analysis/analysis/components/AnalysisMap.vue

@@ -12,16 +12,39 @@
             </el-form-item>
         </el-form> -->
 
-        <!-- <el-row :gutter="10" class="mb8">
-          <el-col :span="1.5">
-            <el-button
-              type="primary"
-              icon="el-icon-plus"
-              size="mini"
-              @click="handleAdd"
-            >新增</el-button>
+        <el-row :gutter="10" class="mb8">
+          <el-col :span="2">
+             <div style='display:inline-block;vertical-align: middle;'>
+                <el-dropdown
+                  style="margin-left: 10px"
+                  size="mini"
+                  trigger="click"
+                  placement="bottom"
+                >
+                  <el-button type="primary" size="mini">
+                    <!-- 下拉菜单 -->
+                    <i class="el-icon-s-grid" />
+                    <i class="el-icon-arrow-down"></i>
+                  </el-button>
+                  <el-dropdown-menu slot="dropdown">
+                    <el-checkbox-group
+                      v-model="colSelect"
+                      style="text-align: left"
+                      @change="columnChange"
+                    >
+                      <el-dropdown-item
+                        v-for="(item, index) in colData"
+                        :key="index"
+                        ><el-checkbox :label="item.title">{{
+                          item.title
+                        }}</el-checkbox></el-dropdown-item
+                      >
+                    </el-checkbox-group>
+                  </el-dropdown-menu>
+                </el-dropdown>
+              </div>
           </el-col>
-        </el-row> -->
+        </el-row>
 
         <div>
           <!-- v-el-table-infinite-scroll="loadMore"  :height="tableHeight"-->
@@ -32,55 +55,55 @@
             :default-sort = "{prop: 'total', order: 'descending'}"
             @row-click="handleRowClick" 
           >
-            <el-table-column header-align="left" label="业务名" prop="name" align="left" :show-overflow-tooltip="true"/>
-            <el-table-column header-align="left" label="起始服务" prop="service_name" align="left" :show-overflow-tooltip="true">
+            <el-table-column header-align="left" label="业务名" prop="name" align="left" :show-overflow-tooltip="true" v-if="colData[0].istrue"/>
+            <el-table-column header-align="left" label="起始服务" prop="service_name" align="left" :show-overflow-tooltip="true" v-if="colData[1].istrue">
               <template slot-scope="scope">
                 <span>{{scope.row.service_name}}</span>
               </template>
             </el-table-column>
-            <el-table-column header-align="left" label="SpanName" prop="span_name" align="left" :show-overflow-tooltip="true">
+            <el-table-column header-align="left" label="SpanName" prop="span_name" align="left" :show-overflow-tooltip="true" v-if="colData[2].istrue">
               <template slot-scope="scope">
                 <span>{{scope.row.span_name}}</span>
               </template>
             </el-table-column>
-            <el-table-column header-align="center" label="rpm" sortable prop="rpm" align="center" :show-overflow-tooltip="true">
+            <el-table-column header-align="center" label="rpm" sortable prop="rpm" align="center" :show-overflow-tooltip="true" v-if="colData[3].istrue">
               <template slot-scope="scope">
 
                 <el-tag>{{ scope.row.rpm == undefined?0:Number(scope.row.rpm).toFixed(2)}}</el-tag>
               </template>
             </el-table-column>
-            <el-table-column header-align="center" label="count" sortable prop="total" align="center">
+            <el-table-column header-align="center" label="count" sortable prop="total" align="center" v-if="colData[4].istrue">
               <template slot-scope="scope">
                 <!-- <span>{{ Number(scope.row.rpm).toFixed(2)}}</span> -->
                 <el-tag>{{ scope.row.total== undefined?0:Number(scope.row.total).toFixed(2)}}</el-tag>
               </template>
             </el-table-column>
-            <el-table-column header-align="center" label="errRate" sortable prop="error_rate" align="center">
+            <el-table-column header-align="center" label="errRate" sortable prop="error_rate" align="center" v-if="colData[5].istrue">
               <template slot-scope="scope">
                  <el-tag v-if="scope.row.error_rate==0">{{  scope.row.error_rate }}</el-tag>
                     <el-tag v-else type="danger">{{  Number(scope.row.error_rate).toFixed(2)}}</el-tag>
               </template>
             </el-table-column>
-            <el-table-column header-align="center" label="max(ms)" sortable prop="max" align="center" width="100">
+            <el-table-column header-align="center" label="max(ms)" sortable prop="max" align="center" width="100" v-if="colData[6].istrue">
               <template slot-scope="scope">
                 <!-- <span>{{ Number(scope.row.max).toFixed(2)}}</span> -->
                 <el-tag v-if="scope.row.max>=2000" type="danger">{{ Number(scope.row.max).toFixed(2) }}</el-tag>
                 <el-tag v-if="scope.row.max<2000">{{ Number(scope.row.max).toFixed(2) }}</el-tag>
               </template>
             </el-table-column>
-            <el-table-column header-align="center" label="avg(ms)" sortable prop="avg" align="center" width="100">
+            <el-table-column header-align="center" label="avg(ms)" sortable prop="avg" align="center" width="100" v-if="colData[7].istrue">
               <template slot-scope="scope">
                 <!-- <span>{{ Number(scope.row.avg).toFixed(2)}}</span> -->
                 <el-tag v-if="scope.row.avg>=2000" type="danger">{{ Number(scope.row.avg).toFixed(2) }}</el-tag>
                 <el-tag v-if="scope.row.avg<2000">{{ Number(scope.row.avg).toFixed(2) }}</el-tag>
               </template>
             </el-table-column>
-            <!-- <el-table-column header-align="center" label="延迟比例" prop="duration_stats" align="center">
+            <el-table-column header-align="center" label="延迟比例" prop="quantiles" align="center" v-if="colData[8].istrue">
                 <template slot-scope="scope">
                   {{ drawEchartsp5(scope.row, scope.$index, 'five') }}
                   <div :id="`tiger-five-trend-index` + scope.$index" class="tiger-trend-charts"></div>
                 </template>
-            </el-table-column> -->
+            </el-table-column>
             <el-table-column
               label="操作"
               align="center"
@@ -187,7 +210,7 @@
             <div class="flexWrap">
               <div class="flex-left">
                 <!-- <Topo /> -->
-                <Topo v-if='JSON.stringify(graphData) != "{}"' :graphData='graphData' topoId='serviceContainer' v-on:changeState="clickRowHandleNode" ref='topo'/>
+                <Topo v-if='drawer' :graphData='graphData' topoId='container' v-on:changeState="clickRowHandleNode" ref='topo'/>
               </div>
               <div class="flex-right">
                   <div id="scaleMain" style="width:100%;min-width:500px;height:180px;margin-bottom:24px"></div>
@@ -201,11 +224,11 @@
                       <span @click="goto(scope.row)">{{scope.row.trace_id}}</span>
                     </template>
                     </el-table-column>
-                    <el-table-column header-align="center" label="ServiceName" prop="service_name" align="center" :show-overflow-tooltip="true" />
+                    <el-table-column header-align="center" label="SpanName" prop="span_name" align="center" :show-overflow-tooltip="true" />
                     <!-- <el-table-column header-align="center" label="SpanName" prop="span_name" align="center" :show-overflow-tooltip="true" />
                     <el-table-column header-align="center" label="SpanKind" prop="span_kind" align="center" width="100"/> -->
-                    <el-table-column header-align="center" label="Target" prop="target" align="center" :show-overflow-tooltip="true" />
-                    <el-table-column header-align="center" label="Method" prop="method" align="center">
+                    <el-table-column header-align="center" label="DateTime" prop="datetime" align="center" :show-overflow-tooltip="true" />
+                    <!-- <el-table-column header-align="center" label="Method" prop="method" align="center">
                       <template slot-scope="scope">
                           <el-tag type="info">{{ scope.row.method }}</el-tag>
                       </template>
@@ -217,8 +240,8 @@
                         <span v-else><i class="red_small"></i>{{scope.row.status_code}}</span>
                       </span>
                     </template>
-                    </el-table-column>
-                    <el-table-column header-align="center" label="Duration(ms)" prop="duration" align="center">
+                    </el-table-column> -->
+                    <el-table-column header-align="center" label="Duration(ms)" prop="duration" width='140' align="center">
                       <template slot-scope="scope">
                           <el-tag v-if="scope.row.duration>=2000" type="danger">{{ scope.row.duration }}</el-tag>
                           <el-tag v-if="scope.row.duration<2000" type="info">{{ scope.row.duration }}</el-tag>
@@ -319,6 +342,28 @@ export default {
   // },
   data() {
     return {
+      // 设置选中的列的复选框
+      colSelect: [
+        "业务名",
+        "起始服务",
+        "SpanName",
+        "rpm",
+        "count",
+        "errRate",
+        "max(ms)",
+        "延迟比例",
+      ],
+      colData: [
+        { title: "业务名", istrue: false },
+        { title: "起始服务", istrue: false },
+        { title: "SpanName", istrue: false },
+        { title: "rpm", istrue: false },
+        { title: "count", istrue: false },
+        { title: "errRate", istrue: false },
+        { title: "max(ms)", istrue: false },
+        { title: "avg(ms)", istrue: false },
+        { title: "延迟比例", istrue: false },
+      ],
       isUpdate:false,
       isflag:false,
       tableflag:false,
@@ -401,6 +446,7 @@ export default {
         end_time:1702972800,
         start_time:1702969200,
       },
+      graphObj:[]
     }
   },
    watch: {
@@ -472,12 +518,22 @@ export default {
       this.getList()
       this.$forceUpdate();
     }
-    // this.columnChange();
+    this.columnChange();
   },
   mounted(){
     this.$forceUpdate();
   },
   methods: {
+    //控制列的显示和隐藏
+    columnChange(val) {
+      this.colData.filter((i) => {
+        if (this.colSelect.indexOf(i.title) !== -1) {
+          i.istrue = true;
+        } else {
+          i.istrue = false;
+        }
+      });
+    },
     // clickFull() {
     //     this.Visible=true;
     //     this.$refs['topo'].initGraph();
@@ -540,50 +596,33 @@ export default {
     },
     getListBizGraph(id){
       listBizGraph({biz_id:id}).then((res)=>{
+        console.log(res,'决策树数据')
         if(res.code == 200){
           let arr = res.data
           if(arr.length>0){
             let List = this.handelListBizData(arr)
-            this.graphData ={ List };
-            // this.drawer=true;
-            // this.$nextTick(() =>{ 
-            //   this.drawEchartsScale(row);
-            // }) 
+            console.log(List,'处理后的数据')
+            this.graphData =List[0];
             console.log(this.graphData,'graphData=======')
           }
         }
       })
     },
-    handelListBizData(arr){
-      arr.forEach((v,k)=>{
-        this.graphStatsQuery.biz_node_id = v.id
-        listBizGraphStats(this.graphStatsQuery).then((response)=>{
-          if(response.code == 200){
-            if(response.data.biz_node_id != undefined){
-              if(v.id == response.data.biz_node_id){
-                  console.log(response.data,'response.data')
-                  // v = Object.assign({},v, response.data);
-                  v={...v,...response.data}
-                  v.collapsed = false;
-                  v.id = String(v.id);
-                  v.name = v.name;
-                  v.label = response.data.duration!=undefined?response.data.duration.toFixed(2):0;
-                  v.currency='ms';
-                  v.rate = response.data.success_rate;
-                  v.status = 'B'
-                  v.variableValue = response.data.success_rate;
-                  console.log(v,'v===================')
-                  // this.isflag = !this.isflag;
-              }
-            }
-          }
-        })
-        if (v.children != undefined && v.children.length > 0 && v.children != null) {
+    handelListBizData(data){
+      data.forEach((v,k)=>{
+        v.collapsed = false;
+        v.id = String(v.id);
+        v.name = v.name;
+        v.label = v.stats.duration!=undefined?v.stats.duration.toFixed(2):0;
+        v.currency = 'ms';
+        v.rate = v.stats.success_rate;
+        v.status = 'B'
+        v.variableValue = v.stats.success_rate;
+        if (v.children != undefined && v.children.length > 0) {
           v.children = this.handelListBizData(v.children)
         }
       })
-      console.log(arr,'------')
-      return arr;
+      return data;
     },
     handleData(data) {
       data.forEach((v, k) => {
@@ -620,7 +659,7 @@ export default {
     clickRowHandleNode(item){
       console.log(item,'点击节点')
       this.detailData = item;
-      // this.drawer=true;
+      this.drawerDetail=true;
     },
     handleSortChang(column, prop, order) {
       prop = column.prop
@@ -672,11 +711,14 @@ export default {
             if(_this.serveceMapList.length>0){
               for(let i=0;i<_this.serveceMapList.length;i++){
                 this.BizStatsQuery.biz_id = _this.serveceMapList[i].id
-                listBizStats(this.BizStatsQuery).then(resq=>{
-                  if(resq.data.biz_id != undefined){
-                    if(_this.serveceMapList[i].id == resq.data.biz_id){
-                      _this.serveceMapList[i] = Object.assign({},_this.serveceMapList[i], resq.data);
-                      _this.isUpdate = !_this.isUpdate;
+                listBizStats(this.BizStatsQuery).then(response=>{
+                  console.log(response,'response bizid-------')
+                  if(response.code == 200){
+                     if(response.data.biz_id != undefined){
+                      if(_this.serveceMapList[i].id == response.data.biz_id){
+                        _this.serveceMapList[i] = Object.assign({},_this.serveceMapList[i], response.data);
+                        _this.isUpdate = !_this.isUpdate;
+                      }
                     }
                   }
                 })
@@ -1004,7 +1046,27 @@ export default {
           type: 'category',
           boundaryGap: false,
           data: row.quantiles.time,
-          // show:true
+          axisLabel: {
+              textStyle: {
+                fontSize: 12,
+                textAlign:'center'
+              },
+              formatter: function(params) {
+                // let newParams = moment(params).format('YYYY-MM-DD HH:mm:ss');
+                // let newArr = newParams.split(' ')
+                // let time = newArr[0] + "\n" + newArr[1]
+                // return time;
+
+                  let newParams = ''
+                let dateStr = params.substring(0,10);
+                  // dateStr = dateStr.replace(/\-/g, function(match) {
+                  //   return match.replace(/\-/g, '.');
+                  // });
+                let timeStr = params.substring(11,19);
+                  newParams = dateStr + "\n" + timeStr
+                  return newParams;
+              }
+          },
         },
         yAxis: {
           type: 'value',
@@ -1194,6 +1256,6 @@ export default {
     width:60%;
   }
   .flex-right{
-    width:39.99
+    width:39.99%;
   }
 </style>

+ 4 - 4
src/views/business-analysis/analysis/components/TopoNew1.vue

@@ -339,7 +339,7 @@ export default {
     }
   },
   created(){
-    console.log(this.graphData,'topoNew组件接受到的父组件数据')
+    console.log(this.graphData,'topo组件中是否拿到数据')
   },
   mounted(){
    this.$nextTick(() => {
@@ -372,7 +372,7 @@ export default {
           const container = document.getElementById(id);
           // const container = this.$refs['container'];
           const width = container.scrollWidth;
-          const height = container.scrollHeight || 500;
+          const height = container.scrollHeight || 700;
          // 默认配置
           const defaultConfig = {
             width,
@@ -892,8 +892,8 @@ export default {
 
 <style lang="scss" scoped>
 .container{
-  // width:100%;
-  // height: 800px;
+  width:100%;
+  height: calc( 100vh - 182px);
   background: #fff;
 }
 .full{

+ 130 - 99
src/views/business-analysis/analysis/index.vue

@@ -8,26 +8,26 @@
               <el-tooltip placement="bottom" effect="dark" :visible-arrow='false'>
                 <div slot="content">
                   <i class="dot"></i>
-                  <span>{{digitsObj.biz}}</span>
+                  <span>{{digitsObj.biz !=undefined? digitsObj.biz:0}}</span>
                 </div>
                 <div class="border-bottom">
                   <div class="block-box px-3 py-4">
-                    <div class="col-tit">业务总数</div>
-                    <div class="col-con">{{digitsObj.biz}}</div>
+                    <div class="col-tit">业务类型总数</div>
+                    <div class="col-con">{{digitsObj.biz !=undefined? digitsObj.biz:0}}</div>
                   </div>
                 </div>
               </el-tooltip>
             </div>
-            <div class="col">
+            <div class="col" @click="go('/service/service/index')">
               <el-tooltip placement="bottom" effect="dark" :visible-arrow='false'>
                 <div slot="content">
                   <i class="dot"></i>
-                  <span>{{digitsObj.service}}</span>
+                  <span>{{digitsObj.service !=undefined? digitsObj.service:0}}</span>
                 </div>
                 <div class="border-bottom">
                   <div class="block-box px-3 py-4">
                     <div class="col-tit">服务总数</div>
-                    <div class="col-con">{{digitsObj.service}}</div>
+                    <div class="col-con">{{digitsObj.service !=undefined? digitsObj.service:0}}</div>
                   </div>
                 </div>
               </el-tooltip>
@@ -46,7 +46,7 @@
                 </div>
               </el-tooltip>
             </div> -->
-            <div class="col">
+            <!-- <div class="col">
               <el-tooltip placement="bottom" effect="dark" :visible-arrow='false'>
                 <div slot="content">
                   <i class="dot"></i>
@@ -55,21 +55,35 @@
                 <div class="border-bottom">
                   <div class="block-box px-3 py-4">
                     <div class="col-tit">错误总数</div>
-                    <div class="col-con">{{(digitsObj.error).toFixed(2)}}</div>
+                    <div class="col-con">{{digitsObj.error !=undefined?digitsObj.error:0}}</div>
                   </div>
                 </div>
               </el-tooltip>
-            </div>
-            <div class="col">
+            </div> -->
+             <div class="col">
               <el-tooltip placement="bottom" effect="dark" :visible-arrow='false'>
                 <div slot="content">
                   <i class="dot"></i>
-                  <span>{{digitsObj.error_rate}}</span>
+                  <span>{{digitsObj.error_rate !=undefined?digitsObj.error_rate:0}}</span>
                 </div>
                 <div class="border-bottom">
                   <div class="block-box px-3 py-4">
                     <div class="col-tit">错误率</div>
-                    <div class="col-con">{{(digitsObj.error_rate*100).toFixed(2)}}%</div>
+                    <div class="col-con">{{digitsObj.error_rate !=undefined?(digitsObj.error_rate*100).toFixed(2):0}}%</div>
+                  </div>
+                </div>
+              </el-tooltip>
+            </div>
+             <div class="col">
+              <el-tooltip placement="bottom" effect="dark" :visible-arrow='false'>
+                <div slot="content">
+                  <i class="dot"></i>
+                  <span>{{digitsObj.error_per_minute != undefined?digitsObj.error_per_minute:0}}</span>
+                </div>
+                <div class="border-bottom">
+                  <div class="block-box px-3 py-4">
+                    <div class="col-tit">错误频率/min</div>
+                    <div class="col-con">{{digitsObj.error_per_minute !=undefined?(digitsObj.error_per_minute).toFixed(4):0}}</div>
                   </div>
                 </div>
               </el-tooltip>
@@ -78,12 +92,12 @@
               <el-tooltip placement="bottom" effect="dark" :visible-arrow='false'>
                 <div slot="content">
                   <i class="dot"></i>
-                  <span>{{digitsObj.trace_per_minute}}</span>
+                  <span>{{digitsObj.trace_per_minute!=undefined?digitsObj.trace_per_minute:0}}</span>
                 </div>
                 <div class="border-bottom">
                   <div class="block-box px-3 py-4">
-                    <div class="col-tit">业务</div>
-                    <div class="col-con">{{(digitsObj.trace_per_minute).toFixed(2)}}</div>
+                    <div class="col-tit">业务频率/min</div>
+                    <div class="col-con">{{digitsObj.trace_per_minute!=undefined?digitsObj.trace_per_minute:0}}</div>
                   </div>
                 </div>
               </el-tooltip>
@@ -92,12 +106,12 @@
               <el-tooltip placement="bottom" effect="dark" :visible-arrow='false'>
                 <div slot="content">
                   <i class="dot"></i>
-                  <span>{{digitsObj.database_biz}}</span>
+                  <span>{{digitsObj.database_biz_per_minute != undefined?digitsObj.database_biz_per_minute:0}}</span>
                 </div>
                 <div class="border-bottom">
                   <div class="block-box px-3 py-4">
-                    <div class="col-tit">DB总数</div>
-                    <div class="col-con">{{digitsObj.database_biz}}</div>
+                    <div class="col-tit">DB查询频率/min</div>
+                    <div class="col-con">{{digitsObj.database_biz_per_minute != undefined?digitsObj.database_biz_per_minute :0}}</div>
                   </div>
                 </div>
               </el-tooltip>
@@ -110,9 +124,9 @@
             <div class="echartsWrap">
               <div id="qualityWrap" style="width:100%;height:200px"></div>
             </div>
-            <h6 class="h6">错误</h6>
+            <h6 class="h6">错误分布</h6>
             <div class="echartsWrap">
-              <el-form ref="errorQuery" :model="errorQuery" :inline="true" label-width="68px" style='margin-left: 3%;'>
+              <!-- <el-form ref="errorQuery" :model="errorQuery" :inline="true" label-width="68px" style='margin-left: 3%;'>
                 <el-form-item label="时间单位" prop="time_type">
                   <el-select v-model="errorQuery.time_type" placeholder="时间单位" clearable size="small" @keyup.enter.native="handleErrorQuery" @change='changeErrorQuery'>
                     <el-option
@@ -135,18 +149,13 @@
                 <el-form-item label="基础时间" prop="time_base">
                     <el-date-picker size="small" type="datetime" format='yyyy-MM-dd HH:mm:ss' value-format="timestamp" placeholder="选择时间" v-model="time_base" @change='changeTimeErrorQuery'></el-date-picker>
                 </el-form-item>
-                
-                <!-- <el-form-item>
-                  <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
-                  <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
-                </el-form-item> -->
-              </el-form>
+              </el-form> -->
               <div id="errorWrap" style="width:100%;height:200px"></div>
             </div>
           </el-tab-pane>
           <el-tab-pane label="解析列表" name="second">
             <!-- <Biz/> -->
-            <service-map></service-map>
+            <AnalysisMap />
           </el-tab-pane>
         </el-tabs>
       </el-card>
@@ -159,12 +168,12 @@ import resize from '../mixins/resize'
 import {listUrlMappingErrors,listUrlMappingQuality,listBiz,listBizStats,getBizDetail,listBizGraph,listBizGraphStats,digitsBiz} from '@/api/mapping'
 import storage from '@/utils/storage'
 // import Biz from './components/biz'
-import ServiceMap from './components/ServiceMap'
+import AnalysisMap from './components/AnalysisMap'
 export default {
   mixins: [resize],
   components:{
     // Biz,
-    ServiceMap
+    AnalysisMap
   },
   data(){
     return{
@@ -175,8 +184,8 @@ export default {
         // url_type:2,   // 0未知 1对内接口 2对外接口
         // start_time:1703656033,
         // end_time:1703656333,
-        time_type:'hour',   // 时间单位, hour或day
-        time_value:10,   // 与时间单位组合,本例为10小时
+        time_type:'day',   // 时间单位, hour或day
+        time_value:30,   // 与时间单位组合,本例为10小时
         time_base: new Date().getTime().toString()
       },
       time_base:new Date().getTime().toString(),
@@ -270,6 +279,9 @@ export default {
     },
     handleClick(tab,event){
 
+    },
+    go(path){
+      this.$router.push(path)
     },
     getDigitsBiz(){
       digitsBiz(this.digitsQuery).then((res)=>{
@@ -339,6 +351,27 @@ export default {
           ]
         }
       )
+      this.errorChart.on('click', function(params) {
+
+          console.log(params, params.componentType);
+
+          if (params.componentType === 'xAxis') {
+
+            return params;
+
+          } else if (params.componentType === 'series') {
+
+            // barForm.feature = params.name;
+
+            // nextTick(() => {
+
+            //   emit('sumRiskClick', { params });
+
+            // });
+
+          }
+
+      });
     },
     initQualityChart(data) {
       console.log(data,'this.qualityObj')
@@ -354,6 +387,21 @@ export default {
             }
           }
         },
+        legend: {
+          data:['当前时段','前续时段对比'],
+          selected: {
+                '当前时段': true,
+                '前续时段对比': false
+            }
+        },
+        toolbox: {
+          feature: {
+            // dataView: { show: true, readOnly: false },
+            magicType: { show: true, type: ['line', 'bar'] },
+            restore: { show: true },
+            // saveAsImage: { show: true }
+          }
+        },
         grid: {
           // top:'5%',
           left: '3%',
@@ -363,7 +411,7 @@ export default {
         },
         xAxis: [
           {
-            type: 'value',
+            type: 'category',
             data: data.buckets,
             axisPointer: {
               type: 'shadow'
@@ -377,99 +425,82 @@ export default {
         ],
         series: [
           {
+            name:'当前时段',
             type: 'bar',
             tooltip: {
               valueFormatter: function (value) {
                 return value;
               }
             },
-            barWidth:6,
+            barWidth:8,
             markLine: {
-              // data: [
-              //   { type: 'average', name: 'Avg' },
-              //   {name: 'Y 轴值为 100 的水平线',yAxis: 100},
-              // ]
+              label:{
+                formatter: '{b}',
+                backgroundColor:"#5A6FC0",
+                color:"#fff",
+                padding:[4,8]
+              },
+              lineStyle: {
+                type: "dashed",
+                color: "#5A6FC0",
+                width:2
+              },
               data: [
-                // {
-                //     name: '平均线',
-                //     // 支持 'average', 'min', 'max'
-                //     type: 'average'
-                // },
-                {
-                    name: 'p50',
-                    xAxis: 'min',
-                    coord: [150, 200]
-                    // x:'50%'
-                },
-                {
-                    name: 'p90',
-                    xAxis: '400-800',
-                    x:'70%'
-                },
-                {
-                    name: 'p99',
-                    xAxis: 'max',
-                    x:'90%'
-                },
-                // [
-                //     {
-                //         // 起点和终点的项会共用一个 name
-                //         name: '最小值到最大值',
-                //         type: 'min'
-                //     },
-                //     {
-                //         type: 'max'
-                //     }
-                // ],
-                // [
-                //     {
-                //         name: '两个坐标之间的标线',
-                //         coord: [10, 20]
-                //     },
-                //     {
-                //         coord: [20, 30]
-                //     }
-                // ],
-                //  [{
-                //     // 固定起点的 x 像素位置,用于模拟一条指向最大值的水平线
-                //     xAxis: 'max',
-                //     x: '50%'
-                // }, {
-                //     type: 'max'
-                // }],
-                // [
-                //     {
-                //         name: '两个屏幕坐标之间的标线',
-                //         x: 100,
-                //         y: 100
-                //     },
-                //     {
-                //         x: 500,
-                //         y: 200
-                //     }
-                // ]
+                  {
+                      name: 'p50',
+                      xAxis:data.buckets[data.current.quantile_indexes.p50],
+                  },
+                  {
+                      name: 'p90',
+                      xAxis:data.buckets[data.current.quantile_indexes.p90],
+                  },
+                  {
+                      name: 'p99',
+                      xAxis:data.buckets[data.current.quantile_indexes.p99],
+                  },
               ]
             },
             data: data.current.counts != undefined?data.current.counts :[],            
           },
           {
             type: 'line',
+            name:'前续时段对比',
             tooltip: {
               valueFormatter: function (value) {
                 return value;
               }
             },
+            lineStyle:{
+              width:3
+            },
             markLine: {
                 name: "",
                 // symbol: ["none", "none"], //去掉箭头
                 lineStyle: {
-                    type: "solid",
-                    color: "rgb(252,13,27)",
+                    type: "dashed",
+                    color: "#9ECA7E",
+                    width:2
                 },
                 label: {
-                    // show: false, //不展示标识线数字
+                    formatter: '{b}',
+                    backgroundColor:"#9ECA7E",
+                    color:"#fff",
+                    padding:[4,8]
                 },
-                data: [{xAxis:934}], //这里设置false是隐藏不了的,可以设置为-1
+                data: [
+                  {
+                    name: 'p50',
+                    xAxis:data.buckets[data.previous.quantile_indexes.p50],
+                  },
+                  {
+                    name: 'p90',
+                    xAxis:data.buckets[data.previous.quantile_indexes.p90],
+                  },
+                  {
+                    name: 'p99',
+                    xAxis:data.buckets[data.previous.quantile_indexes.p99],
+                  }
+                ], //这里设置false是隐藏不了的,可以设置为-1
             },
 
             data:data.previous.counts

+ 96 - 64
src/views/business-analysis/panel/index.vue

@@ -7,42 +7,66 @@
             <div class="dataBlock">
               <el-row :gutter="10">
                 <el-col :span="6">
-                  <div class="grid-container">
-                    <div class="grid-header">
-                      <h6 class="grid-header-title">健康度</h6>
+                  <el-tooltip placement="bottom" effect="dark" :visible-arrow='false'>
+                    <div slot="content">
+                      <i class="dot"></i>
+                      <span>{{apdex!=undefined?apdex:0}}</span>
                     </div>
-                    <div class="grid-content">
-                      <span :class="ApdexNum>=0.94?'gc'
-                      :(ApdexNum>=0.85&&ApdexNum<0.94)?'bc'
-                      :(ApdexNum>=0.7&&ApdexNum<0.85)?'grc'
-                      :(ApdexNum>=0.5&&ApdexNum<0.7)?'oc'
-                      :'rc'">{{apdex}}</span>
+                    <div class="grid-container">
+                      <div class="grid-header">
+                        <h6 class="grid-header-title">健康度</h6>
+                      </div>
+                      <div class="grid-content">
+                        <span :class="ApdexNum>=0.94?'gc'
+                        :(ApdexNum>=0.85&&ApdexNum<0.94)?'bc'
+                        :(ApdexNum>=0.7&&ApdexNum<0.85)?'grc'
+                        :(ApdexNum>=0.5&&ApdexNum<0.7)?'oc'
+                        :'rc'" style="font-size:46px;font-weight:500">{{ApdexNum>=0.94?'性能极佳':(ApdexNum>=0.85 && ApdexNum<0.94)?"性能较好":(ApdexNum>=0.7&&ApdexNum<0.85)?"性能一般":(ApdexNum>=0.5&&ApdexNum<0.7)?"性能一般":"性能不佳"}}</span>
+                      </div>
                     </div>
-                  </div>
+                  </el-tooltip>
                 </el-col>
                 <el-col :span="6">
-                  <div class="grid-container">
-                    <div class="grid-header">
-                      <h6 class="grid-header-title">业务总数</h6>
+                  <el-tooltip placement="bottom" effect="dark" :visible-arrow='false'>
+                    <div slot="content">
+                      <i class="dot"></i>
+                      <span>{{apdex!=undefined?apdex:0}}</span>
                     </div>
-                    <div class="grid-content">411</div>
-                  </div>
+                    <div class="grid-container">
+                      <div class="grid-header">
+                        <h6 class="grid-header-title">业务总数</h6>
+                      </div>
+                      <div class="grid-content">411</div>
+                    </div>
+                  </el-tooltip>
                 </el-col>
                 <el-col :span="6">
-                  <div class="grid-container">
-                    <div class="grid-header">
-                      <h6 class="grid-header-title">Server总数</h6>
+                  <el-tooltip placement="bottom" effect="dark" :visible-arrow='false'>
+                    <div slot="content">
+                      <i class="dot"></i>
+                      <span>{{apdex!=undefined?apdex:0}}</span>
                     </div>
-                    <div class="grid-content">133411</div>
-                  </div>
+                    <div class="grid-container">
+                      <div class="grid-header">
+                        <h6 class="grid-header-title">Server总数</h6>
+                      </div>
+                      <div class="grid-content">133411</div>
+                    </div>
+                  </el-tooltip>
                 </el-col>
                 <el-col :span="6">
-                  <div class="grid-container">
-                    <div class="grid-header">
-                      <h6 class="grid-header-title">对外接口总数</h6>
+                  <el-tooltip placement="bottom" effect="dark" :visible-arrow='false'>
+                    <div slot="content">
+                      <i class="dot"></i>
+                      <span>{{apdex!=undefined?apdex:0}}</span>
                     </div>
-                    <div class="grid-content">133411</div>
-                  </div>
+                    <div class="grid-container">
+                      <div class="grid-header">
+                        <h6 class="grid-header-title">对外接口总数</h6>
+                      </div>
+                      <div class="grid-content">133411</div>
+                    </div>
+                  </el-tooltip>
                 </el-col>
                 
               </el-row>
@@ -103,7 +127,7 @@
             <div class="amountIframe">
                 <div class="header">
                   <div class="header-right">
-                    <el-button type="primary" size="mini" style="margin-right:12px;vertical-align: middle;" round @click="handleIframe">使用Iframe</el-button>
+                    <el-button type="primary" size="mini" style="margin-right:12px;vertical-align: middle;" round @click="handleIframe">使用快捷站点</el-button>
                   </div>
                 </div>
                 <div v-if='iframeFlag'>
@@ -122,8 +146,8 @@
                   <!-- <el-form ref="form" :model="form" :rules="rules" label-width="120px">
                       <el-row>
                         <el-col :span="24">
-                          <el-form-item label="URL地址:" prop="url">
-                            <el-input v-model="form.url" placeholder="请填入需要绑定的页面URL" />
+                          <el-form-item label="站点地址:" prop="url">
+                            <el-input v-model="form.url" placeholder="请填入需要绑定的站点URL" />
                           </el-form-item>
                         </el-col>
                         <el-col :span="24">
@@ -180,8 +204,8 @@
           <el-form ref="form" :model="form" :rules="rules" label-width="120px">
               <el-row>
                 <el-col :span="24">
-                  <el-form-item label="URL地址:" prop="url">
-                    <el-input v-model="form.url" placeholder="请填入需要绑定的页面URL" />
+                  <el-form-item label="站点地址:" prop="url">
+                    <el-input v-model="form.url" placeholder="请填入需要绑定的站点URL" />
                   </el-form-item>
                 </el-col>
                 <el-col :span="24">
@@ -688,40 +712,48 @@ export default {
   }
 }
 .gc{
-      // background: #66DC4A;
-    color:#00B54F;
-  }
-  .bc{
-    color: #60B4F9;
-  }
-  .grc{
-    color: #8B8B8B;
-  }
-  .oc{
-    color: #F1A657;
-  }
-  .rc{
-    color: #EA463D;
+    // background: #66DC4A;
+  color:#00B54F;
+}
+.bc{
+  color: #60B4F9;
+}
+.grc{
+  color: #8B8B8B;
+}
+.oc{
+  color: #F1A657;
+}
+.rc{
+  color: #EA463D;
+}
+.header{
+  position: absolute;
+  z-index: 99;
+  min-width: 1000px;
+  width: 100%;
+  border-bottom: 0;
+  height: 60px;
+  line-height: 60px;
+  background: #fff;
+  left: 0px;
+  .header-right{
+      position: absolute;
+      right: 0;
+      top: 0;
+      z-index: 100;
+      height: 60px;
+      padding-right: 24px;
+      padding-left: 200px;
+      -webkit-tap-highlight-color: transparent;
   }
-  .header{
-    position: absolute;
-    z-index: 99;
-    min-width: 1000px;
-    width: 100%;
-    border-bottom: 0;
-    height: 60px;
-    line-height: 60px;
-    background: #fff;
-    left: 0px;
-    .header-right{
-        position: absolute;
-        right: 0;
-        top: 0;
-        z-index: 100;
-        height: 60px;
-        padding-right: 24px;
-        padding-left: 200px;
-        -webkit-tap-highlight-color: transparent;
+}
+.dot{
+      display: inline-block !important;
+      width:8px !important;
+      height: 8px !important;
+      border-radius: 50% !important;
+      background: #1976d2 !important;
+      margin-right: 12px !important;
     }
-  }
 </style>

+ 59 - 25
src/views/index/index.vue

@@ -48,7 +48,7 @@
                 <div class="border-bottom">
                   <div class="block-box px-3 py-4">
                     <div class="col-tit">应用系统总量</div>
-                    <div class="col-con">{{appList.length}}</div>
+                    <div class="col-con">{{appList.length !=undefined?appList.length:0}}</div>
                   </div>
                 </div>
               </el-tooltip>
@@ -59,7 +59,7 @@
                 <div class="border-bottom">
                   <div class="block-box px-3 py-4">
                     <div class="col-tit">服务总量</div>
-                    <div class="col-con">{{statusData.services}}</div>
+                    <div class="col-con">{{statusData.services!=undefined?statusData.services:0}}</div>
                   </div>
                 </div>
               </el-tooltip>
@@ -70,7 +70,7 @@
                 <div class="border-bottom">
                   <div class="block-box px-3 py-4">
                     <div class="col-tit">Trace总量</div>
-                    <div class="col-con">{{statusData.traces}}</div>
+                    <div class="col-con">{{statusData.traces != undefined? statusData.traces:0}}</div>
                   </div>
                 </div>
               </el-tooltip>
@@ -81,7 +81,7 @@
                 <div class="border-bottom">
                   <div class="block-box px-3 py-4">
                     <div class="col-tit">日志总量</div>
-                    <div class="col-con">{{statusData.logs}}</div>
+                    <div class="col-con">{{statusData.logs !=undefined?statusData.logs :0}}</div>
                   </div>
                 </div>
               </el-tooltip>
@@ -92,7 +92,7 @@
                 <div class="border-bottom">
                   <div class="block-box px-3 py-4">
                     <div class="col-tit">用户总量</div>
-                    <div class="col-con">{{statusData.users}}</div>
+                    <div class="col-con">{{statusData.users !=undefined?statusData.users:0}}</div>
                   </div>
                 </div>
               </el-tooltip>
@@ -223,6 +223,11 @@ export default {
         // immediate: true,
         deep: true
     },
+    statusData:{
+      handler(newValue, oldValue){
+
+      }
+    },
   },
   methods:{
     handlerNumber(num){
@@ -282,7 +287,7 @@ export default {
           storage.set('appsItem',obj);
 
           this.$router.push({
-            path:'apps/index',
+            path:'/business-analysis/analysis/index',
             query:{
               id:val.id,
               app_alias:val.alias, 
@@ -309,7 +314,8 @@ export default {
           let req_applist =[]
           let app_ids =[]
           if(res.code == 200){
-            // this.appsList = res.data.list
+            console.log(res,'获取所有的list')
+            this.appsList = res.data.list
             let arr = res.data.list;
              res.data.list.map((item)=>{
               req_applist.push({app_alias:item.alias});
@@ -332,28 +338,56 @@ export default {
 
                       }
                     }
-                    eventNums(this.queryNums).then((res)=>{
-                      console.log(res,'数量')
-                      if(res.code == 200){
-                        if(res.data.list.length!=0){
-                          for(let i=0;i<arr.length;i++){
-                            for(let j=0;j<res.data.list.length;j++){
-                              if(arr[i].id == res.data.list[j].app_id){
-                                arr[i] = Object.assign({},arr[i], res.data.list[j])
-                              }else{
-                                arr[i].exception_num = undefined;
-                              }
-                              console.log(arr[i].exception_num,'exception_num')
-                            }
-                          }
+                    this.appList = arr
+                    // eventNums(this.queryNums).then((res)=>{
+                    //   console.log(res,'数量')
+                    //   if(res.code == 200){
+                    //     if(res.data.list.length!=0){
+                    //       for(let i=0;i<arr.length;i++){
+                    //         for(let j=0;j<res.data.list.length;j++){
+                    //           if(arr[i].id == res.data.list[j].app_id){
+                    //             arr[i] = Object.assign({},arr[i], res.data.list[j])
+                    //           }else{
+                    //             arr[i].exception_num = undefined;
+                    //           }
+                    //           console.log(arr[i].exception_num,'exception_num')
+                    //         }
+                    //       }
+                    //     }
+                    //   }
+                    //   this.appList=arr; 
+                    // })
+                  }else{
+                    this.appList = arr
+                  }
+                  // this.appList = arr
+                }
+              })
+              
+            }
+
+            if(app_ids.length>0){
+              eventNums(this.queryNums).then((res)=>{
+                console.log(res,'数量')
+                if(res.code == 200){
+                  if(res.data.list.length>0){
+                    for(let i=0;i<arr.length;i++){
+                      for(let j=0;j<res.data.list.length;j++){
+                        if(arr[i].id == res.data.list[j].app_id){
+                          arr[i] = Object.assign({},arr[i], res.data.list[j])
+                        }else{
+                          arr[i].exception_num = 0;
                         }
+                        console.log(arr[i].exception_num,'exception_num')
                       }
-                      this.appList=arr; 
-                    })
+                    }
+                   this.appList=arr; 
+                  }else{
+                    this.appList=arr; 
                   }
                 }
+                
               })
-              
             }
               
           }
@@ -436,8 +470,8 @@ export default {
     handleQuery(){}
   },
   created(){
-    this.getList();
     this.getData();
+    this.getList();
   },
 }
 </script>

+ 3 - 3
src/views/instruction/carry/index.vue

@@ -5,7 +5,7 @@
         <div class="amountIframe">
             <div class="header" v-if='iframeFlag'>
               <div class="header-right">
-                <el-button type="primary" size="mini" style="margin-right:12px;vertical-align: middle;" round @click="handleIframe">使用Iframe</el-button>
+                <el-button type="primary" size="mini" style="margin-right:12px;vertical-align: middle;" round @click="handleIframe">使用快捷站点</el-button>
               </div>
             </div>
             <div v-if='iframeFlag'>
@@ -27,8 +27,8 @@
           <el-form ref="form" :model="form" :rules="rules" label-width="120px">
               <el-row>
                 <el-col :span="24">
-                  <el-form-item label="URL地址:" prop="url">
-                    <el-input v-model="form.url" placeholder="请填入需要绑定的页面URL" />
+                  <el-form-item label="站点地址:" prop="url">
+                    <el-input v-model="form.url" placeholder="请填入需要绑定的站点URL" />
                   </el-form-item>
                 </el-col>
                 <el-col :span="24">

+ 3 - 3
src/views/instruction/grafana/index.vue

@@ -5,7 +5,7 @@
         <div class="amountIframe">
             <div class="header" v-if='iframeFlag'>
               <div class="header-right">
-                <el-button type="primary" size="mini" style="margin-right:12px;vertical-align: middle;" round @click="handleIframe">使用Iframe</el-button>
+                <el-button type="primary" size="mini" style="margin-right:12px;vertical-align: middle;" round @click="handleIframe">使用快捷站点</el-button>
               </div>
             </div>
             <div v-if='iframeFlag'>
@@ -27,8 +27,8 @@
           <el-form ref="form" :model="form" :rules="rules" label-width="120px">
               <el-row>
                 <el-col :span="24">
-                  <el-form-item label="URL地址:" prop="url">
-                    <el-input v-model="form.url" placeholder="请填入需要绑定的页面URL" />
+                  <el-form-item label="站点地址:" prop="url">
+                    <el-input v-model="form.url" placeholder="请填入需要绑定的站点URL" />
                   </el-form-item>
                 </el-col>
                 <el-col :span="24">

+ 3 - 3
src/views/instruction/java/index.vue

@@ -5,7 +5,7 @@
         <div class="amountIframe">
             <div class="header" v-if='iframeFlag'>
               <div class="header-right">
-                <el-button type="primary" size="mini" style="margin-right:12px;vertical-align: middle;" round @click="handleIframe">使用Iframe</el-button>
+                <el-button type="primary" size="mini" style="margin-right:12px;vertical-align: middle;" round @click="handleIframe">使用快捷站点</el-button>
               </div>
             </div>
             <div v-if='iframeFlag'>
@@ -27,8 +27,8 @@
           <el-form ref="form" :model="form" :rules="rules" label-width="120px">
               <el-row>
                 <el-col :span="24">
-                  <el-form-item label="URL地址:" prop="url">
-                    <el-input v-model="form.url" placeholder="请填入需要绑定的页面URL" />
+                  <el-form-item label="站点地址:" prop="url">
+                    <el-input v-model="form.url" placeholder="请填入需要绑定的站点URL" />
                   </el-form-item>
                 </el-col>
                 <el-col :span="24">

+ 3 - 3
src/views/instruction/javascript/index.vue

@@ -5,7 +5,7 @@
         <div class="amountIframe">
             <div class="header" v-if='iframeFlag'>
               <div class="header-right">
-                <el-button type="primary" size="mini" style="margin-right:12px;vertical-align: middle;" round @click="handleIframe">使用Iframe</el-button>
+                <el-button type="primary" size="mini" style="margin-right:12px;vertical-align: middle;" round @click="handleIframe">使用快捷站点</el-button>
               </div>
             </div>
             <div v-if='iframeFlag'>
@@ -27,8 +27,8 @@
           <el-form ref="form" :model="form" :rules="rules" label-width="120px">
               <el-row>
                 <el-col :span="24">
-                  <el-form-item label="URL地址:" prop="url">
-                    <el-input v-model="form.url" placeholder="请填入需要绑定的页面URL" />
+                  <el-form-item label="站点地址:" prop="url">
+                    <el-input v-model="form.url" placeholder="请填入需要绑定的站点URL" />
                   </el-form-item>
                 </el-col>
                 <el-col :span="24">

+ 3 - 3
src/views/link-log/index.vue

@@ -5,7 +5,7 @@
         <div class="amountIframe">
             <div class="header" v-if='iframeFlag'>
               <div class="header-right">
-                <el-button type="primary" size="mini" style="margin-right:12px;vertical-align: middle;" round @click="handleIframe">使用Iframe</el-button>
+                <el-button type="primary" size="mini" style="margin-right:12px;vertical-align: middle;" round @click="handleIframe">使用快捷站点</el-button>
               </div>
             </div>
             <div v-if='iframeFlag'>
@@ -27,8 +27,8 @@
           <el-form ref="form" :model="form" :rules="rules" label-width="120px">
               <el-row>
                 <el-col :span="24">
-                  <el-form-item label="URL地址:" prop="url">
-                    <el-input v-model="form.url" placeholder="请填入需要绑定的页面URL" />
+                  <el-form-item label="站点地址:" prop="url">
+                    <el-input v-model="form.url" placeholder="请填入需要绑定的站点URL" />
                   </el-form-item>
                 </el-col>
                 <el-col :span="24">

+ 3 - 3
src/views/platform/self-monitoring/index.vue

@@ -5,7 +5,7 @@
         <div class="amountIframe">
             <div class="header" v-if='iframeFlag'>
               <div class="header-right">
-                <el-button type="primary" size="mini" style="margin-right:12px;vertical-align: middle;" round @click="handleIframe">使用Iframe</el-button>
+                <el-button type="primary" size="mini" style="margin-right:12px;vertical-align: middle;" round @click="handleIframe">使用快捷站点</el-button>
               </div>
             </div>
             <div v-if='iframeFlag'>
@@ -27,8 +27,8 @@
           <el-form ref="form" :model="form" :rules="rules" label-width="120px">
               <el-row>
                 <el-col :span="24">
-                  <el-form-item label="URL地址:" prop="url">
-                    <el-input v-model="form.url" placeholder="请填入需要绑定的页面URL" />
+                  <el-form-item label="站点地址:" prop="url">
+                    <el-input v-model="form.url" placeholder="请填入需要绑定的站点URL" />
                   </el-form-item>
                 </el-col>
                 <el-col :span="24">

+ 83 - 21
src/views/service/Interface/components/ServiceMap.vue → src/views/service/Interface/components/InterfaceMap.vue

@@ -15,13 +15,43 @@
         <el-row :gutter="10" class="mb8">
           <el-col :span="1.5">
             <el-button
-              v-permisaction="['disposition:index:add']"
               type="primary"
               icon="el-icon-plus"
               size="mini"
               @click="handleAdd"
             >新增</el-button>
           </el-col>
+          <el-col :span="2">
+              <div style='display:inline-block;vertical-align: middle;'>
+                <el-dropdown
+                  style="margin-left: 10px"
+                  size="mini"
+                  trigger="click"
+                  placement="bottom"
+                >
+                  <el-button type="primary" size="mini">
+                    <!-- 下拉菜单 -->
+                    <i class="el-icon-s-grid" />
+                    <i class="el-icon-arrow-down"></i>
+                  </el-button>
+                  <el-dropdown-menu slot="dropdown">
+                    <el-checkbox-group
+                      v-model="colSelect"
+                      style="text-align: left"
+                      @change="columnChange"
+                    >
+                      <el-dropdown-item
+                        v-for="(item, index) in colData"
+                        :key="index"
+                        ><el-checkbox :label="item.title">{{
+                          item.title
+                        }}</el-checkbox></el-dropdown-item
+                      >
+                    </el-checkbox-group>
+                  </el-dropdown-menu>
+                </el-dropdown>
+              </div>
+          </el-col>
         </el-row>
 
         <div>
@@ -32,46 +62,46 @@
             :default-sort = "{prop: 'total', order: 'descending'}"
             @row-click="handleRowClick" 
           >
-            <el-table-column header-align="left" label="接口名" prop="name" align="left" :show-overflow-tooltip="true"/>
-            <el-table-column header-align="left" label="URL组" prop="url" align="left" :show-overflow-tooltip="true">
+            <el-table-column header-align="left" label="接口名" prop="name" align="left" :show-overflow-tooltip="true" v-if="colData[0].istrue"/>
+            <el-table-column header-align="left" label="URL组" prop="url" align="left" :show-overflow-tooltip="true" v-if="colData[1].istrue">
               <template slot-scope="scope">
                 <!-- <span style="cursor:pointer" @click="toogleExpand(row,$index)">{{scope.row.url}}</span> -->
                 <span>{{scope.row.url}}</span>
               </template>
             </el-table-column>
-            <el-table-column header-align="center" label="rpm" sortable prop="rpm" align="center" :show-overflow-tooltip="true">
+            <el-table-column header-align="center" label="rpm" sortable prop="rpm" align="center" :show-overflow-tooltip="true" v-if="colData[2].istrue">
               <template slot-scope="scope">
                 <!-- <span>{{ Number(scope.row.rpm).toFixed(2)}}</span> -->
                 <el-tag>{{ Number(scope.row.rpm).toFixed(2)}}</el-tag>
               </template>
             </el-table-column>
-            <el-table-column header-align="center" label="count" sortable prop="total" align="center">
+            <el-table-column header-align="center" label="count" sortable prop="total" align="center" v-if="colData[3].istrue">
               <template slot-scope="scope">
                 <!-- <span>{{ Number(scope.row.rpm).toFixed(2)}}</span> -->
                 <el-tag>{{ Number(scope.row.total).toFixed(2)}}</el-tag>
               </template>
             </el-table-column>
-            <el-table-column header-align="center" label="errRate" sortable prop="error_rate" align="center">
+            <el-table-column header-align="center" label="errRate" sortable prop="error_rate" align="center" v-if="colData[4].istrue">
               <template slot-scope="scope">
                  <el-tag v-if="scope.row.error_rate==0">{{  scope.row.error_rate }}</el-tag>
                     <el-tag v-else type="danger">{{  Number(scope.row.error_rate).toFixed(2)}}</el-tag>
               </template>
             </el-table-column>
-            <el-table-column header-align="center" label="max(ms)" sortable prop="max" align="center" width="100">
+            <el-table-column header-align="center" label="max(ms)" sortable prop="max" align="center" width="100" v-if="colData[5].istrue">
               <template slot-scope="scope">
                 <!-- <span>{{ Number(scope.row.max).toFixed(2)}}</span> -->
                 <el-tag v-if="scope.row.max>=2000" type="danger">{{ Number(scope.row.max).toFixed(2) }}</el-tag>
                 <el-tag v-if="scope.row.max<2000">{{ Number(scope.row.max).toFixed(2) }}</el-tag>
               </template>
             </el-table-column>
-            <el-table-column header-align="center" label="avg(ms)" sortable prop="avg" align="center" width="100">
+            <el-table-column header-align="center" label="avg(ms)" sortable prop="avg" align="center" width="100" v-if="colData[6].istrue">
               <template slot-scope="scope">
                 <!-- <span>{{ Number(scope.row.avg).toFixed(2)}}</span> -->
                 <el-tag v-if="scope.row.avg>=2000" type="danger">{{ Number(scope.row.avg).toFixed(2) }}</el-tag>
                 <el-tag v-if="scope.row.avg<2000">{{ Number(scope.row.avg).toFixed(2) }}</el-tag>
               </template>
             </el-table-column>
-            <el-table-column header-align="center" label="延迟比例" prop="duration_stats" align="center">
+            <el-table-column header-align="center" label="延迟比例" prop="duration_stats" align="center" v-if="colData[7].istrue">
                 <template slot-scope="scope">
                   {{ drawEchartsp5(scope.row, scope.$index, 'five') }}
                   <div :id="`tiger-five-trend-index` + scope.$index" class="tiger-trend-charts"></div>
@@ -116,15 +146,15 @@
             </el-table-column>
           </el-table>
         </div>
-        <div class="more" v-if="serveceMapList.length<tableCount" @click="loadMore">加载更多</div>
-        <div class="more nomore" v-if="loading==false&&serveceMapList.length>=tableCount">已加载完所有的数据!</div>
-        <!-- <pagination
-          v-show="total>0"
-          :total="total"
-          :page.sync="childQueryParams.pageIndex"
-          :limit.sync="childQueryParams.pageSize"
-          @pagination="handelgetUrlMappingRange"
-        /> -->
+        <!-- <div class="more" v-if="serveceMapList.length<tableCount" @click="loadMore">加载更多</div>
+        <div class="more nomore" v-if="loading==false&&serveceMapList.length>=tableCount">已加载完所有的数据!</div> -->
+        <pagination
+          v-show="tableCount>0"
+          :total="tableCount"
+          :page.sync="queryParams.pageIndex"
+          :limit.sync="queryParams.pageSize"
+          @pagination="getList"
+        />
 
         <!-- 添加或修改应用配置对话框 -->
         <el-dialog v-if="open" :title="title" :visible.sync="open" width="700px" :center='true' :close-on-click-modal="false">
@@ -261,6 +291,26 @@ export default {
   // },
   data() {
     return {
+      // 设置选中的列的复选框
+      colSelect: [
+        "接口名",
+        "URL组",
+        "rpm",
+        "count",
+        "errRate",
+        "max(ms)",
+        "延迟比例",
+      ],
+      colData: [
+        { title: "接口名", istrue: false },
+        { title: "URL组", istrue: false },
+        { title: "rpm", istrue: false },
+        { title: "count", istrue: false },
+        { title: "errRate", istrue: false },
+        { title: "max(ms)", istrue: false },
+        { title: "avg(ms)", istrue: false },
+        { title: "延迟比例", istrue: false },
+      ],
       drawer:false,
       detailData:{},
       tableLoading:false,
@@ -299,7 +349,7 @@ export default {
         favor:'',
         url:'',
         pageIndex: 1,
-        pageSize: 50,
+        pageSize: 10,
       },
       // 表单参数
       form: {
@@ -377,10 +427,21 @@ export default {
       this.childQueryParams.app_id = this.appsItem.id;
       this.getList()
     }
+    this.columnChange();
   },
   mounted(){
   },
   methods: {
+     //控制列的显示和隐藏
+    columnChange(val) {
+      this.colData.filter((i) => {
+        if (this.colSelect.indexOf(i.title) !== -1) {
+          i.istrue = true;
+        } else {
+          i.istrue = false;
+        }
+      });
+    },
     Refresh(timeOut){
       this.serviceMapTimer = setInterval(()=>{
         this.getList();
@@ -478,10 +539,11 @@ export default {
           if(res.code == 200){
             console.log(res.data.list,'业务映射')
             this.loading = false;
-            this.serveceMapList= this.serveceMapList.concat(res.data.list);
+            // this.serveceMapList= this.serveceMapList.concat(res.data.list);
+            this.serveceMapList=res.data.list
             console.log(this.serveceMapList,'this.serveceMapList 所有接口映射内容')
             this.tableCount = res.data.count;
-            this.queryParams.pageIndex = res.data.pageIndex;
+            // this.queryParams.pageIndex = res.data.pageIndex;
           }
       })
     },

+ 2 - 2
src/views/service/Interface/components/Latency.vue

@@ -49,8 +49,8 @@ export default {
       appsItem:{},
       option:{
         title: {
-          text: '延迟分位图',
-          subtext: 'ms',
+          text: '延迟分位图(ms)',
+          // subtext: 'ms',
           textStyle:{
             fontSize:14
           },

+ 31 - 3
src/views/service/Interface/index.vue

@@ -4,7 +4,35 @@
       <el-card class="box-card" style="flex:1;">
         <el-tabs v-model="activeName" @tab-click="handleClick">
           <el-tab-pane label="接口映射" name="first">
-            <ServiceMap/>
+              <div style="background-color: #fff;box-sizing:border-box;padding:8px 16px 4px;min-height:288px;">
+                <el-row type="flex" justify="start" :gutter="8">
+                    <el-col :span="24"
+                    :lg="24"
+                    :md="24"
+                    :sm="24">
+                        <div style='background-color: #fff;position:relative;padding:6px;'>
+                          <Latency v-if="activeName=='first'" :percentile='percentile'/>
+                          <div class="LatencySelect">
+                            <el-radio-group size="mini" v-model="radio" @input="changePercentile" >
+                              <el-radio :label="0.5">p.50</el-radio>
+                              <el-radio :label="0.95">p.95</el-radio>
+                              <el-radio :label="0.99">p.99</el-radio>
+                            </el-radio-group>
+                          </div>
+                        </div>
+                    </el-col>
+                  
+                    <!-- <el-col :span="12"
+                    :lg="12"
+                    :md="12"
+                    :sm="24">
+                        <div style='background-color: #fff;border: 1px solid #24292e1f;border-radius: 3px;padding:6px'>
+                          <Service/>
+                        </div>
+                    </el-col> -->
+                </el-row>
+              </div>
+              <InterfaceMap/>
           </el-tab-pane>
           <el-tab-pane label="分析视图" name="second">
               <div style="background-color: rgb(244, 245, 245);box-sizing:border-box;padding:8px 16px 4px;min-height:288px;">
@@ -95,7 +123,7 @@ require("codemirror/addon/hint/sql-hint");
 import Latency from "./components/Latency.vue"
 import TreeViews from "./components/TreeViews.vue"
 import RectTree from "./components/RectTree.vue"
-import ServiceMap from "./components/ServiceMap.vue"
+import InterfaceMap from "./components/InterfaceMap.vue"
 import { serviceGraphSide} from '@/api/topo'
 import {otAppDashboard,addDashBoard} from "@/api/dashboard"
 import { listOtPlugins, singleOtPlugin,addOtPlugins,updateOtPlugins,delOtPlugins } from "@/api/plugin";
@@ -110,7 +138,7 @@ export default {
   components:{
     Latency,
     TreeViews,
-    ServiceMap,
+    InterfaceMap,
     RectTree
   },
   computed: {

+ 342 - 132
src/views/service/service/components/ServiceMap.vue

@@ -1,6 +1,6 @@
 <template>
     <div style="padding:16px;">
-        <el-form ref="queryForm" :model="queryParams" :inline="true" label-width="68px" @submit.native.prevent>
+        <!-- <el-form ref="queryForm" :model="queryParams" :inline="true" label-width="68px" @submit.native.prevent>
           <el-form-item label="" prop="url">
               <el-input
                 v-model="queryParams.url"
@@ -10,45 +10,55 @@
                 @keyup.enter.native="handleQuery"
               />
             </el-form-item>
-        </el-form>
+        </el-form> -->
 
-        <el-row :gutter="10" class="mb8">
+        <!-- <el-row :gutter="10" class="mb8">
           <el-col :span="1.5">
             <el-button
-              v-permisaction="['disposition:index:add']"
               type="primary"
               icon="el-icon-plus"
               size="mini"
               @click="handleAdd"
             >新增</el-button>
           </el-col>
-        </el-row>
+        </el-row> -->
 
         <div>
-          <!-- v-el-table-infinite-scroll="loadMore"  :height="tableHeight"-->
+          <!-- <el-table
+            v-loading="loading"
+            :key="isUpdate"
+            :data="serveceMapList"
+            :default-sort = "{prop: 'total', order: 'descending'}"
+            @row-click="handleRowClick" 
+          > -->
           <el-table
             v-loading="loading"
+            :key="isUpdate"
             :data="serveceMapList"
             :default-sort = "{prop: 'total', order: 'descending'}"
             @row-click="handleRowClick" 
           >
-            <el-table-column header-align="left" label="接口名" prop="name" align="left" :show-overflow-tooltip="true"/>
-            <el-table-column header-align="left" label="URL组" prop="url" align="left" :show-overflow-tooltip="true">
+            <el-table-column header-align="left" label="服务名" prop="name" align="left" :show-overflow-tooltip="true"/>
+            <el-table-column header-align="left" label="起始服务" prop="service_name" align="left" :show-overflow-tooltip="true">
               <template slot-scope="scope">
-                <!-- <span style="cursor:pointer" @click="toogleExpand(row,$index)">{{scope.row.url}}</span> -->
-                <span>{{scope.row.url}}</span>
+                <span>{{scope.row.service_name}}</span>
               </template>
             </el-table-column>
+            <!-- <el-table-column header-align="left" label="SpanName" prop="span_name" align="left" :show-overflow-tooltip="true">
+              <template slot-scope="scope">
+                <span>{{scope.row.span_name}}</span>
+              </template>
+            </el-table-column> -->
             <el-table-column header-align="center" label="rpm" sortable prop="rpm" align="center" :show-overflow-tooltip="true">
               <template slot-scope="scope">
-                <!-- <span>{{ Number(scope.row.rpm).toFixed(2)}}</span> -->
-                <el-tag>{{ Number(scope.row.rpm).toFixed(2)}}</el-tag>
+
+                <el-tag>{{ scope.row.rpm == undefined?0:Number(scope.row.rpm).toFixed(2)}}</el-tag>
               </template>
             </el-table-column>
             <el-table-column header-align="center" label="count" sortable prop="total" align="center">
               <template slot-scope="scope">
                 <!-- <span>{{ Number(scope.row.rpm).toFixed(2)}}</span> -->
-                <el-tag>{{ Number(scope.row.total).toFixed(2)}}</el-tag>
+                <el-tag>{{ scope.row.total== undefined?0:Number(scope.row.total).toFixed(2)}}</el-tag>
               </template>
             </el-table-column>
             <el-table-column header-align="center" label="errRate" sortable prop="error_rate" align="center">
@@ -77,7 +87,7 @@
                   <div :id="`tiger-five-trend-index` + scope.$index" class="tiger-trend-charts"></div>
                 </template>
             </el-table-column>
-            <el-table-column
+            <!-- <el-table-column
               label="操作"
               align="center"
               class-name="small-padding fixed-width"
@@ -85,7 +95,6 @@
             >
               <template slot-scope="scope">
                 <el-button
-                  v-permisaction="['disposition:index:edit']"
                   size="mini"
                   type="text"
                   icon="el-icon-edit"
@@ -113,7 +122,7 @@
                   @click.native.stop="handleDelete(scope.row)"
                 >删除</el-button>
               </template>
-            </el-table-column>
+            </el-table-column> -->
           </el-table>
         </div>
         <div class="more" v-if="serveceMapList.length<tableCount" @click="loadMore">加载更多</div>
@@ -123,7 +132,7 @@
           :total="total"
           :page.sync="childQueryParams.pageIndex"
           :limit.sync="childQueryParams.pageSize"
-          @pagination="handelgetUrlMappingRange"
+          @pagination="handelgetBizDetail"
         /> -->
 
         <!-- 添加或修改应用配置对话框 -->
@@ -177,92 +186,152 @@
         <el-drawer
             :visible.sync="drawer"
             direction="rtl"
-            size="55%"
+            size="calc( 100vw - 210px)"
             @close="drawerClose"
           >
-          <div style="margin-bottom:16px">
+          <div style="margin-bottom:16px;margin-top:-32px;">
+            <div class="flexWrap">
+              <div class="flex-left">
+                <!-- <Topo /> -->
+                <Topo v-if='drawer' :graphData='graphData' topoId='container' v-on:changeState="clickRowHandleNode" ref='topo'/>
+              </div>
+              <div class="flex-right">
+                  <div id="scaleMain" style="width:100%;min-width:500px;height:180px;margin-bottom:24px"></div>
 
-            <div id="scaleMain" style="width:100%;min-width:500px;height:180px;margin-bottom:24px"></div>
+                  <el-table
+                    v-loading="tableLoading"
+                    :data="rowData"
+                  >
+                    <el-table-column header-align="center" label="TraceID" prop="trace_id" align="center" width="240">
+                    <template slot-scope="scope">
+                      <span @click="goto(scope.row)">{{scope.row.trace_id}}</span>
+                    </template>
+                    </el-table-column>
+                    <el-table-column header-align="center" label="ServiceName" prop="service_name" align="center" :show-overflow-tooltip="true" />
+                    <!-- <el-table-column header-align="center" label="SpanName" prop="span_name" align="center" :show-overflow-tooltip="true" />
+                    <el-table-column header-align="center" label="SpanKind" prop="span_kind" align="center" width="100"/> -->
+                    <el-table-column header-align="center" label="Target" prop="target" align="center" :show-overflow-tooltip="true" />
+                    <el-table-column header-align="center" label="Method" prop="method" align="center">
+                      <template slot-scope="scope">
+                          <el-tag type="info">{{ scope.row.method }}</el-tag>
+                      </template>
+                    </el-table-column>
+                    <el-table-column header-align="center" label="StatusCode" prop="status_code" align="center">
+                    <template slot-scope="scope">
+                      <span>
+                        <span v-if="scope.row.status_code<400"><i class="green_small"></i>{{scope.row.status_code}}</span>
+                        <span v-else><i class="red_small"></i>{{scope.row.status_code}}</span>
+                      </span>
+                    </template>
+                    </el-table-column>
+                    <el-table-column header-align="center" label="Duration(ms)" prop="duration" align="center">
+                      <template slot-scope="scope">
+                          <el-tag v-if="scope.row.duration>=2000" type="danger">{{ scope.row.duration }}</el-tag>
+                          <el-tag v-if="scope.row.duration<2000" type="info">{{ scope.row.duration }}</el-tag>
+                      </template>
+                    </el-table-column>
+                    <!-- <el-table-column header-align="center" label="max(ms)" sortable="custom" prop="duration_stats" align="center" width="100">
+                      <template slot-scope="scope">
+                        <span>{{ Number(scope.row.max).toFixed(2)}}</span>
+                      </template>
+                    </el-table-column>
+                    <el-table-column header-align="center" label="avg(ms)" sortable="custom" prop="duration_stats" align="center" width="100">
+                      <template slot-scope="scope">
+                        <span>{{ Number(scope.row.avg).toFixed(2)}}</span>
+                      </template>
+                    </el-table-column> -->
+                  </el-table>
+                  <pagination
+                    v-show="total>0"
+                    :total="total"
+                    :page.sync="childQueryParams.pageIndex"
+                    :limit.sync="childQueryParams.pageSize"
+                    @pagination="handelgetBizDetail"
+                  />
+              </div>
+            </div>
 
-            <el-table
-              v-loading="tableLoading"
-              :data="rowData"
-            >
-              <el-table-column header-align="center" label="TraceID" prop="trace_id" align="center" width="240">
-              <template slot-scope="scope">
-                <span @click="goto(scope.row)">{{scope.row.trace_id}}</span>
-              </template>
-              </el-table-column>
-              <el-table-column header-align="center" label="ServiceName" prop="service_name" align="center" :show-overflow-tooltip="true" />
-              <!-- <el-table-column header-align="center" label="SpanName" prop="span_name" align="center" :show-overflow-tooltip="true" />
-              <el-table-column header-align="center" label="SpanKind" prop="span_kind" align="center" width="100"/> -->
-              <el-table-column header-align="center" label="Target" prop="target" align="center" :show-overflow-tooltip="true" />
-              <el-table-column header-align="center" label="Method" prop="method" align="center">
-                <template slot-scope="scope">
-                    <el-tag type="info">{{ scope.row.method }}</el-tag>
-                </template>
-              </el-table-column>
-              <el-table-column header-align="center" label="StatusCode" prop="status_code" align="center">
-              <template slot-scope="scope">
-                <span>
-                  <span v-if="scope.row.status_code<400"><i class="green_small"></i>{{scope.row.status_code}}</span>
-                  <span v-else><i class="red_small"></i>{{scope.row.status_code}}</span>
-                </span>
-              </template>
-              </el-table-column>
-              <el-table-column header-align="center" label="Duration(ms)" prop="duration" align="center">
-                <template slot-scope="scope">
-                    <el-tag v-if="scope.row.duration>=2000" type="danger">{{ scope.row.duration }}</el-tag>
-                    <el-tag v-if="scope.row.duration<2000" type="info">{{ scope.row.duration }}</el-tag>
-                </template>
-              </el-table-column>
-              <!-- <el-table-column header-align="center" label="max(ms)" sortable="custom" prop="duration_stats" align="center" width="100">
-                <template slot-scope="scope">
-                  <span>{{ Number(scope.row.max).toFixed(2)}}</span>
-                </template>
-              </el-table-column>
-              <el-table-column header-align="center" label="avg(ms)" sortable="custom" prop="duration_stats" align="center" width="100">
-                <template slot-scope="scope">
-                  <span>{{ Number(scope.row.avg).toFixed(2)}}</span>
-                </template>
-              </el-table-column> -->
-            </el-table>
-            <pagination
-              v-show="total>0"
-              :total="total"
-              :page.sync="childQueryParams.pageIndex"
-              :limit.sync="childQueryParams.pageSize"
-              @pagination="handelgetUrlMappingRange"
-            />
+            
           </div>
         </el-drawer>
+
+        <el-drawer
+            :visible.sync="drawerDetail"
+            direction="rtl"
+            size="55%"
+            @close="drawerCloseDetail"
+            v-if='JSON.stringify(detailData) != "{}"'
+          >
+            <el-collapse v-model="activeNames">
+              <el-collapse-item title="Attributes" name="one">
+                <ul class='ul_box' v-if='detailData.span_attributes !=null'>
+                  <li v-for='(value,key) in detailData.span_attributes' :key='key'> 
+                    <div class="ul_label">{{key}}</div>
+                    <div class="ul_value" style='color:#008080;white-space: pre-wrap;'>"{{value}}"</div>
+                  </li>
+                </ul>
+              </el-collapse-item>
+              <el-collapse-item title="Resource" name="tow">
+                <ul class='ul_box' v-if='detailData.resource_attributes !=null'>
+                  <li v-for='(value,key) in detailData.resource_attributes' :key='key'> 
+                    <div class="ul_label">{{key}}</div>
+                    <div class="ul_value" style='color:#008080;white-space: pre-wrap;'>"{{value}}"</div>
+                  </li>
+                </ul>
+              </el-collapse-item>
+              <el-collapse-item v-if='detailData.events_timestamp.length>0 && detailData.events_timestamp!=null' :title="'Events'+'('+ detailData.events_timestamp.length +')'" name="three">
+                <div class='events_box'>
+                  <el-collapse :value="activeIn">
+                    <el-collapse-item v-for='(item,index) in detailData.events_timestamp' :key='index' :title="item" :name="index">
+                      <ul class='ul_box'>
+                        <li>
+                          <div class="ul_label">message</div>
+                          <div class="ul_value" style='color:#008080;white-space: pre-wrap;'>"{{detailData.events_name[index]}}"</div>
+                        </li>
+                        <li v-for='(value,key) in detailData.events_attributes[index]' :key='key'>
+                          <div class="ul_label">{{key}}</div>
+                          <div class="ul_value" style='color:#008080;white-space: pre-wrap;'>"{{value}}"</div>
+                        </li>
+                      </ul>
+                    </el-collapse-item>
+                  </el-collapse>
+                </div>
+              </el-collapse-item>
+            </el-collapse>
+        </el-drawer>
     </div>
 </template>
 
 <script>
-import { listUrlMapping, addUrlMapping, getUrlMapping, updateUrlMapping, delUrlMapping, favor,getUrlMappingRange } from '@/api/mapping'
+import { listUrlMapping, addUrlMapping, getUrlMapping, updateUrlMapping, delUrlMapping, favor,getUrlMappingRange,getBizDetail,listBizGraph,listBizGraphStats,updateBiz,delBiz,favorBiz } from '@/api/mapping'
 import { formatJson } from '@/utils'
 import storage from '@/utils/storage'
 // import bus from '@/utils/bus'
+import {listService,listServiceStats,serviceSpans} from "@/api/service"
 
 import { getToken } from '@/utils/auth'
 // import echarts from 'echarts'
 import resize from './mixins/resize'
 import moment from 'moment'
 // import elTableInfiniteScroll from 'el-table-infinite-scroll';
+import Topo from './TopoNew1'
 export default {
   name: 'ServiceMap',
   mixins: [resize],
   components: {
-
+    Topo
   },
   // directives: {
   //   'el-table-infinite-scroll': elTableInfiniteScroll
   // },
   data() {
     return {
+      isUpdate:false,
+      isflag:false,
+      tableflag:false,
       drawer:false,
       detailData:{},
+      drawerDetail:false,
       tableLoading:false,
       // 表格高度
       tableHeight:"",
@@ -293,13 +362,11 @@ export default {
       queryParams: {
         // start_time:Math.round((new Date().getTime())/1000 - (5*60)),
         // end_time:Math.round(new Date().getTime()/1000),
-        start_time:0,
-        end_time:0,
-        app_id:undefined,
-        favor:'',
-        url:'',
-        pageIndex: 1,
-        pageSize: 50,
+        app_id:'',
+        start_time:'',
+        end_time:'',
+        pageIndex:1,
+        pageSize:50,
       },
       // 表单参数
       form: {
@@ -323,15 +390,25 @@ export default {
         // end_time:Math.round(new Date().getTime()/1000),
         start_time:0,
         end_time:0,
-        id:0,
-        app_id:0,
-        kind:'',
-        only_error:0,
+        biz_id:1,
         pageIndex: 1,
         pageSize: 10,
       },
       rowData:[],
-      serviceMapTimer:null
+      serviceMapTimer:null,
+      BizStatsQuery:{
+        id:0,
+        start_time:'',
+        end_time:'',
+      },
+      tempList:[],
+      graphData:{},
+      graphStatsQuery:{
+        biz_node_id:0,// 仅支持传递单个节点,多个节点需要并发请求分别调用
+        end_time:1702972800,
+        start_time:1702969200,
+      },
+      graphObj:[]
     }
   },
    watch: {
@@ -340,6 +417,10 @@ export default {
             if(newValue){
               this.queryParams.start_time = newValue.startTime;
               this.queryParams.end_time = newValue.endTime
+              this.BizStatsQuery.start_time= newValue.start_time;
+              this.BizStatsQuery.end_time= newValue.end_time;
+              this.graphStatsQuery.start_time= newValue.start_time;
+              this.graphStatsQuery.end_time= newValue.end_time;
               this.childQueryParams.start_time = newValue.startTime;
               this.childQueryParams.end_time = newValue.endTime
               this.queryParams.pageIndex = 1
@@ -359,28 +440,56 @@ export default {
         // immediate: true,
         deep: true
     },
+    serveceMapList:{
+      handler(newVal,oldVal){
+        if(newVal){
+          this.serveceMapList = newVal;
+          this.tableflag = true;
+        }
+      },
+      // immediate: true,
+      deep:true
+    }
   },
   beforeDestroy() {
     clearInterval(this.serviceMapTimer);
   },
-  created() {
-    // this.queryParams.start_time = this.$store.getters.globalTimes.startTime;
-    // this.queryParams.end_time = this.$store.getters.globalTimes.endTime
-    // this.childQueryParams.start_time = this.$store.getters.globalTimes.startTime;
-    // this.childQueryParams.end_time = this.$store.getters.globalTimes.endTime
-    let windowHeight =document.documentElement.clientHeight || document.body.clientHeight;
-      // 动态计算表格的高度,200为屏幕内除了表格以外其他元素的高度,依实际情况而定
-    this.tableHeight = windowHeight - 200 + "px";
-    this.appsItem=storage.get('appsItem');
-     if(this.appsItem.id!=''||this.appsItem.id!=undefined){
-      this.queryParams.app_id=this.appsItem.id;
-      this.childQueryParams.app_id = this.appsItem.id;
+  // created() {
+  //   let windowHeight =document.documentElement.clientHeight || document.body.clientHeight;
+  //     // 动态计算表格的高度,200为屏幕内除了表格以外其他元素的高度,依实际情况而定
+  //   this.tableHeight = windowHeight - 200 + "px";
+  //   this.appsItem=storage.get('appsItem');
+  //    if(this.appsItem.id!=''||this.appsItem.id!=undefined){
+  //     this.queryParams.app_id=this.appsItem.id;
+  //     this.childQueryParams.app_id = this.appsItem.id;
+  //     this.getList()
+  //   }
+  // },
+   created(){ 
+    this.$store.commit('time/setTimeFlag',false)
+
+     this.appItem=storage.get('appsItem');
+    if(JSON.stringify(this.appItem) !="{}"){
+      this.queryParams.app_id = this.appItem.id;
+      this.queryParams.start_time = this.appItem.start_time;
+      this.queryParams.end_time = this.appItem.end_time;
+      this.BizStatsQuery.start_time= this.appItem.start_time;
+      this.BizStatsQuery.end_time= this.appItem.end_time;
+      this.childQueryParams.start_time = this.appItem.start_time;
+      this.childQueryParams.end_time = this.appItem.end_time;
       this.getList()
+      this.$forceUpdate();
     }
+    // this.columnChange();
   },
   mounted(){
+    this.$forceUpdate();
   },
   methods: {
+    // clickFull() {
+    //     this.Visible=true;
+    //     this.$refs['topo'].initGraph();
+    // },
     Refresh(timeOut){
       this.serviceMapTimer = setInterval(()=>{
         this.getList();
@@ -399,37 +508,99 @@ export default {
     drawerClose(){
       this.drawer = false;
     },
+    drawerCloseDetail(){
+      this.drawerDetail = false;
+    },
     toogleExpand(row, column, event){
       console.log(row,'点击展开行');
       this.drawer=true;
       this.childQueryParams.id = row.id;
-      this.handelgetUrlMappingRange();
+      this.handelgetBizDetail();
     },
     handleRowClick(row, column, event){
       console.log(row,'点击行');
-      this.drawer=true;
-      this.$nextTick(() =>{ 
-        this.drawEchartsScale(row);
-       }) 
+      console.log(column,'column')
+      this.childQueryParams.biz_id = row.id;
+      this.handelgetBizDetail();
+      this.getListBizGraph(row.id)
+
+      
+     
       setTimeout(()=>{
-        
-        // this.childQueryParams.id = row.id;
-        this.childQueryParams.kind = row.kind;
-        this.handelgetUrlMappingRange();
-      },0)
+        // this.childQueryParams.biz_id = row.id;
+        // this.handelgetBizDetail();
+        // this.getListBizGraph(row.id)
+        this.drawer=true;
+        this.$nextTick(() =>{ 
+          this.drawEchartsScale(row);
+        }) 
+      },300)
     },
-    handelgetUrlMappingRange(){
+    handelgetBizDetail(){
       this.tableLoading = true
-      console.log(this.childQueryParams,'this.childQueryParams')
-      getUrlMappingRange(this.childQueryParams).then(res => {
+      getBizDetail(this.childQueryParams).then(res => {
           if(res.code == 200){
             this.tableLoading = false;
-            console.log(res.data.list,'业务映射获取行的数据')
             this.rowData= res.data.list;
             this.total = res.data.count;
           }
       })
     },
+    getListBizGraph(id){
+      listBizGraph({biz_id:id}).then((res)=>{
+        console.log(res,'决策树数据')
+        if(res.code == 200){
+          let arr = res.data
+          if(arr.length>0){
+            let List = this.handelListBizData(arr)
+            console.log(List,'处理后的数据')
+            this.graphData =List[0];
+            console.log(this.graphData,'graphData=======')
+          }
+        }
+      })
+    },
+    handelListBizData(data){
+      data.forEach((v,k)=>{
+        v.collapsed = false;
+        v.id = String(v.id);
+        v.name = v.name;
+        v.label = v.stats.duration!=undefined?v.stats.duration.toFixed(2):0;
+        v.currency = 'ms';
+        v.rate = v.stats.success_rate;
+        v.status = 'B'
+        v.variableValue = v.stats.success_rate;
+        if (v.children != undefined && v.children.length > 0) {
+          v.children = this.handelListBizData(v.children)
+        }
+      })
+      return data;
+    },
+    handleData(data) {
+      data.forEach((v, k) => {
+      // let string = key === '' ? k + 1 : key + '.' + (k + 1)
+
+      // v.span_name += '---' + string
+      // v.id = v.span_name;
+
+      v.id = v.biz_id;
+
+      v.collapsed = false;
+      v.name = v.name;
+      // v.label = (v.duration).toFixed(2);
+      v.label = v.service_name;
+      v.currency='ms';
+      v.rate = v.duration_persent;
+      v.status = (v.status_code == 'STATUS_CODE_ERROR'||v.events_timestamp.length>0||v.http_code>399)?'R':(v.duration>500)?'Y':'G';
+      v.variableValue = v.duration_persent;
+      // v.status_code = 'UNSET'
+      
+      if (v.children != undefined && v.children.length > 0) {
+          v.children = this.handleData(v.children)
+        }
+      })
+      return data
+    },
     // 根据行的id判断
     getRowKeys(row) {
       return row.id;
@@ -437,6 +608,11 @@ export default {
     clickRowHandle(row, column, event) {
     //  alert('a')
     },
+    clickRowHandleNode(item){
+      console.log(item,'点击节点')
+      this.detailData = item;
+      this.drawerDetail=true;
+    },
     handleSortChang(column, prop, order) {
       prop = column.prop
       order = column.order
@@ -474,14 +650,33 @@ export default {
     },
     getList() {
       this.loading = true
-      listUrlMapping(this.queryParams).then(res => {
+      const _this = this;
+      listService(this.queryParams).then(res => {
+          console.log(res.data.list,'服务列表')
           if(res.code == 200){
-            console.log(res.data.list,'业务映射')
-            this.loading = false;
-            this.serveceMapList= this.serveceMapList.concat(res.data.list);
-            console.log(this.serveceMapList,'this.serveceMapList 所有接口映射内容')
+            _this.serveceMapList= _this.serveceMapList.concat(res.data.list);
             this.tableCount = res.data.count;
             this.queryParams.pageIndex = res.data.pageIndex;
+            this.loading = false;
+
+            // this.tempList = this.tempList.concat(res.data.list);
+            if(_this.serveceMapList.length>0){
+              for(let i=0;i<_this.serveceMapList.length;i++){
+                this.BizStatsQuery.id = _this.serveceMapList[i].id
+                listServiceStats(this.BizStatsQuery).then(resq=>{
+                  console.log(resq,'服务解析列表=======')
+                  if(resq.data.id != undefined){
+                    if(_this.serveceMapList[i].id == resq.data.id){
+                      _this.serveceMapList[i] = Object.assign({},_this.serveceMapList[i], resq.data);
+                      _this.isUpdate = !_this.isUpdate;
+                    }
+                  }
+                })
+              }
+            }
+            this.$nextTick(()=>{
+              this.$forceUpdate();
+            })
           }
       })
     },
@@ -518,6 +713,7 @@ export default {
     handleQuery() {
       this.queryParams.pageIndex = 1
       this.serveceMapList=[];
+      this.tempList=[];
       this.getList()
       // this.getList()
       // if(this.queryParams.url != ''){
@@ -562,7 +758,6 @@ export default {
     },
     /** 修改按钮操作 */
     handleUpdate(row) {
-      console.log(row,'-------')
       this.reset()
       const id = row.id || this.ids
       if(row.id != 0){
@@ -570,7 +765,7 @@ export default {
           console.log(response.data,'修改URL组')
           this.form = response.data
           this.form.id = row.id
-          this.title = '修改URL组'
+          this.title = '修改业务名'
           this.isEdit = true
           this.open = true
         })
@@ -587,12 +782,13 @@ export default {
       this.$refs['form'].validate(valid => {
         if (valid) {
           if (this.form.id !== undefined || this.form.id !=0) {
-            updateUrlMapping(this.form, this.form.id).then(response => {
+            updateBiz(this.form, this.form.id).then(response => {
               if (response.code === 200) {
                 this.msgSuccess(response.msg)
                 this.open = false
                 this.queryParams.pageIndex =1;
                 this.serveceMapList=[];
+                this.tempList=[];
                 this.getList()
               } else {
                 this.msgError(response.msg)
@@ -605,6 +801,7 @@ export default {
                 this.open = false
                 this.queryParams.pageIndex =1;
                 this.serveceMapList=[];
+                this.tempList=[];
                 this.getList()
               } else {
                 this.msgError(response.msg)
@@ -623,10 +820,11 @@ export default {
         cancelButtonText: '取消',
         type: 'warning'
       }).then(function() {
-        return delUrlMapping(id)
+        return delBiz(id)
       }).then((response) => {
         this.queryParams.pageIndex =1;
         this.serveceMapList=[];
+        this.tempList=[];
         this.msgSuccess(response.msg);
         this.getList()
       }).catch(function() {})
@@ -638,11 +836,12 @@ export default {
           row.favor = '1';
         }
 
-      favor({favor:row.favor},row.id).then(res=>{
+      favorBiz({favor:row.favor},row.id).then(res=>{
           if(res.code = 200){
             this.msgSuccess(res.msg);
             this.queryParams.pageIndex =1;
             this.serveceMapList=[];
+             this.tempList=[];
             this.getList()
           }
       })
@@ -687,7 +886,7 @@ export default {
         })
       })
     },
-     drawEchartsp5(row, index) {
+    drawEchartsp5(row, index) {
       let option = {
         tooltip: {
           trigger: 'axis',
@@ -705,7 +904,7 @@ export default {
           type: 'category',
           boundaryGap: false,
           // data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
-          data: row.duration_stats.time,
+          data: row.quantiles.time,
           show:false
         },
         yAxis: {
@@ -720,7 +919,7 @@ export default {
             symbol: 'none',
             // // data: [120, 132, 101, 134, 90, 230, 210]
             // data: Number(row.duration_stats.p50).toFixed(2)
-            data:row.duration_stats.p50
+            data:row.quantiles.p50
           },
           {
             name: 'P.95',
@@ -729,7 +928,7 @@ export default {
             symbol: 'none',
             // data: [320, 332, 301, 334, 390, 330, 320]
             // data: Number(row.duration_stats.p90).toFixed(2)
-            data:row.duration_stats.p90
+            data:row.quantiles.p90
           },
           {
             name: 'P.99',
@@ -738,7 +937,7 @@ export default {
             symbol: 'none',
             // data: [820, 932, 901, 934, 1290, 1330, 1320]
             // data: Number(row.duration_stats.p99).toFixed(2)
-            data:row.duration_stats.p99
+            data:row.quantiles.p99
           }
         ]
       };
@@ -787,15 +986,16 @@ export default {
           }
         },
         grid: {
-          left: '4%',
+          top:'2%',
+          left: '3%',
           right: '4%',
-          bottom: '3%',
+          bottom: '1%',
           containLabel: true
         },
         xAxis: {
           type: 'category',
           boundaryGap: false,
-          data: row.duration_stats.time,
+          data: row.quantiles.time,
           // show:true
         },
         yAxis: {
@@ -822,7 +1022,7 @@ export default {
             stack: 'Total',
             symbol: 'none',
             // symbol: 'emptyCircle',//拐点
-            data:row.duration_stats.p50
+            data:row.quantiles.p50
           },
           {
             name: 'P.95',
@@ -830,7 +1030,7 @@ export default {
             stack: 'Total',
             symbol: 'none',//拐点
             // symbol: 'emptyCircle',//拐点
-            data:row.duration_stats.p90
+            data:row.quantiles.p90
           },
           {
             name: 'P.99',
@@ -838,7 +1038,7 @@ export default {
             stack: 'Total',
             symbol: 'none',//拐点
             // symbol: 'emptyCircle',//拐点
-            data:row.duration_stats.p99
+            data:row.quantiles.p99
           }
         ]
       };
@@ -867,7 +1067,7 @@ export default {
         
         _this.childQueryParams.start_time = timestamp
         _this.childQueryParams.end_time =timestamp
-        _this.handelgetUrlMappingRange();
+        _this.handelgetBizDetail();
       })
     },
     drawEchartsp99() {
@@ -978,4 +1178,14 @@ export default {
     background:#F56C6C;
     margin-right:8px;
   }
+  .flexWrap{
+    display:flex;
+    justify-content: space-between;
+  }
+  .flex-left{
+    width:60%;
+  }
+  .flex-right{
+    width:39.99
+  }
 </style>

+ 166 - 127
src/views/business-analysis/analysis/components/TopoNew.vue → src/views/service/service/components/TopoNew1.vue

@@ -1,12 +1,20 @@
 <template>
   <div style="position:relative;">
-    <div class="container" id="container">
+    <!-- <div class="container" id="container" ref="container">
+    </div> -->
+    <div class="container" :id="topoId" ref="container">
     </div>
     <!-- <div class="full">
       <span class="title_href" id='fullscreen_button'>
-        <i class="el-icon-full-screen"></i>
+        <svg-icon :icon-class="isFull?'exit-fullscreen':'fullscreen'" @click.native.prevent="clickFull" />
       </span>
     </div> -->
+    <!-- <el-dialog
+      :visible.sync="Visible"
+      :fullscreen='true'
+      center>
+      <div ref="container1" id="container1" style="width:100%;height:100vh"></div>
+    </el-dialog> -->
   </div>
 </template>
 
@@ -28,56 +36,7 @@ insertCss(`
     border-radius = 4px;
   }
 `);
-export default {
-  props: {
-    // 数据
-    graphData: {
-      // type: Object,
-      // default () {
-      //   return {}
-      // }
-      // style: {
-      //   active: {
-      //     fill: "rgb(247, 250, 255)",
-      //     lineWidth: 2,
-      //     shadowBlur: 10,
-      //     shadowColor:"rgb(95, 149, 255)",
-      //     stroke: "rgb(95, 149, 255)",
-      //   }, 
-      //   selected: {
-
-      //   },
-      //    highlight: {
-      //     fill: "rgb(223, 234, 255)",
-      //     lineWidth: 2,
-      //     stroke: "#4572d9",
-      //     textShape: {
-      //       fontWeight: 500
-      //       }
-      //    }, 
-      //    inactive: {
-      //     fill: "rgb(247, 250, 255)",
-      //     lineWidth: 1,
-      //     stroke: "rgb(191, 213, 255)"
-      //    }, 
-      //    disable: {
-      //     fill: "rgb(250, 250, 250)",
-      //     lineWidth: 1,
-      //     stroke: "rgb(224, 224, 224)"
-      //     }
-      // }
-    },
-  },
-  data(){
-    return {
 
-    }
-  },
-  created(){
-    console.log(this.graphData,'topoNew组件接受到的父组件数据')
-  },
-  mounted(){
-    // mocked data
     const mockData = {
       id: 'g1',
       name: 'LOST ROOT SPAN',
@@ -281,7 +240,6 @@ export default {
       ],
     };
 
-    console.log(mockData,'mockData数据的特征')
 
     const DataGrafa =  {
             id:'1',
@@ -344,12 +302,10 @@ export default {
       G: '#5BD8A6',
       DI: '#A7A7A7',
     };
-    const  obj = this.graphData
-    console.log(obj,'----')
     //  组件props
     let props = {
       // data: this.graphData,  
-      data:obj,
+      // data:obj,
       // data:mockData,
       // data:DataGrafa,
       config: {
@@ -360,43 +316,93 @@ export default {
       },
     };
 
-    const container = document.getElementById('container');
-    const width = container.scrollWidth;
-    const height = container.scrollHeight || 500;
-
-
-    // 默认配置
-    const defaultConfig = {
-      width,
-      height,
-      modes: {
-        default: ['zoom-canvas', 'drag-canvas'],
-      },
-      fitView: true,
-      animate: true,
-      defaultNode: {
-        type: 'flow-rect',
-      },
-      defaultEdge: {
-        type: 'cubic-horizontal',
-        style: {
-          stroke: '#CED4D9',
-        },
-      },
-      layout: {
-        type: 'indented',
-        direction: 'LR',
-        dropCap: false,
-        indent: 300,
-        getHeight: () => {
-          return 60;
-        },
-      },
-    };
+export default {
+  props: {
+    // 数据
+    graphData: {
+      type: Object,
+      default () {
+        return {}
+      }
+    },
+    topoId:{
+      type:String,
+      default(){
+        return ''
+      }
+    }
+  },
+  data(){
+    return {
+      isFull: false,
+      Visible:false,
+    }
+  },
+  created(){
+    console.log(this.graphData,'topoNew组件接受到的父组件数据')
+  },
+  mounted(){
+   this.$nextTick(() => {
+    // this.initGraph(this.graphData,'container');
+    this.initGraph(this.graphData,this.topoId)
+   });
+  },
+  destroy() {
+   if (screenfull.isEnabled) {
+     screenfull.off('change', this.change)
+   }
+  },
+  methods:{
+    init() {
+      if (screenfull.isEnabled) {
+        screenfull.on('change', this.change)		// 开启监听
+      }
+    },
+    change() {
+      this.isFull = screenfull.isFullscreen  // 更新全屏状态
+    },
+    clickFull() {
+        this.Visible=true;
+        this.$nextTick(() => {
+          this.initGraph(this.graphData,'container1');
+        });
+    },
+    initGraph(data,id){
+          let graph = null;
+          const container = document.getElementById(id);
+          // const container = this.$refs['container'];
+          const width = container.scrollWidth;
+          const height = container.scrollHeight || 500;
+         // 默认配置
+          const defaultConfig = {
+            width,
+            height,
+            modes: {
+              default: ['zoom-canvas', 'drag-canvas'],
+            },
+            fitView: true,
+            animate: true,
+            defaultNode: {
+              type: 'flow-rect',
+            },
+            defaultEdge: {
+              type: 'cubic-horizontal',
+              style: {
+                stroke: '#CED4D9',
+              },
+            },
+            layout: {
+              type: 'indented',
+              direction: 'LR',
+              dropCap: false,
+              indent: 300,
+              getHeight: () => {
+                return 60;
+              },
+            },
+          };
 
-    // 自定义节点、边
-    const registerFn = () => {
-      /**
+       /**
        * 自定义节点
        */
       G6.registerNode(
@@ -458,7 +464,6 @@ export default {
               },
             });
 
-            console.log(rect,'a--------')
 
             const rectBBox = rect.getBBox();
 
@@ -510,8 +515,8 @@ export default {
                 ...textConfig,
                 x: rectBBox.maxX - 8,
                 y: rectBBox.maxY - 12,
-                // text: `${((variableValue || 0) * 100).toFixed(2)}%`,
-                text:variableValue,
+                text: `${((variableValue || 0) * 100).toFixed(2)}%`,
+                // text:variableValue,
                 fontSize: 12,
                 textAlign: 'right',
                 fill: colors[status],
@@ -608,7 +613,6 @@ export default {
           },
           update(cfg, item) {
             const { level, status, name } = cfg;
-            console.log(cfg,'更新中的cfg')
             const group = item.getContainer();
             let mask = group.find(ele => ele.get('name') === 'mask-shape');
             let maskLabel = group.find(ele => ele.get('name') === 'mask-label-shape');
@@ -656,7 +660,6 @@ export default {
               return mask;
             } else {
               group.get('children').forEach(child => {
-                console.log(child,child.get('name'),'---------')
                 if (child.get('name')?.includes('collapse')) return;
                 child.show();
               })
@@ -737,14 +740,8 @@ export default {
         },
         'single-line',
       );
-    };
 
-    registerFn();
 
-    const { data } = props;
-    let graph = null;
-
-    const initGraph = (data) => {
       if (!data) {
         return;
       }
@@ -775,8 +772,15 @@ export default {
           return false;
         },
       });
-      graph = new G6.TreeGraph({
-        container: 'container',
+      // graph = new G6.TreeGraph({
+      //   container: 'container',
+      //   ...defaultConfig,
+      //   ...config,
+      //   plugins: [tooltip],
+      // });
+
+       graph = new G6.TreeGraph({
+        container: id,
         ...defaultConfig,
         ...config,
         plugins: [tooltip],
@@ -785,9 +789,53 @@ export default {
       if (typeof onInit === 'function') {
         onInit(graph);
       }
+      // graph.on("afterrender", () => {
+      //     // graph.zoom(0.2, { x: width / 2, y: height / 2 });
+      //      graph.zoom(0.5, { x: width / 2, y: height / 2 });
+      // });
       graph.data(data);
       graph.render();
 
+      setTimeout(() => {
+        // 1 默认展开三层节点,之后,重新渲染,item.depth > 1是三层,item.depth > 0是两层
+        G6.Util.traverseTree(data, function(item) {
+          if (item.depth > 1) {
+            //collapsed为true时默认收起
+            item.collapsed = true
+          }
+        })
+        graph.render()
+        // graph.fitCenter() // 移到图中心
+      }, 10)
+      //添加点击事件
+      graph.on("node:click", (evt) => {
+        const itemData = evt.item._cfg.model;
+        const { level, id } = itemData;
+        this.$emit("changeState", itemData);
+      });
+
+      // 双击节点进行跳转
+      // graph.on("dblclick", (evt) => {
+      //   const itemData = evt.item._cfg.model;
+      //   const { level, id } = itemData;
+      //   this.$emit("changeState", [id]);
+      //   if (level === 2) {
+      //     this.$router.push({
+      //       name: "groupDetail",
+      //       query: {
+      //         id,
+      //       },
+      //     });
+      //   } else if (level === 3) {
+      //     this.$router.push({
+      //       name: "serviceInfo",
+      //       query: {
+      //         id,
+      //       },
+      //     });
+      //   }
+      // });
+
       const handleCollapse = (e) => {
         const target = e.target;
         const id = target.get('modelId');
@@ -798,7 +846,7 @@ export default {
         graph.setItemState(item, 'collapse', nodeModel.collapsed);
       };
       graph.on('collapse-text:click', (e) => {
-        e.stopPropagation();
+         e.stopPropagation();
         e.preventDefault()
         handleCollapse(e);
       });
@@ -810,7 +858,7 @@ export default {
 
       // 监听画布缩放,缩小到一定程度,节点显示缩略样式
       let currentLevel = 1;
-      const briefZoomThreshold = Math.max(graph.getZoom(), 0.5);
+       const briefZoomThreshold = Math.max(graph.getZoom(), 0.5);
       graph.on('viewportchange', e => {
         if (e.action !== 'zoom') return;
         const currentZoom = graph.getZoom();
@@ -829,34 +877,25 @@ export default {
           })
         }
       });
-    };
-
-    initGraph(data);
-    // initGraph(this.graphData);
-
 
-
-    if (typeof window !== 'undefined'){
-      window.onresize = () => {
-        if (!graph || graph.get('destroyed')) return;
-        if (!container || !container.scrollWidth || !container.scrollHeight) return;
-        graph.changeSize(container.scrollWidth, container.scrollHeight);
-      };
+      if (typeof window !== 'undefined'){
+        window.onresize = () => {
+          if (!graph || graph.get('destroyed')) return;
+          if (!container || !container.scrollWidth || !container.scrollHeight) return;
+          graph.changeSize(container.scrollWidth, container.scrollHeight);
+        };
+      }
     }
-
-
-
-
-
   }
 }
 </script>
 
 <style lang="scss" scoped>
-// .container{
-//   width:100%;
-//   height: 800px;
-// }
+.container{
+  // width:100%;
+  // height: 800px;
+  background: #fff;
+}
 .full{
   width:32px;
   height:32px;

Dosya farkı çok büyük olduğundan ihmal edildi
+ 680 - 464
src/views/service/service/index.vue


+ 942 - 0
src/views/service/serviceDetail/index.vue

@@ -0,0 +1,942 @@
+<template>
+  <BasicLayout>
+    <template #wrapper>
+      <el-card class="box-card" style="flex:1;">
+        <div style="margin-bottom:16px;">
+          <i class="el-icon-arrow-left" style="font-size:24px;cursor: pointer;vertical-align: middle;" @click='back'></i>
+          <!-- <el-button type="primary" icon="el-icon-refresh-left" size="mini" @click='back' plain>返回</el-button> -->
+          <span style="font-size:18px;vertical-align: middle;">{{name}}({{spansQuery.service_name}})</span>
+        </div>
+        <div class="block-container" style="margin-bottom:20px">
+          <div class="row">
+            <div class="col">
+              <el-tooltip placement="bottom" effect="dark" :visible-arrow='false'>
+                <div slot="content">
+                  <i class="dot"></i>
+                  <span>{{digitsObj.Span}}</span>
+                </div>
+                <div class="border-bottom">
+                  <div class="block-box px-3 py-4">
+                    <div class="col-tit">SPANS/min</div>
+                    <div class="col-con">{{digitsObj.Span !=undefined?digitsObj.Span:0}}</div>
+                  </div>
+                </div>
+              </el-tooltip>
+            </div>
+            <div class="col">
+              <el-tooltip placement="bottom" effect="dark" :visible-arrow='false'>
+                <div slot="content">
+                  <i class="dot"></i>
+                  <span>{{digitsObj.Http}}</span>
+                </div>
+                <div class="border-bottom">
+                  <div class="block-box px-3 py-4">
+                    <div class="col-tit">HTTP/min</div>
+                    <div class="col-con">{{digitsObj.Http !=undefined?digitsObj.Http:0}}</div>
+                  </div>
+                </div>
+              </el-tooltip>
+            </div>
+            <div class="col">
+              <el-tooltip placement="bottom" effect="dark" :visible-arrow='false'>
+                <div slot="content">
+                  <i class="dot"></i>
+                  <span>{{digitsObj.Rpc}}</span>
+                </div>
+                <div class="border-bottom">
+                  <div class="block-box px-3 py-4">
+                    <div class="col-tit">RPC/min</div>
+                    <div class="col-con">{{digitsObj.Rpc !=undefined?(digitsObj.Rpc).toFixed(2):0}}</div>
+                  </div>
+                </div>
+              </el-tooltip>
+            </div>
+            <!-- <div class="col">
+              <el-tooltip placement="bottom" effect="dark" :visible-arrow='false'>
+                <div slot="content">
+                  <i class="dot"></i>
+                  <span>{{digitsObj.error_rate}}</span>
+                </div>
+                <div class="border-bottom">
+                  <div class="block-box px-3 py-4">
+                    <div class="col-tit">LOGS</div>
+                    <div class="col-con">{{(digitsObj.error_rate*100).toFixed(2)}}/min</div>
+                  </div>
+                </div>
+              </el-tooltip>
+            </div> -->
+            <div class="col">
+              <el-tooltip placement="bottom" effect="dark" :visible-arrow='false'>
+                <div slot="content">
+                  <i class="dot"></i>
+                  <span>{{digitsObj.Error!=undefined?digitsObj.Error:0}}</span>
+                </div>
+                <div class="border-bottom">
+                  <div class="block-box px-3 py-4">
+                    <div class="col-tit">HTTPERROR/min</div>
+                    <div class="col-con">{{digitsObj.Error!=undefined?(digitsObj.Error).toFixed(2):0}}</div>
+                  </div>
+                </div>
+              </el-tooltip>
+            </div>
+            <div class="col">
+              <el-tooltip placement="bottom" effect="dark" :visible-arrow='false'>
+                <div slot="content">
+                  <i class="dot"></i>
+                  <span>{{digitsObj.DB}}</span>
+                </div>
+                <div class="border-bottom">
+                  <div class="block-box px-3 py-4">
+                    <div class="col-tit">DATABASE/min</div>
+                    <div class="col-con">{{digitsObj.DB !=undefined?digitsObj.DB :0}}</div>
+                  </div>
+                </div>
+              </el-tooltip>
+            </div>
+          </div>
+        </div> 
+        <el-tabs v-model="activeName" @tab-click="handleClick">
+          <el-tab-pane label="对比分析" name="first">
+              <el-form ref="timeQuery" :model="timeQuery" :inline="true" label-width="100px" style="text-align: right;">
+                <el-form-item label="时间跨度" prop="hour_num">
+                  <el-select v-model="timeQuery.hour_num" placeholder="时间选择" clearable size="small" @keyup.enter.native="handletimeQuery" @change='changetimeQuery'>
+                    <el-option
+                      v-for="time in timeOptions"
+                      :key="time.value"
+                      :label="time.label"
+                      :value="time.value"
+                    />
+                  </el-select>
+                </el-form-item>
+              </el-form>
+              <div>
+                <h6 class="h6">活跃度</h6>
+                <div class="echartsWrap" v-if="ServiceCompareObj.current.length>0">
+                  <div id="serviceActive" style="width:100vw;height:200px"></div>
+                </div>
+                <div v-else class="noData">
+                    <div style="text-align: center;color: rgba(36, 41, 46, 0.75);font-size: 18px; width: 100%;line-height:200px">No Data</div>
+                </div>
+                <h6 class="h6">错误率分布</h6>
+                <div class="echartsWrap" v-if="errorRateObj.current.length>0">
+                  <div id="errorRate" style="width:100vw;height:200px"></div>
+                </div>
+                <div v-else class="noData">
+                    <div style="text-align: center;color: rgba(36, 41, 46, 0.75);font-size: 18px; width: 100%;line-height:200px">No Data</div>
+                </div>
+              </div>
+          </el-tab-pane>
+          <el-tab-pane label="Span列表" name="second">
+            <div style="display:flex">
+              <el-form ref="spansQuery" :model="spansQuery" :inline="true" label-width="100px">
+                <el-form-item label="自定义属性" prop="time_value">
+                  <el-input
+                    v-model="spansQuery.span_attribute_key"
+                    placeholder="请输入自定义属性"
+                    clearable
+                    size="small"
+                    @keyup.enter.native="handleSpansQuery"
+                  />
+                </el-form-item>
+                <el-form-item label="自定义属性值" prop="time_value">
+                  <el-input
+                    v-model="spansQuery.span_attribute_value"
+                    placeholder="请输入自定义属性值"
+                    clearable
+                    size="small"
+                    @keyup.enter.native="handleSpansQuery"
+                  />
+                </el-form-item>
+                <el-form-item label="Span类型" prop="span_kind">
+                  <el-select v-model="spansQuery.span_kind" placeholder="Span类型" clearable size="small" @keyup.enter.native="handleSpansQuery" @change='changeSpansQuery'>
+                    <el-option
+                      v-for="kind in spanOptions"
+                      :key="kind.value"
+                      :label="kind.label"
+                      :value="kind.value"
+                    />
+                  </el-select>
+                </el-form-item>
+                <el-form-item label="延迟大于" prop="time_value">
+                  <el-input
+                    v-model="spansQuery.min_duration"
+                    placeholder=""
+                    clearable
+                    size="small"
+                    type="number"
+                    @keyup.enter.native="handleSpansQuery"
+                    class="Dur_input"
+                  >
+                   <template slot="append">ms</template>
+                  </el-input>
+                </el-form-item>
+                <!-- <el-form-item label="最大延迟" prop="max_duration">
+                  <el-input
+                    v-model="spansQuery.max_duration"
+                    placeholder="请输入最大延迟"
+                    clearable
+                    size="small"
+                    type="number"
+                    @keyup.enter.native="handleSpansQuery"
+                  />
+                </el-form-item> -->
+                <el-form-item label="" prop="only_exception">
+                  <el-checkbox :true-label='1' :false-label='0' v-model="spansQuery.only_exception" @keyup.enter.native="handleSpansQuery" @change='changeErrorSpans'>仅异常</el-checkbox>
+                </el-form-item>
+                <el-form-item label="" prop="only_database">
+                  <!-- <el-checkbox v-model="spansQuery.only_database"></el-checkbox> -->
+                  <el-checkbox v-model="spansQuery.only_database" :true-label='1' :false-label='0' @keyup.enter.native="handleSpansQuery" @change='changeSQLSpans'>仅SQL</el-checkbox>
+                </el-form-item>
+              </el-form>
+              <div style='display:inline-block;vertical-align: middle;'>
+                <el-dropdown
+                  style="margin-left: 10px"
+                  size="mini"
+                  trigger="click"
+                  placement="bottom"
+                >
+                  <el-button type="primary" size="mini">
+                    <!-- 下拉菜单 -->
+                    <i class="el-icon-s-grid" />
+                    <i class="el-icon-arrow-down"></i>
+                  </el-button>
+                  <el-dropdown-menu slot="dropdown">
+                    <el-checkbox-group
+                      v-model="colSelect"
+                      style="text-align: left"
+                      @change="columnChange"
+                    >
+                      <el-dropdown-item
+                        v-for="(item, index) in colData"
+                        :key="index"
+                        ><el-checkbox :label="item.title">{{
+                          item.title
+                        }}</el-checkbox></el-dropdown-item
+                      >
+                    </el-checkbox-group>
+                  </el-dropdown-menu>
+                </el-dropdown>
+              </div>
+            </div>
+            <div style="padding-bottom:16px;">
+              <el-table
+                v-loading="loading"
+                :data="spansList"
+              >
+                <!-- <el-table-column type="selection" width="45" align="center" /> -->
+                <el-table-column label="TraceId" prop="trace_id" :show-overflow-tooltip="true" v-if="colData[0].istrue">
+                  <template slot-scope="scope">
+                    <span @click="goto(scope.row)">{{scope.row.trace_id}}</span>
+                  </template>
+                </el-table-column>
+                <el-table-column label="ServiceName" prop="service_name" :show-overflow-tooltip="true" v-if="colData[1].istrue"/>
+                <el-table-column label="DateTime" prop="datetime" :show-overflow-tooltip="true" v-if="colData[2].istrue"/>
+                <el-table-column label="Method" prop="method" :show-overflow-tooltip="true" v-if="colData[3].istrue"/>
+                <el-table-column label="Code" prop="code" :show-overflow-tooltip="true" v-if="colData[4].istrue"/>
+                <el-table-column label="Duration(ms)" prop='duration' :show-overflow-tooltip="true" v-if="colData[5].istrue">
+                    <template slot-scope="scope">
+                        <el-tag v-if="scope.row.duration>=2000" type="danger">{{ scope.row.duration }}</el-tag>
+                        <el-tag v-if="scope.row.duration<2000" type="info">{{ scope.row.duration }}</el-tag>
+                    </template>
+                </el-table-column>
+                <el-table-column
+                  label="SpanId"
+                  prop="span_id"
+                  :show-overflow-tooltip="true" 
+                  v-if="colData[6].istrue"
+                >
+                </el-table-column>
+              </el-table>
+
+              <pagination
+                v-show="total>0"
+                :total="total"
+                :page.sync="spansQuery.pageIndex"
+                :limit.sync="spansQuery.pageSize"
+                @pagination="getServiceSpans"
+              />
+            </div>
+          </el-tab-pane>
+        </el-tabs>
+      </el-card>
+    </template>
+  </BasicLayout>
+</template>
+<script>
+import {digitsService,serviceSpans,serviceCompare,serviceErrors} from "@/api/service"
+import storage from '@/utils/storage'
+import { uniqueArr } from '@/utils'
+import moment from 'moment'
+export default {
+  data(){
+    return {
+      timeQuery:{
+        app_alias:'',
+        service_name:'',
+        hour_num:1, 
+      },
+      timeOptions:[
+        {
+          value: 1,
+          label: '1 小时'
+        },
+        {
+          value: 3,
+          label: '3 小时'
+        },
+        {
+          value: 6,
+          label: '6 小时'
+        },
+        {
+          value: 12,
+          label: '12 小时'
+        },
+        {
+          value: 24,
+          label: '24 小时'
+        },
+      ],
+      spanOptions:[
+        {
+          value: 'SPAN_KIND_CLIENT',
+          label: 'SPAN_KIND_CLIENT'
+        },
+        {
+          value: 'SPAN_KIND_SERVER',
+          label: 'SPAN_KIND_SERVER'
+        },
+        {
+          value: 'SPAN_KIND_INTERNAL',
+          label: 'SPAN_KIND_INTERNAL'
+        },
+        {
+          value: 'SPAN_KIND_CONSUMER',
+          label: 'SPAN_KIND_CONSUMER'
+        },
+        {
+          value: 'SPAN_KIND_PRODUCER',
+          label: 'SPAN_KIND_PRODUCER'
+        },
+      ],
+      // 设置选中的列的复选框
+      colSelect: [
+        "TraceId",
+        "ServiceName",
+        "DateTime",
+        "Method",
+        "Code",
+        "Duration(ms)",
+      ],
+      colData: [
+        { title: "TraceId", istrue: false },
+        { title: "ServiceName", istrue: false },
+        { title: "DateTime", istrue: false },
+        { title: "Method", istrue: false },
+        { title: "Code", istrue: false },
+        { title: "Duration(ms)", istrue: false },
+        { title: "SpanId", istrue: false },
+      ],
+      loading:false,
+      total:0,
+      activeName:'first',
+      digitsObj:{},
+      digitsQuery:{
+        app_alias:'',
+        service_name:''
+      },
+      timer:null,
+      spansQuery:{
+        app_alias:'',
+        service_name:'', // 支持多个,多个并列
+        only_exception:0 ,   // 仅显示异常trace相关
+        only_database:0,    // 仅显示数据库相关
+          // 支持分页,参数与之前一致
+          // 支持时间筛选,参数与之前一致
+        trace_id: '',// trace id, 字符串
+        span_kind: '',// 固定5个值,建议下拉列表,分别为SPAN_KIND_CLIENT SPAN_KIND_SERVER SPAN_KIND_INTERNAL SPAN_KIND_CONSUMER SPAN_KIND_PRODUCER
+        span_attribute_key: '',// 字符串
+        span_attribute_value:'', // 字符串
+        min_duration:0,  // 最小耗时
+        max_duration:0, // 最大耗时
+        start_time:0,
+        end_time:0,
+        pageIndex:1,
+        pageSize:10
+      },
+      spansList:[],
+      ServiceCompareObj:{
+        current:[],
+        forward:[],
+        time:[],
+      },
+      errorRateObj:{
+        current:[],
+        forward:[],
+        time:[],
+      },
+      compareChart:null,
+      errorChart:null,
+      name:''
+    }
+  },
+  watch: {
+     '$store.state.time.globalTimes': {
+        handler(newValue, oldValue) {
+            if(newValue){
+              this.digitsQuery.start_time= newValue.start_time;
+              this.digitsQuery.end_time= newValue.end_time;
+              this.getDigitsService();
+              if(newValue.timeOut){
+                console.log(newValue.timeOut,'业务接口页面假如timeOut有变化了执行,否而不执行')
+                if(newValue.timeOut == 1){
+                  clearInterval(this.timer);
+                }else{
+                  clearInterval(this.timer);
+                  this.Refresh(newValue.timeOut);
+                }
+              }
+            }
+        },
+        // immediate: true,
+        deep: true
+    },
+  },
+  created(){
+     // 说明
+    // appItem中的id和app_id是一样的
+    this.appItem=storage.get('appsItem');
+    console.log(this.appItem,'appitem 服务-----')
+    if(JSON.stringify(this.appItem) !="{}"){
+      this.digitsQuery.app_alias=this.appItem.app_alias;
+      this.digitsQuery.app_id = this.appItem.id;
+      this.digitsQuery.start_time = this.appItem.start_time;
+      this.digitsQuery.end_time = this.appItem.end_time;
+      this.spansQuery.app_alias=this.appItem.app_alias;
+      this.spansQuery.start_time=this.appItem.start_time;
+      this.spansQuery.end_time=this.appItem.end_time;
+      this.timeQuery.app_alias=this.appItem.app_alias;
+      
+    }
+    if(this.$route.query.service_name != undefined){
+      this.digitsQuery.service_name =this.$route.query.service_name
+      this.spansQuery.service_name =this.$route.query.service_name
+      this.timeQuery.service_name=this.$route.query.service_name;
+
+      this.getDigitsService();
+      this.getServiceSpans();
+      this.getServiceCompare();
+      this.getErrorRateCompare()
+    }
+
+    if(this.$route.query.name != undefined){
+      this.name = this.$route.query.name
+    }
+
+    let strr = window.location.href;
+    let param = this.parseQueryString(strr);
+    
+    if(param.app_alias!=undefined && param.service_name != undefined){
+      console.log('从拓扑跳转过来')
+        this.digitsQuery.app_alias = param.app_alias;
+        this.spansQuery.app_alias=this.appItem.app_alias;
+        this.timeQuery.app_alias=this.appItem.app_alias;
+        this.digitsQuery.service_name =this.$route.query.service_name
+        this.spansQuery.service_name =this.$route.query.service_name
+        this.timeQuery.service_name=this.$route.query.service_name;
+        this.getDigitsService();
+        this.getServiceSpans();
+        this.getServiceCompare();
+        this.getErrorRateCompare()
+    }
+
+    this.columnChange();
+  },
+  mounted(){
+    //  this.$nextTick(()=>{
+    //    this.$echarts5.connect([this.errorChart, this.compareChart]);
+    //  })
+  },
+  methods:{
+    parseQueryString(url){
+      var json = {};
+      var arr = url.substr(url.indexOf('?') + 1).split('&');
+      console.log(arr,'arr')
+      arr.forEach(item=>{
+          var tmp = item.split('=');
+              json[tmp[0]] = tmp[1];
+      });
+      return json;
+    },
+    handletimeQuery(){
+      this.getServiceCompare();
+      this.getErrorRateCompare()
+    },
+    changetimeQuery(val){
+      this.timeQuery.hour_num = val;
+      this.getServiceCompare();
+      this.getErrorRateCompare()
+    },
+    handleSpansQuery(){
+      this.getServiceSpans();
+    },
+    changeErrorSpans(val){
+      console.log(val)
+      this.spansQuery.only_exception=val;
+      this.getServiceSpans();
+    },
+    changeSQLSpans(val){
+      console.log(val)
+      this.spansQuery.only_database=val;
+      this.getServiceSpans();
+    },
+    changeSpansQuery(val){
+      this.spansQuery.span_kind = val;
+      this.getServiceSpans();
+    },
+    //控制列的显示和隐藏
+    columnChange(val) {
+      this.colData.filter((i) => {
+        if (this.colSelect.indexOf(i.title) !== -1) {
+          i.istrue = true;
+        } else {
+          i.istrue = false;
+        }
+      });
+    },
+    handleClick(tab){},
+    Refresh(timeOut){
+      this.timer = setInterval(()=>{
+        this.getDigitsService();
+      },timeOut)
+    },
+    getDigitsService(){
+      digitsService(this.digitsQuery).then((res)=>{
+        console.log(res,'块的数据----')
+        if(res.code == 200){
+          this.digitsObj= res.data
+        }
+      })
+    },
+    getServiceSpans(){
+      serviceSpans(this.spansQuery).then((res)=>{
+        console.log(res,'spans数据----')
+        if(res.code == 200){
+          this.spansList= res.data.list
+          this.total = res.data.count
+        }
+      })
+    },
+    getServiceCompare(){
+      console.log('活跃度-----/compare/liveness')
+      serviceCompare(this.timeQuery).then(res=>{
+        if(res.code == 200){
+          this.ServiceCompareObj = res.data;
+          console.log(this.ServiceCompareObj,'活跃度')
+          if(this.ServiceCompareObj.current.length>0){
+          this.initServiceCompareChart(this.ServiceCompareObj)
+          }
+        }
+      })
+    },
+    initServiceCompareChart(data) {
+      console.log(data,'this.ServiceCompareObj')
+      let _this = this;
+      this.compareChart = this.$echarts5.init(document.getElementById('serviceActive'))
+      this.compareChart.setOption({
+        tooltip: {
+          trigger: 'axis',
+          axisPointer: {
+            type: 'cross',
+            crossStyle: {
+              color: '#999'
+            }
+          }
+        },
+        legend: {
+          data:['当前时段','前续时段'],
+          // selected: {
+          //       '当前时段': true,
+          //       '前续时段对比': false
+          //   }
+        },
+        toolbox: {
+          feature: {
+            // dataView: { show: true, readOnly: false },
+            magicType: { show: true, type: ['line', 'bar'] },
+            restore: { show: true },
+            // saveAsImage: { show: true }
+          }
+        },
+        grid: {
+          // top:'5%',
+          left: '3%',
+          right: '7%',
+          bottom: '1%',
+          containLabel: true
+        },
+        xAxis: [
+          {
+            type: 'category',
+            // type:'time',
+            data: data.time,
+            // axisPointer: {
+            //   type: 'shadow'
+            // },
+          }
+        ],
+        yAxis: [
+          {
+            type: 'value',
+          }
+        ],
+        series: [
+          {
+            name:'当前时段',
+            type: 'bar',
+            tooltip: {
+              valueFormatter: function (value) {
+                return value;
+              }
+            },
+            barWidth:8,
+            // markLine: {
+            //   label:{
+            //     formatter: '{b}',
+            //     backgroundColor:"#5A6FC0",
+            //     color:"#fff",
+            //     padding:[4,8]
+            //   },
+            //   lineStyle: {
+            //     type: "dashed",
+            //     color: "#5A6FC0",
+            //     width:2
+            //   },
+            //   data: [
+            //       {
+            //           name: 'p50',
+            //           xAxis:data.buckets[data.current.quantile_indexes.p50],
+            //       },
+            //       {
+            //           name: 'p90',
+            //           xAxis:data.buckets[data.current.quantile_indexes.p90],
+            //       },
+            //       {
+            //           name: 'p99',
+            //           xAxis:data.buckets[data.current.quantile_indexes.p99],
+            //       },
+            //   ]
+            // },
+            data: data.current != undefined?data.current :[],            
+          },
+          {
+            type: 'line',
+            name:'前续时段',
+            tooltip: {
+              valueFormatter: function (value) {
+                return value;
+              }
+            },
+            lineStyle:{
+              width:3
+            },
+            // markLine: {
+            //     name: "",
+            //     // symbol: ["none", "none"], //去掉箭头
+            //     lineStyle: {
+            //         type: "dashed",
+            //         color: "#9ECA7E",
+            //         width:2
+            //     },
+            //     label: {
+            //         formatter: '{b}',
+            //         backgroundColor:"#9ECA7E",
+            //         color:"#fff",
+            //         padding:[4,8]
+            //     },
+            //     data: [
+            //       {
+            //         name: 'p50',
+            //         xAxis:data.buckets[data.previous.quantile_indexes.p50],
+            //       },
+            //       {
+            //         name: 'p90',
+            //         xAxis:data.buckets[data.previous.quantile_indexes.p90],
+            //       },
+            //       {
+            //         name: 'p99',
+            //         xAxis:data.buckets[data.previous.quantile_indexes.p99],
+            //       }
+            //     ], //这里设置false是隐藏不了的,可以设置为-1
+            // },
+
+            data:data.forward!= undefined?data.forward :[]
+          }
+        ]
+      })
+       window.addEventListener('resize', () => {
+        this.compareChart.resize()
+      })
+      // let that = this
+      // that.compareChart.on('mousemove', (params) => {
+      //     let index1 = params.name
+      //     // 饼状图
+      //     that.errorChart.dispatchAction({
+      //       type: 'highlight',
+      //       seriesIndex: 0,
+      //       name: index1
+      //     })
+      // })
+      // // 1.悬停离开桑基图,饼状一高光消失
+      // that.compareChart.on('mouseout', (params) => {
+      //   let index1 = params.name
+      //   that.errorChart.dispatchAction({
+      //     type: 'downplay',
+      //     seriesIndex: 0,
+      //     name: index1
+      //   })
+      // })
+      // // 1.悬停桑基图,饼状一tooltip提示
+      // that.compareChart.on('mousemove', (params) => {
+      //   let index1 = params.name
+      //   that.errorChart.dispatchAction({
+      //     type: 'showTip',
+      //     seriesIndex: 0,
+      //     name: index1
+      //   })
+      // })
+      // this.compareChart.connect([this.errorChart]);
+    },
+    getErrorRateCompare(){
+      console.log('活跃度-----/compare/liveness')
+      serviceErrors(this.timeQuery).then(res=>{
+        if(res.code == 200){
+          this.errorRateObj = res.data;
+          console.log(this.errorRateObj,'错误率')
+          if(this.errorRateObj.current.length>0){
+            this.initErrorRateCompareChart(this.errorRateObj)
+          }
+        }
+      })
+    },
+    initErrorRateCompareChart(data) {
+      console.log(data,'this.errorRateObj')
+      let _this = this;
+      this.errorChart = this.$echarts5.init(document.getElementById('errorRate'))
+      this.errorChart.setOption({
+        tooltip: {
+          trigger: 'axis',
+          axisPointer: {
+            type: 'cross',
+            crossStyle: {
+              color: '#999'
+            }
+          }
+        },
+        legend: {
+          data:['当前时段','前续时段'],
+          // selected: {
+          //       '当前时段': true,
+          //       '前续时段对比': false
+          //   }
+        },
+        toolbox: {
+          feature: {
+            // dataView: { show: true, readOnly: false },
+            magicType: { show: true, type: ['line', 'bar'] },
+            restore: { show: true },
+            // saveAsImage: { show: true }
+          }
+        },
+        grid: {
+          // top:'5%',
+          left: '3%',
+          right: '7%',
+          bottom: '1%',
+          containLabel: true
+        },
+        xAxis: [
+          {
+            // type: 'value',
+            type:'category',
+            data: data.time,
+            // axisPointer: {
+            //   type: 'shadow'
+            // },
+
+          }
+        ],
+        yAxis: [
+          {
+            type: 'value',
+          }
+        ],
+        series: [
+          {
+            name:'当前时段',
+            type: 'bar',
+            tooltip: {
+              valueFormatter: function (value) {
+                return value;
+              }
+            },
+            barWidth:8,
+            // markLine: {
+            //   label:{
+            //     formatter: '{b}',
+            //     backgroundColor:"#5A6FC0",
+            //     color:"#fff",
+            //     padding:[4,8]
+            //   },
+            //   lineStyle: {
+            //     type: "dashed",
+            //     color: "#5A6FC0",
+            //     width:2
+            //   },
+            //   data: [
+            //       {
+            //           name: 'p50',
+            //           xAxis:data.buckets[data.current.quantile_indexes.p50],
+            //       },
+            //       {
+            //           name: 'p90',
+            //           xAxis:data.buckets[data.current.quantile_indexes.p90],
+            //       },
+            //       {
+            //           name: 'p99',
+            //           xAxis:data.buckets[data.current.quantile_indexes.p99],
+            //       },
+            //   ]
+            // },
+            data: data.current!= undefined?data.current:[],            
+          },
+          {
+            type: 'line',
+            name:'前续时段',
+            tooltip: {
+              valueFormatter: function (value) {
+                return value;
+              }
+            },
+            lineStyle:{
+              width:3
+            },
+            // markLine: {
+            //     name: "",
+            //     // symbol: ["none", "none"], //去掉箭头
+            //     lineStyle: {
+            //         type: "dashed",
+            //         color: "#9ECA7E",
+            //         width:2
+            //     },
+            //     label: {
+            //         formatter: '{b}',
+            //         backgroundColor:"#9ECA7E",
+            //         color:"#fff",
+            //         padding:[4,8]
+            //     },
+            //     data: [
+            //       {
+            //         name: 'p50',
+            //         xAxis:data.buckets[data.previous.quantile_indexes.p50],
+            //       },
+            //       {
+            //         name: 'p90',
+            //         xAxis:data.buckets[data.previous.quantile_indexes.p90],
+            //       },
+            //       {
+            //         name: 'p99',
+            //         xAxis:data.buckets[data.previous.quantile_indexes.p99],
+            //       }
+            //     ], //这里设置false是隐藏不了的,可以设置为-1
+            // },
+
+            data:data.forward!=undefined?data.forward:[]
+          }
+        ]
+      })
+
+      window.addEventListener('resize', () => {
+        this.errorChart.resize()
+      })
+      // let that = this
+      // that.errorChart.on('mousemove', (params) => {
+      //     let index1 = params.name
+      //     // 饼状图
+      //     that.compareChart.dispatchAction({
+      //       type: 'highlight',
+      //       seriesIndex: 0,
+      //       name: index1
+      //     })
+      // })
+      // // 1.悬停离开桑基图,饼状一高光消失
+      // that.errorChart.on('mouseout', (params) => {
+      //   let index1 = params.name
+      //   that.compareChart.dispatchAction({
+      //     type: 'downplay',
+      //     seriesIndex: 0,
+      //     name: index1
+      //   })
+      // })
+      // // 1.悬停桑基图,饼状一tooltip提示
+      // that.errorChart.on('mousemove', (params) => {
+      //   let index1 = params.name
+      //   that.compareChart.dispatchAction({
+      //     type: 'showTip',
+      //     seriesIndex: 0,
+      //     name: index1
+      //   })
+      // })
+
+      // this.errorChart.connect([this.compareChart]);
+    },
+    back(){
+      this.$router.push({
+        path:'/service/service/index'
+      })
+    },
+    goto(row){
+      let href = this.$router.resolve({
+        path:'/latency/index',
+        query:{
+          id:row.trace_id
+        }
+      })
+      console.log(href)
+      window.open(window.location.origin+"/"+href.href,"_blank")
+    },
+  },
+  beforeDestroy() {
+    clearInterval(this.timer);
+  },
+
+}
+</script>
+<style lang="scss" scoped>
+.echartsWrap{
+  width:100%;
+  // height: 300px;
+}
+.h6{
+  font-size: 14px;
+}
+.Dur_input ::v-deep .el-input__inner{
+  width:100px;
+}
+.noData{
+    width: 100%;
+    height: 200px;
+    background: #fff;
+}
+.noData_title{
+    margin-bottom: 0px;
+    padding: 2px 5px;
+    text-overflow: ellipsis;
+    overflow: hidden;
+    white-space: nowrap;
+    font-size: 14px;
+    font-weight: 500;
+    line-height: 1.57143;
+    font-family: Inter, Helvetica, Arial, sans-serif;
+}
+</style>

+ 3 - 3
src/views/warn-manage/alarm/index.vue

@@ -5,7 +5,7 @@
         <div class="amountIframe">
             <div class="header" v-if='iframeFlag'>
               <div class="header-right">
-                <el-button type="primary" size="mini" style="margin-right:12px;vertical-align: middle;" round @click="handleIframe">使用Iframe</el-button>
+                <el-button type="primary" size="mini" style="margin-right:12px;vertical-align: middle;" round @click="handleIframe">使用快捷站点</el-button>
               </div>
             </div>
             <div v-if='iframeFlag'>
@@ -27,8 +27,8 @@
           <el-form ref="form" :model="form" :rules="rules" label-width="120px">
               <el-row>
                 <el-col :span="24">
-                  <el-form-item label="URL地址:" prop="url">
-                    <el-input v-model="form.url" placeholder="请填入需要绑定的页面URL" />
+                  <el-form-item label="站点地址:" prop="url">
+                    <el-input v-model="form.url" placeholder="请填入需要绑定的站点URL" />
                   </el-form-item>
                 </el-col>
                 <el-col :span="24">

+ 3 - 3
src/views/warn-manage/contact/index.vue

@@ -5,7 +5,7 @@
         <div class="amountIframe">
             <div class="header" v-if='iframeFlag'>
               <div class="header-right">
-                <el-button type="primary" size="mini" style="margin-right:12px;vertical-align: middle;" round @click="handleIframe">使用Iframe</el-button>
+                <el-button type="primary" size="mini" style="margin-right:12px;vertical-align: middle;" round @click="handleIframe">使用快捷站点</el-button>
               </div>
             </div>
             <div v-if='iframeFlag'>
@@ -27,8 +27,8 @@
           <el-form ref="form" :model="form" :rules="rules" label-width="120px">
               <el-row>
                 <el-col :span="24">
-                  <el-form-item label="URL地址:" prop="url">
-                    <el-input v-model="form.url" placeholder="请填入需要绑定的页面URL" />
+                  <el-form-item label="站点地址:" prop="url">
+                    <el-input v-model="form.url" placeholder="请填入需要绑定的站点URL" />
                   </el-form-item>
                 </el-col>
                 <el-col :span="24">

+ 3 - 3
src/views/warn-manage/notification/index.vue

@@ -5,7 +5,7 @@
         <div class="amountIframe">
             <div class="header" v-if='iframeFlag'>
               <div class="header-right">
-                <el-button type="primary" size="mini" style="margin-right:12px;vertical-align: middle;" round @click="handleIframe">使用Iframe</el-button>
+                <el-button type="primary" size="mini" style="margin-right:12px;vertical-align: middle;" round @click="handleIframe">使用快捷站点</el-button>
               </div>
             </div>
             <div v-if='iframeFlag'>
@@ -27,8 +27,8 @@
           <el-form ref="form" :model="form" :rules="rules" label-width="120px">
               <el-row>
                 <el-col :span="24">
-                  <el-form-item label="URL地址:" prop="url">
-                    <el-input v-model="form.url" placeholder="请填入需要绑定的页面URL" />
+                  <el-form-item label="站点地址:" prop="url">
+                    <el-input v-model="form.url" placeholder="请填入需要绑定的站点URL" />
                   </el-form-item>
                 </el-col>
                 <el-col :span="24">

+ 3 - 3
src/views/warn-manage/silent/index.vue

@@ -5,7 +5,7 @@
         <div class="amountIframe">
             <div class="header" v-if='iframeFlag'>
               <div class="header-right">
-                <el-button type="primary" size="mini" style="margin-right:12px;vertical-align: middle;" round @click="handleIframe">使用Iframe</el-button>
+                <el-button type="primary" size="mini" style="margin-right:12px;vertical-align: middle;" round @click="handleIframe">使用快捷站点</el-button>
               </div>
             </div>
             <div v-if='iframeFlag'>
@@ -27,8 +27,8 @@
           <el-form ref="form" :model="form" :rules="rules" label-width="120px">
               <el-row>
                 <el-col :span="24">
-                  <el-form-item label="URL地址:" prop="url">
-                    <el-input v-model="form.url" placeholder="请填入需要绑定的页面URL" />
+                  <el-form-item label="站点地址:" prop="url">
+                    <el-input v-model="form.url" placeholder="请填入需要绑定的站点URL" />
                   </el-form-item>
                 </el-col>
                 <el-col :span="24">

Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor