Просмотр исходного кода

Merge branch 'dev_test' into dev

Jinyao 5 лет назад
Родитель
Сommit
64d26e9d72
7 измененных файлов с 720 добавлено и 468 удалено
  1. 1 0
      .eslintrc.js
  2. 267 238
      package-lock.json
  3. 1 0
      package.json
  4. 20 0
      src/api/devcloud/apitest.ts
  5. 0 120
      src/components/APITestInfoForm.vue
  6. 1 0
      src/element-plus.ts
  7. 430 110
      src/views/Project/APITest.vue

+ 1 - 0
.eslintrc.js

@@ -19,5 +19,6 @@ module.exports = {
     'no-param-reassign': [2, { props: false }],
     'linebreak-style': [0, 'error', 'windows'],
     'import/no-cycle': 0,
+    '@typescript-eslint/no-this-alias': ['off'],
   },
 };

+ 267 - 238
package-lock.json

@@ -2881,6 +2881,160 @@
         "tslint": "^5.20.1",
         "webpack": "^4.0.0",
         "yorkie": "^2.0.0"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "4.3.0",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+          "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "color-convert": "^2.0.1"
+          }
+        },
+        "chalk": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
+          "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "cosmiconfig": {
+          "version": "6.0.0",
+          "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz",
+          "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "@types/parse-json": "^4.0.0",
+            "import-fresh": "^3.1.0",
+            "parse-json": "^5.0.0",
+            "path-type": "^4.0.0",
+            "yaml": "^1.7.2"
+          }
+        },
+        "deepmerge": {
+          "version": "4.2.2",
+          "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
+          "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==",
+          "dev": true,
+          "optional": true
+        },
+        "fork-ts-checker-webpack-plugin-v5": {
+          "version": "npm:fork-ts-checker-webpack-plugin@5.2.1",
+          "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-5.2.1.tgz",
+          "integrity": "sha512-SVi+ZAQOGbtAsUWrZvGzz38ga2YqjWvca1pXQFUArIVXqli0lLoDQ8uS0wg0kSpcwpZmaW5jVCZXQebkyUQSsw==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "@babel/code-frame": "^7.8.3",
+            "@types/json-schema": "^7.0.5",
+            "chalk": "^4.1.0",
+            "cosmiconfig": "^6.0.0",
+            "deepmerge": "^4.2.2",
+            "fs-extra": "^9.0.0",
+            "memfs": "^3.1.2",
+            "minimatch": "^3.0.4",
+            "schema-utils": "2.7.0",
+            "semver": "^7.3.2",
+            "tapable": "^1.0.0"
+          }
+        },
+        "fs-extra": {
+          "version": "9.1.0",
+          "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
+          "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "at-least-node": "^1.0.0",
+            "graceful-fs": "^4.2.0",
+            "jsonfile": "^6.0.1",
+            "universalify": "^2.0.0"
+          }
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true,
+          "optional": true
+        },
+        "jsonfile": {
+          "version": "6.1.0",
+          "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
+          "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "graceful-fs": "^4.1.6",
+            "universalify": "^2.0.0"
+          }
+        },
+        "lru-cache": {
+          "version": "6.0.0",
+          "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+          "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "yallist": "^4.0.0"
+          }
+        },
+        "schema-utils": {
+          "version": "2.7.0",
+          "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz",
+          "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "@types/json-schema": "^7.0.4",
+            "ajv": "^6.12.2",
+            "ajv-keywords": "^3.4.1"
+          }
+        },
+        "semver": {
+          "version": "7.3.5",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
+          "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "lru-cache": "^6.0.0"
+          }
+        },
+        "supports-color": {
+          "version": "7.2.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        },
+        "universalify": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
+          "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
+          "dev": true,
+          "optional": true
+        }
       }
     },
     "@vue/cli-plugin-vuex": {
@@ -2953,6 +3107,37 @@
         "webpack-merge": "^4.2.2"
       },
       "dependencies": {
+        "ansi-styles": {
+          "version": "4.3.0",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+          "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "color-convert": "^2.0.1"
+          }
+        },
+        "chalk": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
+          "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
         "debug": {
           "version": "4.3.1",
           "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
@@ -2962,11 +3147,62 @@
             "ms": "2.1.2"
           }
         },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true,
