Ver código fonte

feat: 增加两个图像

zhaoxingrui 5 anos atrás
pai
commit
29583d4481
7 arquivos alterados com 479 adições e 298 exclusões
  1. 1 0
      .eslintrc.js
  2. 267 238
      package-lock.json
  3. 1 0
      package.json
  4. 16 0
      src/api/apitest.ts
  5. 1 1
      src/api/prefix.ts
  6. 121 21
      src/components/APITestInfoForm.vue
  7. 72 38
      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",

+ 16 - 0
src/api/apitest.ts

@@ -2,4 +2,20 @@ 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}`);

+ 1 - 1
src/api/prefix.ts

@@ -3,4 +3,4 @@ export const DEPLOYMENT_PREFIX = '/deployments';
 export const USER_PREFIX = '/users';
 export const TREE_PREFIX = '/tree';
 export const PROJECT_PREFIX = '/project';
-export const APITEST_PREFIX = '/test';
+export const APITEST_PREFIX = '/apitest';

+ 121 - 21
src/components/APITestInfoForm.vue

@@ -4,20 +4,20 @@
       <div class="title">测试任务详情</div>
       <div class="marginTop">
         <ElRow>
-          <ElCol :span="3">
+          <ElCol :span="4">
             <div class="key">url:</div>
           </ElCol>
-          <ElCol :span="12" :offset="2">
+          <ElCol :span="12" :offset="1">
             <div class="value">{{info.url}}</div>
           </ElCol>
         </ElRow>
       </div>
       <div class="marginTop">
         <ElRow>
-          <ElCol :span="3">
+          <ElCol :span="4">
             <div class="key">params:</div>
           </ElCol>
-          <ElCol :span="12" :offset="2">
+          <ElCol :span="12" :offset="1">
             <div>
               <vue-json-editor
                 :height="'400px'"
@@ -33,36 +33,39 @@
       </div>
       <div class="marginTop">
         <ElRow>
-          <ElCol :span="3">
+          <ElCol :span="4">
+            <div class="key">待测url方法:</div>
+          </ElCol>
+          <ElCol :span="12" :offset="1">
+            <div class="value">{{info.method}}</div>
+          </ElCol>
+        </ElRow>
+      </div>
+      <div class="marginTop">
+        <ElRow>
+          <ElCol :span="4">
             <div class="key">并发数:</div>
           </ElCol>
-          <ElCol :span="12" :offset="2">
+          <ElCol :span="12" :offset="1">
             <div class="value">{{info.qps}}</div>
           </ElCol>
         </ElRow>
       </div>
       <div class="title">测试结果</div>
-      <div v-if="info.success === 0 && info.failure === 0">
+      <div v-if="info.success === 0 && info.failure === 0" class="marginTop">
         还未运行!
       </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 v-if="(info.failure === info.qps) || info.success === 0">
+          访问接口失败,请检查接口输入是否规范!
         </div>
-        <div class="marginTop">
+        <div v-else class="marginTop">
           <ElRow>
-            <ElCol :span="3">
-              <div class="key">失败:</div>
+            <ElCol :span="7">
+              <div id="chart1" style="height: 500px; width: 350px"></div>
             </ElCol>
             <ElCol :span="12" :offset="2">
-              <div class="value">{{info.failure}}</div>
+              <div id="chart2" style="height: 500px; width: 450px"></div>
             </ElCol>
           </ElRow>
         </div>
@@ -73,6 +76,7 @@
 
 <script>
 import vueJsonEditor from 'vue-json-editor';
+import * as echarts from 'echarts';
 import RightForm from './RightForm.vue';
 
 export default {
@@ -90,10 +94,106 @@ export default {
       type: Object,
     },
   },
+  async mounted() {
+    const that = this;
+    setInterval(() => {
+      this.$nextTick(() => {
+        that.initChart1();
+        that.initChart2();
+      });
+    }, 2000);
+  },
   methods: {
     showForm() {
       this.$refs.rightForm.showForm();
     },
+    async initChart1() {
+      const chart1 = echarts.init(document.getElementById('chart1'));
+      const options1 = {
+        title: {
+          text: `并发数:${this.info.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.info.success, name: '成功', itemStyle: { color: '#CCFF99' } },
+              { value: this.info.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.info.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>
@@ -103,7 +203,7 @@ export default {
   margin-left: 30px;
 }
 .APITestInfoForm .title {
-  font-size: 24px;
+  font-size: 25px;
   font-weight: bold;
   margin-top: 20px;
 }

+ 72 - 38
src/views/Project/APITest.vue

@@ -18,7 +18,7 @@
           prop="testName"
           label="测试名称"
           align="center"
-          width="500">
+          width="400">
         </el-table-column>
         <el-table-column
           prop="state"
@@ -32,7 +32,7 @@
             <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 === '完成'">
+            <template v-else-if="scope.row.state === '完成'">
               <el-tag type="success">{{scope.row.state}}</el-tag>
             </template>
           </template>
@@ -49,6 +49,20 @@
           align="center"
           width="250">
         </el-table-column>
+        <el-table-column
+          prop="executeTime"
+          label="完成时间"
+          align="center"
+          width="250">
+          <template #default="scope">
+            <template v-if="scope.row.executeTime === null">
+              <span>还未执行</span>
+            </template>
+            <template v-else>
+              <span>{{scope.row.executeTime}}</span>
+            </template>
+          </template>
+        </el-table-column>
         <el-table-column
           label="操作"
           align="center">
@@ -56,10 +70,10 @@
             <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 === '完成'">
+            <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="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>
           </template>
         </el-table-column>
@@ -99,6 +113,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>
@@ -111,7 +134,7 @@
       </el-dialog>
     </div>
     <div>
-      <APITestInfoForm ref="apiTestInfoForm" :info="resultJson"></APITestInfoForm>
+      <APITestInfoForm ref="apiTestInfoForm" :info="detailedJson"></APITestInfoForm>
     </div>
   </div>
 </template>
@@ -119,6 +142,7 @@
 <script>
 import vueJsonEditor from 'vue-json-editor';
 import { APITestAPI } from '@/api';
+import { ElMessage } from 'element-plus';
 import APITestInfoForm from '../../components/APITestInfoForm.vue';
 
 export default {
@@ -128,49 +152,24 @@ export default {
   },
   data() {
     return {
-      APITests: [
-        {
-          testId: 1,
-          testName: '登录接口测试',
-          state: '进行中',
-          username: '张三',
-          createTime: '2021-03-19',
-        },
-        {
-          testId: 1,
-          testName: '登录接口测试',
-          state: '已完成',
-          username: '张三',
-          createTime: '2021-03-19',
-        },
-      ],
+      APITests: [],
       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'],
+      detailedJson: {},
       jsonValid: true,
     };
   },
   async mounted() {
-    const testJson = await APITestAPI.getAPITestInfosByProjectId(1);
-    console.log(testJson);
+    this.APITests = await APITestAPI.getAPITestInfosByProjectId(1);
   },
   methods: {
     async handleClick(action, id) {
@@ -181,15 +180,26 @@ export default {
           break;
         }
         case 'trigger': {
-          console.log('运行测试');
+          await APITestAPI.executeAPITestByTestId(id);
+          this.APITests = await APITestAPI.getAPITestInfosByProjectId(1);
           break;
         }
         case 'viewDetail': {
+          this.APITests.forEach((item) => {
+            if (item.testId === id) {
+              this.detailedJson = item;
+            }
+          });
           this.$refs.apiTestInfoForm.showForm();
           break;
         }
         case 'delete': {
-          console.log('删除测试任务');
+          await APITestAPI.deleteAPITestByTestId(id);
+          ElMessage.success({
+            message: '删除成功!',
+            type: 'success',
+          });
+          this.APITests = await APITestAPI.getAPITestInfosByProjectId(1);
           break;
         }
         default: {
@@ -211,12 +221,36 @@ 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: 1,
+            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(1);
           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}`;
+    },
   },
 };
 </script>