+          "optional": true
+        },
+        "json5": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz",
+          "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "minimist": "^1.2.5"
+          }
+        },
+        "loader-utils": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
+          "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "big.js": "^5.2.2",
+            "emojis-list": "^3.0.0",
+            "json5": "^2.1.2"
+          }
+        },
         "ms": {
           "version": "2.1.2",
           "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
           "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
           "dev": true
+        },
+        "supports-color": {
+          "version": "7.2.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        },
+        "vue-loader-v16": {
+          "version": "npm:vue-loader@16.2.0",
+          "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.2.0.tgz",
+          "integrity": "sha512-TitGhqSQ61RJljMmhIGvfWzJ2zk9m1Qug049Ugml6QP3t0e95o0XJjk29roNEiPKJQBEi8Ord5hFuSuELzSp8Q==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "chalk": "^4.1.0",
+            "hash-sum": "^2.0.0",
+            "loader-utils": "^2.0.0"
+          }
         }
       }
     },
@@ -6143,6 +6379,22 @@
         "safer-buffer": "^2.1.0"
       }
     },
+    "echarts": {
+      "version": "5.0.2",
+      "resolved": "https://registry.npmjs.org/echarts/-/echarts-5.0.2.tgz",
+      "integrity": "sha512-En0VYpc96nw2/2AZoBWPHsGi471zMublttj50kfFpYAeR4geup0Tj9iVgEXh7QYZFPnRiruDJEjcB5PXZ+BYzQ==",
+      "requires": {
+        "tslib": "2.0.3",
+        "zrender": "5.0.4"
+      },
+      "dependencies": {
+        "tslib": {
+          "version": "2.0.3",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
+          "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ=="
+        }
+      }
+    },
     "ee-first": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
@@ -7260,160 +7512,6 @@
         "worker-rpc": "^0.1.0"
       }
     },
-    "fork-ts-checker-webpack-plugin-v5": {
-      "version": "npm:fork-ts-checker-webpack-plugin@5.2.1",
-      "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-5.2.1.tgz",
-      "integrity": "sha512-SVi+ZAQOGbtAsUWrZvGzz38ga2YqjWvca1pXQFUArIVXqli0lLoDQ8uS0wg0kSpcwpZmaW5jVCZXQebkyUQSsw==",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "@babel/code-frame": "^7.8.3",
-        "@types/json-schema": "^7.0.5",
-        "chalk": "^4.1.0",
-        "cosmiconfig": "^6.0.0",
-        "deepmerge": "^4.2.2",
-        "fs-extra": "^9.0.0",
-        "memfs": "^3.1.2",
-        "minimatch": "^3.0.4",
-        "schema-utils": "2.7.0",
-        "semver": "^7.3.2",
-        "tapable": "^1.0.0"
-      },
-      "dependencies": {
-        "ansi-styles": {
-          "version": "4.3.0",
-          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-          "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "color-convert": "^2.0.1"
-          }
-        },
-        "chalk": {
-          "version": "4.1.0",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
-          "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "ansi-styles": "^4.1.0",
-            "supports-color": "^7.1.0"
-          }
-        },
-        "color-convert": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "color-name": "~1.1.4"
-          }
-        },
-        "cosmiconfig": {
-          "version": "6.0.0",
-          "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz",
-          "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "@types/parse-json": "^4.0.0",
-            "import-fresh": "^3.1.0",
-            "parse-json": "^5.0.0",
-            "path-type": "^4.0.0",
-            "yaml": "^1.7.2"
-          }
-        },
-        "deepmerge": {
-          "version": "4.2.2",
-          "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
-          "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==",
-          "dev": true,
-          "optional": true
-        },
-        "fs-extra": {
-          "version": "9.1.0",
-          "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
-          "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "at-least-node": "^1.0.0",
-            "graceful-fs": "^4.2.0",
-            "jsonfile": "^6.0.1",
-            "universalify": "^2.0.0"
-          }
-        },
-        "has-flag": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-          "dev": true,
-          "optional": true
-        },
-        "jsonfile": {
-          "version": "6.1.0",
-          "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
-          "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "graceful-fs": "^4.1.6",
-            "universalify": "^2.0.0"
-          }
-        },
-        "lru-cache": {
-          "version": "6.0.0",
-          "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
-          "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "yallist": "^4.0.0"
-          }
-        },
-        "schema-utils": {
-          "version": "2.7.0",
-          "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz",
-          "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "@types/json-schema": "^7.0.4",
-            "ajv": "^6.12.2",
-            "ajv-keywords": "^3.4.1"
-          }
-        },
-        "semver": {
-          "version": "7.3.4",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz",
-          "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "lru-cache": "^6.0.0"
-          }
-        },
-        "supports-color": {
-          "version": "7.2.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
-          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "has-flag": "^4.0.0"
-          }
-        },
-        "universalify": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
-          "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
-          "dev": true,
-          "optional": true
-        }
-      }
-    },
     "form-data": {
       "version": "2.3.3",
       "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
@@ -13708,90 +13806,6 @@
         }
       }
     },
-    "vue-loader-v16": {
-      "version": "npm:vue-loader@16.1.2",
-      "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.1.2.tgz",
-      "integrity": "sha512-8QTxh+Fd+HB6fiL52iEVLKqE9N1JSlMXLR92Ijm6g8PZrwIxckgpqjPDWRP5TWxdiPaHR+alUWsnu1ShQOwt+Q==",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "chalk": "^4.1.0",
-        "hash-sum": "^2.0.0",
-        "loader-utils": "^2.0.0"
-      },
-      "dependencies": {
-        "ansi-styles": {
-          "version": "4.3.0",
-          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-          "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "color-convert": "^2.0.1"
-          }
-        },
-        "chalk": {
-          "version": "4.1.0",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
-          "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "ansi-styles": "^4.1.0",
-            "supports-color": "^7.1.0"
-          }
-        },
-        "color-convert": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "color-name": "~1.1.4"
-          }
-        },
-        "has-flag": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-          "dev": true,
-          "optional": true
-        },
-        "json5": {
-          "version": "2.2.0",
-          "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz",
-          "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "minimist": "^1.2.5"
-          }
-        },
-        "loader-utils": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
-          "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "big.js": "^5.2.2",
-            "emojis-list": "^3.0.0",
-            "json5": "^2.1.2"
-          }
-        },
-        "supports-color": {
-          "version": "7.2.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
-          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "has-flag": "^4.0.0"
-          }
-        }
-      }
-    },
     "vue-router": {
       "version": "4.0.3",
       "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.0.3.tgz",
@@ -14728,6 +14742,21 @@
           "dev": true
         }
       }
+    },
+    "zrender": {
+      "version": "5.0.4",
+      "resolved": "https://registry.npmjs.org/zrender/-/zrender-5.0.4.tgz",
+      "integrity": "sha512-DJpy0yrHYY5CuH6vhb9IINWbjvBUe/56J8aH86Jb7O8rRPAYZ3M2E469Qf5B3EOIfM3o3aUrO5edRQfLJ+l1Qw==",
+      "requires": {
+        "tslib": "2.0.3"
+      },
+      "dependencies": {
+        "tslib": {
+          "version": "2.0.3",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
+          "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ=="
+        }
+      }
     }
   }
 }

+ 1 - 0
package.json

@@ -13,6 +13,7 @@
   "dependencies": {
     "axios": "^0.21.1",
     "core-js": "^3.6.5",
+    "echarts": "^5.0.2",
     "element-plus": "^1.0.2-beta.31",
     "jsonwebtoken": "^8.5.1",
     "vue": "^3.0.0",

+ 20 - 0
src/api/devcloud/apitest.ts

@@ -2,4 +2,24 @@ import axios from '@/utils/axios';
 
 import { APITEST_PREFIX } from './prefix';
 
+type CreateAPITest = {
+  projectId: number;
+  createTime: string;
+  username: string;
+  testName: string;
+  url: string;
+  params: JSON;
+  method: string;
+  qps: number;
+}
 export const getAPITestInfosByProjectId = (projectId: number) => axios.get(`${APITEST_PREFIX}/list/${projectId}`);
+
+export const createAPITest = (APITest: CreateAPITest) => axios.post(`${APITEST_PREFIX}/create`, APITest);
+
+export const deleteAPITestByTestId = (testId: number) => axios.get(`${APITEST_PREFIX}/delete/${testId}`);
+
+export const executeAPITestByTestId = (testId: number) => axios.get(`${APITEST_PREFIX}/execute/${testId}`);
+
+export const getAPITestResultByTestId = (testId: number) => axios.get(`${APITEST_PREFIX}/result/${testId}`);
+
+export const getLatestResultByTestId = (testId: number) => axios.get(`${APITEST_PREFIX}/latest/${testId}`);

+ 0 - 120
src/components/APITestInfoForm.vue

@@ -1,120 +0,0 @@
-<template>
-  <right-form ref="rightForm">
-    <div class="APITestInfoForm">
-      <div class="title">测试任务详情</div>
-      <div class="marginTop">
-        <ElRow>
-          <ElCol :span="3">
-            <div class="key">url:</div>
-          </ElCol>
-          <ElCol :span="12" :offset="2">
-            <div class="value">{{info.url}}</div>
-          </ElCol>
-        </ElRow>
-      </div>
-      <div class="marginTop">
-        <ElRow>
-          <ElCol :span="3">
-            <div class="key">params:</div>
-          </ElCol>
-          <ElCol :span="12" :offset="2">
-            <div>
-              <vue-json-editor
-                :height="'400px'"
-                :value="info.params"
-                :show-btns="false"
-                :mode="'code'"
-                :modes="['code']"
-                lang="zh"
-              ></vue-json-editor>
-            </div>
-          </ElCol>
-        </ElRow>
-      </div>
-      <div class="marginTop">
-        <ElRow>
-          <ElCol :span="3">
-            <div class="key">并发数:</div>
-          </ElCol>
-          <ElCol :span="12" :offset="2">
-            <div class="value">{{info.qps}}</div>
-          </ElCol>
-        </ElRow>
-      </div>
-      <div class="title">测试结果</div>
-      <div v-if="info.success === 0 && info.failure === 0">
-        还未运行!
-      </div>
-      <div v-else>
-        <div class="marginTop">
-          <ElRow>
-            <ElCol :span="3">
-              <div class="key">成功:</div>
-            </ElCol>
-            <ElCol :span="12" :offset="2">
-              <div class="value">{{info.success}}</div>
-            </ElCol>
-          </ElRow>
-        </div>
-        <div class="marginTop">
-          <ElRow>
-            <ElCol :span="3">
-              <div class="key">失败:</div>
-            </ElCol>
-            <ElCol :span="12" :offset="2">
-              <div class="value">{{info.failure}}</div>
-            </ElCol>
-          </ElRow>
-        </div>
-      </div>
-    </div>
-  </right-form>
-</template>
-
-<script>
-import vueJsonEditor from 'vue-json-editor';
-import RightForm from './RightForm.vue';
-
-export default {
-  components: {
-    vueJsonEditor,
-    RightForm,
-  },
-  name: 'APITestInfoForm',
-  data() {
-    return {
-    };
-  },
-  props: {
-    info: {
-      type: Object,
-    },
-  },
-  methods: {
-    showForm() {
-      this.$refs.rightForm.showForm();
-    },
-  },
-};
-</script>
-
-<style>
-.APITestInfoForm {
-  margin-left: 30px;
-}
-.APITestInfoForm .title {
-  font-size: 24px;
-  font-weight: bold;
-  margin-top: 20px;
-}
-.APITestInfoForm .marginTop {
-  margin-top: 20px;
-}
-.APITestInfoForm .marginTop .key {
-  font-size: 20px;
-  font-weight: bold;
-}
-.APITestInfoForm .marginTop .value {
-  font-size: 18px;
-}
-</style>

+ 1 - 0
src/element-plus.ts

@@ -52,6 +52,7 @@ export const Components = [
   ElCheckbox,
   ElContainer,
   ElCol,
+  ElDrawer,
   ElHeader,
   ElMain,
   ElMenu,

+ 430 - 110
src/views/Project/APITest.vue

@@ -1,69 +1,175 @@
 <template>
-  <div class="apiTestContainer">
-    <div class="apiTestHeader">
-      <div class="title">接口测试</div>
-      <el-button size="medium" type="primary" icon="el-icon-plus" @click="handleClick('create')">新建接口测试</el-button>
-    </div>
-    <div class="apiTestTableContainer">
-      <el-table
-        :data="APITests"
-        style="width: 100%">
-        <el-table-column
+  <ElTabs class="tabs" v-model="activeTab">
+    <ElTabPane label="接口测试" name="apitest">
+      <ElTable :data="apitests" width="100%">
+        <ElTableColumn
           prop="testId"
           label="ID"
           align="center"
-          width="100">
-        </el-table-column>
-        <el-table-column
+          width="60">
+        </ElTableColumn>
+        <ElTableColumn
           prop="testName"
           label="测试名称"
           align="center"
-          width="500">
-        </el-table-column>
-        <el-table-column
-          prop="state"
-          label="状态"
-          align="center"
-          width="100"
-          :filters="[{ text: '进行中', value: '进行中' }, { text: '已完成', value: '已完成' }]"
-          :filter-method="(value, row) => {return row.result === value;}"
-          filter-placement="bottom-end">
-          <template #default="scope">
-            <template v-if="scope.row.state === '进行中'">
-              <el-tag>{{scope.row.state}}<i class="el-icon-loading"></i></el-tag>
-            </template>
-            <template v-else-if="scope.row.state === '已完成'">
-              <el-tag type="success">{{scope.row.state}}</el-tag>
-            </template>
-          </template>
-        </el-table-column>
-        <el-table-column
+          width="300">
+        </ElTableColumn>
+        <ElTableColumn
           prop="username"
           label="创建者"
           align="center"
-          width="200">
-        </el-table-column>
-        <el-table-column
+          width="180">
+        </ElTableColumn>
+        <ElTableColumn
           prop="createTime"
           label="创建时间"
           align="center"
           width="250">
-        </el-table-column>
-        <el-table-column
-          label="操作"
+        </ElTableColumn>
+        <ElTableColumn
+          label="详情"
+          align="center">
+          <template #default="scope">
+            <ElButton
+              @click="handleClick('latest', scope.row.testId)"
+              type="text"
+              size="small">最近执行详情</ElButton>
+            <ElButton @click="handleClick('detail', scope.row.testId)" type="text" size="small">测试任务详情</ElButton>
+          </template>
+        </ElTableColumn>
+        <ElTableColumn
           align="center">
+          <template #header>
+            <span>操作</span>
+            <ElButton @click="handleClick('create')" type="text" class="add-button">新建</ElButton>
+          </template>
           <template #default="scope">
-            <template v-if="scope.row.state === '进行中'">
-              <el-button type="primary" size="small" @click="handleClick('trigger', scope.row.testId)">执行测试</el-button>
-            </template>
-            <template v-else-if="scope.row.state === '已完成'">
-              <el-button type="primary" size="small" disabled>执行测试</el-button>
-            </template>
-            <el-button type="warning" size="small" @click="handleClick('viewDetail', scope.row.testId)">查看详情</el-button>
-            <el-button type="danger" size="small" @click="handleClick('delete', scope.row.testId)">删除</el-button>
+            <ElButton @click="handleClick('trigger', scope.row.testId)" type="text" size="small">触发</ElButton>
+            <ElButton @click="handleClick('delete', scope.row.testId)" type="text" size="small">删除</ElButton>
           </template>
-        </el-table-column>
-      </el-table>
+        </ElTableColumn>
+      </ElTable>
+      <!-- 测试任务详情 -->
+      <ElDrawer
+        v-model="detailDrawer"
+        :size="800">
+        <template #title>
+          <el-row class="entry-row">
+            <el-col :span="2">
+              <div class="node-type">测试</div>
+            </el-col>
+            <el-col :span="2">
+              <template class="entry-row">
+                <span>#{{detailAPIInfo.testId}}</span>
+              </template>
+            </el-col>
+            <el-col :span="4">
+              <template class="entry-row">
+                <span>{{detailAPIInfo.testName}}</span>
+              </template>
+            </el-col>
+          </el-row>
+        </template>
+        <template #default>
+          <el-row type="flex" justify="center">
+            <el-col :span="20">
+              <el-tabs
+                v-model="detailTab">
+                <el-tab-pane label="基本信息" name="basic_info">
+                  <el-row class="entry-row" style="margin-top: 15px">
+                    <el-col :span="4">
+                      <h4>url: </h4>
+                    </el-col>
+                    <el-col :span="18">
+                      <div>{{detailAPIInfo.url}}</div>
+                    </el-col>
+                  </el-row>
+                  <el-row class="entry-row" style="margin-top: 15px">
+                    <el-col :span="4">
+                      <h4>params: </h4>
+                    </el-col>
+                    <el-col :span="18">
+                      <div>
+                        <vue-json-editor
+                          :height="'400px'"
+                          v-model="detailAPIInfo.params"
+                          :show-btns="false"
+                          :mode="'code'"
+                          :modes="['code']"
+                          lang="zh"></vue-json-editor>
+                      </div>
+                    </el-col>
+                  </el-row>
+                  <el-row class="entry-row" style="margin-top: 15px">
+                    <el-col :span="4">
+                      <h4>method: </h4>
+                    </el-col>
+                    <el-col :span="18">
+                      <div>{{detailAPIInfo.method}}</div>
+                    </el-col>
+                  </el-row>
+                  <el-row class="entry-row" style="margin-top: 15px">
+                    <el-col :span="4">
+                      <h4>qps: </h4>
+                    </el-col>
+                    <el-col :span="18">
+                      <div>{{detailAPIInfo.qps}}</div>
+                    </el-col>
+                  </el-row>
+                </el-tab-pane>
+                <el-tab-pane label="执行历史" name="execute_history">
+                  <h5>注:Max、Min、Average的单位均为ms</h5>
+                  <el-table :data="testResults" width="100%">
+                    <el-table-column
+                      prop="id"
+                      label="ID"
+                      align="center"
+                      width="60">
+                    </el-table-column>
+                    <el-table-column
+                      prop="executeTime"
+                      label="执行时间"
+                      align="center">
+                    </el-table-column>
+                    <el-table-column
+                      prop="success"
+                      label="成功"
+                      align="center">
+                    </el-table-column>
+                    <el-table-column
+                      prop="failure"
+                      label="失败"
+                      align="center">
+                      <template #default="scope">
+                        {{scope.row.failure}}
+                        <span v-if="scope.row.success === 0">
+                          <i class="el-icon-warning" title="url/参数有误或者服务器出错!"></i>
+                        </span>
+                      </template>
+                    </el-table-column>
+                    <el-table-column
+                      prop="maxTime"
+                      label="Max"
+                      align="center">
+                    </el-table-column>
+                    <el-table-column
+                      prop="minTime"
+                      label="Min"
+                      align="center">
+                    </el-table-column>
+                    <el-table-column
+                      prop="averageTime"
+                      label="Average"
+                      align="center">
+                    </el-table-column>
+                  </el-table>
+                </el-tab-pane>
+              </el-tabs>
+            </el-col>
+          </el-row>
+        </template>
+      </ElDrawer>
+      <!-- 新建测试任务 -->
       <el-dialog
         v-model="showAPITestCreateModel"
         width="600px"
@@ -99,6 +205,15 @@
               <span v-if="!jsonValid" style="color: #F56C6C; font-size: 12px">JSON is invalid.</span>
             </div>
           </el-form-item>
+          <el-form-item label="方法" prop="method" required>
+            <ElSelect v-model="createAPITestForm.method" placeholder="请选择待测URL的方法">
+              <ElOption
+                v-for="(method, index) in methodList"
+                :key="index" :label="method"
+                :value="method">
+              </ElOption>
+            </ElSelect>
+          </el-form-item>
           <el-form-item label="并发数" prop="qps" required>
             <el-input v-model="createAPITestForm.qps" placeholder="请输入并发数"></el-input>
           </el-form-item>
@@ -109,91 +224,179 @@
           </span>
         </template>
       </el-dialog>
-    </div>
-    <div>
-      <APITestInfoForm ref="apiTestInfoForm" :info="resultJson"></APITestInfoForm>
-    </div>
-  </div>
+      <ElDrawer
+        v-model="latestDrawer"
+        :size="750">
+        <template #title>
+          <el-row class="entry-row">
+            <el-col :span="3">
+              <div class="node-type">测试结果</div>
+            </el-col>
+            <el-col :span="2">
+              <template class="entry-row">
+                <span>#{{latestResultInfo.id}}</span>
+              </template>
+            </el-col>
+          </el-row>
+        </template>
+        <template #default>
+          <el-row type="flex" justify="center">
+            <el-col :span="22">
+              <el-row class="entry-row" style="margin-top: 15px">
+                <el-col :span="5">
+                  <h4>执行时间:</h4>
+                </el-col>
+                <el-col :span="18">
+                  <div>{{latestResultInfo.executeTime}}</div>
+                </el-col>
+              </el-row>
+              <el-row class="entry-row" style="margin-top: 15px">
+                <el-col :span="5">
+                  <h4>成功:</h4>
+                </el-col>
+                <el-col :span="18">
+                  <div>{{latestResultInfo.success}}</div>
+                </el-col>
+              </el-row>
+              <el-row class="entry-row" style="margin-top: 15px">
+                <el-col :span="5">
+                  <h4>失败:</h4>
+                </el-col>
+                <el-col :span="18">
+                  <div>
+                    {{latestResultInfo.failure}}
+                    <span v-if="latestResultInfo.success === 0" style="color: red">(url/参数输入有误或者服务器出错!)</span>
+                  </div>
+                </el-col>
+              </el-row>
+              <el-row class="entry-row" style="margin-top: 15px">
+                <el-col :span="5">
+                  <h4>maxTime:</h4>
+                </el-col>
+                <el-col :span="18">
+                  <div>{{latestResultInfo.maxTime}} ms</div>
+                </el-col>
+              </el-row>
+              <el-row class="entry-row" style="margin-top: 15px">
+                <el-col :span="5">
+                  <h4>minTime:</h4>
+                </el-col>
+                <el-col :span="18">
+                  <div>{{latestResultInfo.minTime}} ms</div>
+                </el-col>
+              </el-row>
+              <el-row class="entry-row" style="margin-top: 15px">
+                <el-col :span="5">
+                  <h4>averageTime:</h4>
+                </el-col>
+                <el-col :span="18">
+                  <div>{{latestResultInfo.averageTime}} ms</div>
+                </el-col>
+              </el-row>
+            </el-col>
+          </el-row>
+          <el-row>
+            <el-col :span="12">
+              <div id="chart1" style="height: 500px; width: 350px"></div>
+            </el-col>
+            <el-col :span="12">
+              <div id="chart2" style="height: 500px; width: 350px"></div>
+            </el-col>
+          </el-row>
+        </template>
+      </ElDrawer>
+    </ElTabPane>
+  </ElTabs>
 </template>
 
 <script>
 import vueJsonEditor from 'vue-json-editor';
 import { APITestAPI } from '@/api';
-import APITestInfoForm from '../../components/APITestInfoForm.vue';
+import { ElMessage } from 'element-plus';
+import * as echarts from 'echarts';
 
 export default {
   components: {
     vueJsonEditor,
-    APITestInfoForm,
   },
   data() {
     return {
-      APITests: [
-        {
-          testId: 1,
-          testName: '登录接口测试',
-          state: '进行中',
-          username: '张三',
-          createTime: '2021-03-19',
-        },
-        {
-          testId: 1,
-          testName: '登录接口测试',
-          state: '已完成',
-          username: '张三',
-          createTime: '2021-03-19',
-        },
-      ],
+      activeTab: 'apitest',
+      apitests: [],
+      detailDrawer: false,
+      detailAPIInfo: [],
+      detailTab: 'basic_info',
+      testResults: [],
       showAPITestCreateModel: false,
       createAPITestForm: {
         testName: '',
         url: '',
         params: {},
+        method: '',
         qps: '',
         createTime: '',
         username: '',
       },
-      resultJson: {
-        url: 'www.baidu.com',
-        params: {
-          name: 'zhangsan',
-          age: 12,
-          occupation: 'SoftWare Engineer',
-        },
-        qps: 10,
-        success: 9,
-        failure: 1,
-        timeList: [4, 3, 5, 6, 2, 2, 10, 7, 1, 8],
-      },
+      methodList: ['GET', 'POST'],
       jsonValid: true,
+      latestDrawer: false,
+      latestResultInfo: {},
+      qps: 0,
+      timer: null,
     };
   },
   async mounted() {
-    const testJson = await APITestAPI.getAPITestInfosByProjectId(1);
-    console.log(testJson);
+    this.apitests = await APITestAPI.getAPITestInfosByProjectId(this.$store.state.workspace.currentProjectId);
   },
   methods: {
     async handleClick(action, id) {
       switch (action) {
         case 'create': {
           this.showAPITestCreateModel = true;
-          console.log(this.$store.state.workspace.currentProjectId);
           break;
         }
-        case 'trigger': {
-          console.log('运行测试');
+        case 'latest': {
+          this.latestResultInfo = await APITestAPI.getLatestResultByTestId(id);
+          this.apitests.forEach((item) => {
+            if (item.testId === id) {
+              this.qps = item.qps;
+            }
+          });
+          this.latestDrawer = true;
+          const that = this;
+          this.timer = setTimeout(() => {
+            this.$nextTick(() => {
+              that.initChart1();
+              that.initChart2();
+            });
+          }, 1500);
+          break;
+        }
+        case 'detail': {
+          this.apitests.forEach((item) => {
+            if (item.testId === id) {
+              this.detailAPIInfo = item;
+            }
+          });
+          this.testResults = await APITestAPI.getAPITestResultByTestId(id);
+          this.detailDrawer = true;
           break;
         }
-        case 'viewDetail': {
-          this.$refs.apiTestInfoForm.showForm();
+        case 'trigger': {
+          await APITestAPI.executeAPITestByTestId(id);
           break;
         }
         case 'delete': {
-          console.log('删除测试任务');
+          await APITestAPI.deleteAPITestByTestId(id);
+          ElMessage.success({
+            message: '删除成功!',
+            type: 'success',
+          });
+          this.apitests = await APITestAPI.getAPITestInfosByProjectId(this.$store.state.workspace.currentProjectId);
           break;
         }
         default: {
-          console.log('Unknown type of action');
+          console.warn('Unknown type of action.');
         }
       }
     },
@@ -211,38 +414,155 @@ export default {
     async handleAPITestCreateConfirm() {
       this.$refs.createAPITestForm.validate(async (valid) => {
         if (valid) {
-          console.log(this.createAPITestForm);
+          this.createAPITestForm.createTime = this.getCurrentTime();
+          await APITestAPI.createAPITest({
+            projectId: this.$store.state.workspace.currentProjectId,
+            createTime: this.createAPITestForm.createTime,
+            username: '',
+            testName: this.createAPITestForm.testName,
+            url: this.createAPITestForm.url,
+            params: this.createAPITestForm.params,
+            method: this.createAPITestForm.method,
+            qps: this.createAPITestForm.qps,
+          });
+          this.apitests = await APITestAPI.getAPITestInfosByProjectId(this.$store.state.workspace.currentProjectId);
           this.$refs.createAPITestForm.resetFields();
           this.showAPITestCreateModel = false;
+          ElMessage.success({
+            message: '创建成功!',
+            type: 'success',
+          });
         }
       });
     },
+    getCurrentTime() {
+      const yy = new Date().getFullYear();
+      const mm = new Date().getMonth() + 1;
+      const dd = new Date().getDate();
+      const hh = new Date().getHours();
+      const mf = new Date().getMinutes() < 10 ? `0${new Date().getMinutes()}` : new Date().getMinutes();
+      const ss = new Date().getSeconds() < 10 ? `0${new Date().getSeconds()}` : new Date().getSeconds();
+      return `${yy}-${mm}-${dd} ${hh}:${mf}:${ss}`;
+    },
+    async initChart1() {
+      const chart1 = echarts.init(document.getElementById('chart1'));
+      const options1 = {
+        title: {
+          text: `并发数: ${this.qps}`,
+          x: 'center',
+          y: 'center',
+          textStyle: {
+            fontSize: 16,
+          },
+        },
+        tooltip: {
+          trigger: 'item',
+        },
+        series: [
+          {
+            type: 'pie',
+            radius: ['40%', '50%'],
+            clockwise: true,
+            avoidLabelOverlap: true,
+            hoverOffset: 15,
+            data: [
+              { value: this.latestResultInfo.success, name: '成功', itemStyle: { color: '#CCFF99' } },
+              { value: this.latestResultInfo.failure, name: '失败', itemStyle: { color: '#FF6600' } },
+            ],
+          },
+        ],
+      };
+      chart1.setOption(options1);
+    },
+    async initChart2() {
+      const chart2 = echarts.init(document.getElementById('chart2'));
+      const option2 = {
+        title: {
+          text: '访问时间曲线图',
+          bottom: '5%',
+          left: 'center',
+        },
+        tooltip: {
+          trigger: 'trigger',
+          axisPointer: {
+            type: 'cross',
+            label: {
+              backgroundColor: '#6a7985',
+            },
+          },
+        },
+        xAxis: [
+          {
+            type: 'category',
+            boundaryGap: false,
+          },
+        ],
+        yAxis: [
+          {
+            name: '执行时间/单位ms',
+            type: 'value',
+            min: 'dataMin',
+            max: 'dataMax',
+          },
+        ],
+        series: [
+          {
+            name: '访问时间',
+            data: this.latestResultInfo.timeList,
+            type: 'line',
+            smooth: true,
+            showSymbol: true,
+            symbolSize: 3,
+            symbol: 'circle',
+            itemStyle: { color: '#8D67FF' },
+            markPoint: {
+              data: [
+                { type: 'max', name: '最大值' },
+                { type: 'min', name: '最小值' },
+              ],
+            },
+            markLine: {
+              data: [
+                { type: 'average', name: '平均值' },
+              ],
+            },
+          },
+        ],
+      };
+      chart2.setOption(option2);
+    },
   },
 };
 </script>
 
-<style>
-.apiTestContainer {
-  margin: 70px 30px 0 30px;
+<style lang="scss" scoped>
+.tabs {
+  width: 80%;
+  margin: auto auto;
 }
-.apiTestHeader {
-  display: flex;
-  justify-content: space-between;
+.add-button {
+  margin-left: 14px;
 }
-.apiTestHeader .title {
-  font-size: 20px;
+.entry-row {
+  width: 100%;
+  margin: 3px 20px;
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  justify-content: flex-start;
+  h3, h4{
+    color: #172b4d;
+  }
 }
-.apiTestTableContainer {
-  margin-top: 20px;
+.node-type{
+  color: #FFFFFF;
+  border-radius: 3px;
+  font-size: 14px;
+  background-color: #42b983;
+  text-align: center;
 }
 .create-APITest-form {
   width: 80%;
   margin: 0 auto;
 }
-.jsoneditor-vue {
-  height: 100%;
-}
-.jsoneditor-poweredBy {
-  display: none;
-}
 </style>