Sakiyary %!s(int64=3) %!d(string=hai) anos
pai
achega
9e4a3f593f

+ 330 - 6
frontend/package-lock.json

@@ -751,9 +751,9 @@
       }
     },
     "node_modules/@babel/parser": {
-      "version": "7.15.6",
-      "resolved": "https://registry.nlark.com/@babel/parser/download/@babel/parser-7.15.6.tgz?cache=0&sync_timestamp=1631216210940&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fparser%2Fdownload%2F%40babel%2Fparser-7.15.6.tgz",
-      "integrity": "sha1-BDuao8MDwHIuU3f++Rl/TPF5ZUk=",
+      "version": "7.19.1",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.1.tgz",
+      "integrity": "sha512-h7RCSorm1DdTVGJf3P2Mhj3kdnkmF/EiysUkzS2TdgAYqyjFdMQJbVuXOBej2SBJaXan/lIVtT6KkGbyyq753A==",
       "dev": true,
       "bin": {
         "parser": "bin/babel-parser.js"
@@ -2675,6 +2675,105 @@
         "node": ">=8"
       }
     },
+    "node_modules/@vue/compiler-core": {
+      "version": "3.2.39",
+      "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.39.tgz",
+      "integrity": "sha512-mf/36OWXqWn0wsC40nwRRGheR/qoID+lZXbIuLnr4/AngM0ov8Xvv8GHunC0rKRIkh60bTqydlqTeBo49rlbqw==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "@babel/parser": "^7.16.4",
+        "@vue/shared": "3.2.39",
+        "estree-walker": "^2.0.2",
+        "source-map": "^0.6.1"
+      }
+    },
+    "node_modules/@vue/compiler-core/node_modules/source-map": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+      "dev": true,
+      "peer": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/@vue/compiler-dom": {
+      "version": "3.2.39",
+      "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.39.tgz",
+      "integrity": "sha512-HMFI25Be1C8vLEEv1hgEO1dWwG9QQ8LTTPmCkblVJY/O3OvWx6r1+zsox5mKPMGvqYEZa6l8j+xgOfUspgo7hw==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "@vue/compiler-core": "3.2.39",
+        "@vue/shared": "3.2.39"
+      }
+    },
+    "node_modules/@vue/compiler-sfc": {
+      "version": "3.2.39",
+      "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.39.tgz",
+      "integrity": "sha512-fqAQgFs1/BxTUZkd0Vakn3teKUt//J3c420BgnYgEOoVdTwYpBTSXCMJ88GOBCylmUBbtquGPli9tVs7LzsWIA==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "@babel/parser": "^7.16.4",
+        "@vue/compiler-core": "3.2.39",
+        "@vue/compiler-dom": "3.2.39",
+        "@vue/compiler-ssr": "3.2.39",
+        "@vue/reactivity-transform": "3.2.39",
+        "@vue/shared": "3.2.39",
+        "estree-walker": "^2.0.2",
+        "magic-string": "^0.25.7",
+        "postcss": "^8.1.10",
+        "source-map": "^0.6.1"
+      }
+    },
+    "node_modules/@vue/compiler-sfc/node_modules/postcss": {
+      "version": "8.4.16",
+      "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz",
+      "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/postcss/"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/postcss"
+        }
+      ],
+      "peer": true,
+      "dependencies": {
+        "nanoid": "^3.3.4",
+        "picocolors": "^1.0.0",
+        "source-map-js": "^1.0.2"
+      },
+      "engines": {
+        "node": "^10 || ^12 || >=14"
+      }
+    },
+    "node_modules/@vue/compiler-sfc/node_modules/source-map": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+      "dev": true,
+      "peer": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/@vue/compiler-ssr": {
+      "version": "3.2.39",
+      "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.39.tgz",
+      "integrity": "sha512-EoGCJ6lincKOZGW+0Ky4WOKsSmqL7hp1ZYgen8M7u/mlvvEQUaO9tKKOy7K43M9U2aA3tPv0TuYYQFrEbK2eFQ==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "@vue/compiler-dom": "3.2.39",
+        "@vue/shared": "3.2.39"
+      }
+    },
     "node_modules/@vue/component-compiler-utils": {
       "version": "3.2.2",
       "resolved": "https://registry.nlark.com/@vue/component-compiler-utils/download/@vue/component-compiler-utils-3.2.2.tgz",
@@ -2738,6 +2837,27 @@
         "webpack": ">=4.0.0"
       }
     },
+    "node_modules/@vue/reactivity-transform": {
+      "version": "3.2.39",
+      "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.39.tgz",
+      "integrity": "sha512-HGuWu864zStiWs9wBC6JYOP1E00UjMdDWIG5W+FpUx28hV3uz9ODOKVNm/vdOy/Pvzg8+OcANxAVC85WFBbl3A==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "@babel/parser": "^7.16.4",
+        "@vue/compiler-core": "3.2.39",
+        "@vue/shared": "3.2.39",
+        "estree-walker": "^2.0.2",
+        "magic-string": "^0.25.7"
+      }
+    },
+    "node_modules/@vue/shared": {
+      "version": "3.2.39",
+      "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.39.tgz",
+      "integrity": "sha512-D3dl2ZB9qE6mTuWPk9RlhDeP1dgNRUKC3NJxji74A4yL8M2MwlhLKUC/49WHjrNzSPug58fWx/yFbaTzGAQSBw==",
+      "dev": true,
+      "peer": true
+    },
     "node_modules/@vue/web-component-wrapper": {
       "version": "1.3.0",
       "resolved": "https://registry.nlark.com/@vue/web-component-wrapper/download/@vue/web-component-wrapper-1.3.0.tgz",
@@ -6628,6 +6748,13 @@
         "node": ">=4.0"
       }
     },
+    "node_modules/estree-walker": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
+      "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
+      "dev": true,
+      "peer": true
+    },
     "node_modules/esutils": {
       "version": "2.0.3",
       "resolved": "https://registry.nlark.com/esutils/download/esutils-2.0.3.tgz",
@@ -9311,6 +9438,16 @@
         "yallist": "^3.0.2"
       }
     },
+    "node_modules/magic-string": {
+      "version": "0.25.9",
+      "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz",
+      "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "sourcemap-codec": "^1.4.8"
+      }
+    },
     "node_modules/make-dir": {
       "version": "3.1.0",
       "resolved": "https://registry.npm.taobao.org/make-dir/download/make-dir-3.1.0.tgz",
@@ -9714,6 +9851,19 @@
       "dev": true,
       "optional": true
     },
+    "node_modules/nanoid": {
+      "version": "3.3.4",
+      "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
+      "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==",
+      "dev": true,
+      "peer": true,
+      "bin": {
+        "nanoid": "bin/nanoid.cjs"
+      },
+      "engines": {
+        "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+      }
+    },
     "node_modules/nanomatch": {
       "version": "1.2.13",
       "resolved": "https://registry.nlark.com/nanomatch/download/nanomatch-1.2.13.tgz",
@@ -10619,6 +10769,13 @@
       "resolved": "https://registry.nlark.com/performance-now/download/performance-now-2.1.0.tgz",
       "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
     },
+    "node_modules/picocolors": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+      "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
+      "dev": true,
+      "peer": true
+    },
     "node_modules/picomatch": {
       "version": "2.3.0",
       "resolved": "https://registry.nlark.com/picomatch/download/picomatch-2.3.0.tgz?cache=0&sync_timestamp=1621648246651&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpicomatch%2Fdownload%2Fpicomatch-2.3.0.tgz",
@@ -12738,6 +12895,16 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/source-map-js": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
+      "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
+      "dev": true,
+      "peer": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
     "node_modules/source-map-resolve": {
       "version": "0.5.3",
       "resolved": "https://registry.nlark.com/source-map-resolve/download/source-map-resolve-0.5.3.tgz",
@@ -12776,6 +12943,13 @@
       "integrity": "sha1-CvZmBadFpaL5HPG7+KevvCg97FY=",
       "dev": true
     },
+    "node_modules/sourcemap-codec": {
+      "version": "1.4.8",
+      "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
+      "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
+      "dev": true,
+      "peer": true
+    },
     "node_modules/spdx-correct": {
       "version": "3.1.1",
       "resolved": "https://registry.npm.taobao.org/spdx-correct/download/spdx-correct-3.1.1.tgz",
@@ -16272,9 +16446,9 @@
       }
     },
     "@babel/parser": {
-      "version": "7.15.6",
-      "resolved": "https://registry.nlark.com/@babel/parser/download/@babel/parser-7.15.6.tgz?cache=0&sync_timestamp=1631216210940&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fparser%2Fdownload%2F%40babel%2Fparser-7.15.6.tgz",
-      "integrity": "sha1-BDuao8MDwHIuU3f++Rl/TPF5ZUk=",
+      "version": "7.19.1",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.1.tgz",
+      "integrity": "sha512-h7RCSorm1DdTVGJf3P2Mhj3kdnkmF/EiysUkzS2TdgAYqyjFdMQJbVuXOBej2SBJaXan/lIVtT6KkGbyyq753A==",
       "dev": true
     },
     "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": {
@@ -17717,6 +17891,90 @@
         }
       }
     },
+    "@vue/compiler-core": {
+      "version": "3.2.39",
+      "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.39.tgz",
+      "integrity": "sha512-mf/36OWXqWn0wsC40nwRRGheR/qoID+lZXbIuLnr4/AngM0ov8Xvv8GHunC0rKRIkh60bTqydlqTeBo49rlbqw==",
+      "dev": true,
+      "peer": true,
+      "requires": {
+        "@babel/parser": "^7.16.4",
+        "@vue/shared": "3.2.39",
+        "estree-walker": "^2.0.2",
+        "source-map": "^0.6.1"
+      },
+      "dependencies": {
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "dev": true,
+          "peer": true
+        }
+      }
+    },
+    "@vue/compiler-dom": {
+      "version": "3.2.39",
+      "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.39.tgz",
+      "integrity": "sha512-HMFI25Be1C8vLEEv1hgEO1dWwG9QQ8LTTPmCkblVJY/O3OvWx6r1+zsox5mKPMGvqYEZa6l8j+xgOfUspgo7hw==",
+      "dev": true,
+      "peer": true,
+      "requires": {
+        "@vue/compiler-core": "3.2.39",
+        "@vue/shared": "3.2.39"
+      }
+    },
+    "@vue/compiler-sfc": {
+      "version": "3.2.39",
+      "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.39.tgz",
+      "integrity": "sha512-fqAQgFs1/BxTUZkd0Vakn3teKUt//J3c420BgnYgEOoVdTwYpBTSXCMJ88GOBCylmUBbtquGPli9tVs7LzsWIA==",
+      "dev": true,
+      "peer": true,
+      "requires": {
+        "@babel/parser": "^7.16.4",
+        "@vue/compiler-core": "3.2.39",
+        "@vue/compiler-dom": "3.2.39",
+        "@vue/compiler-ssr": "3.2.39",
+        "@vue/reactivity-transform": "3.2.39",
+        "@vue/shared": "3.2.39",
+        "estree-walker": "^2.0.2",
+        "magic-string": "^0.25.7",
+        "postcss": "^8.1.10",
+        "source-map": "^0.6.1"
+      },
+      "dependencies": {
+        "postcss": {
+          "version": "8.4.16",
+          "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz",
+          "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==",
+          "dev": true,
+          "peer": true,
+          "requires": {
+            "nanoid": "^3.3.4",
+            "picocolors": "^1.0.0",
+            "source-map-js": "^1.0.2"
+          }
+        },
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "dev": true,
+          "peer": true
+        }
+      }
+    },
+    "@vue/compiler-ssr": {
+      "version": "3.2.39",
+      "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.39.tgz",
+      "integrity": "sha512-EoGCJ6lincKOZGW+0Ky4WOKsSmqL7hp1ZYgen8M7u/mlvvEQUaO9tKKOy7K43M9U2aA3tPv0TuYYQFrEbK2eFQ==",
+      "dev": true,
+      "peer": true,
+      "requires": {
+        "@vue/compiler-dom": "3.2.39",
+        "@vue/shared": "3.2.39"
+      }
+    },
     "@vue/component-compiler-utils": {
       "version": "3.2.2",
       "resolved": "https://registry.nlark.com/@vue/component-compiler-utils/download/@vue/component-compiler-utils-3.2.2.tgz",
@@ -17771,6 +18029,27 @@
       "dev": true,
       "requires": {}
     },
+    "@vue/reactivity-transform": {
+      "version": "3.2.39",
+      "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.39.tgz",
+      "integrity": "sha512-HGuWu864zStiWs9wBC6JYOP1E00UjMdDWIG5W+FpUx28hV3uz9ODOKVNm/vdOy/Pvzg8+OcANxAVC85WFBbl3A==",
+      "dev": true,
+      "peer": true,
+      "requires": {
+        "@babel/parser": "^7.16.4",
+        "@vue/compiler-core": "3.2.39",
+        "@vue/shared": "3.2.39",
+        "estree-walker": "^2.0.2",
+        "magic-string": "^0.25.7"
+      }
+    },
+    "@vue/shared": {
+      "version": "3.2.39",
+      "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.39.tgz",
+      "integrity": "sha512-D3dl2ZB9qE6mTuWPk9RlhDeP1dgNRUKC3NJxji74A4yL8M2MwlhLKUC/49WHjrNzSPug58fWx/yFbaTzGAQSBw==",
+      "dev": true,
+      "peer": true
+    },
     "@vue/web-component-wrapper": {
       "version": "1.3.0",
       "resolved": "https://registry.nlark.com/@vue/web-component-wrapper/download/@vue/web-component-wrapper-1.3.0.tgz",
@@ -21088,6 +21367,13 @@
       "integrity": "sha1-OYrT88WiSUi+dyXoPRGn3ijNvR0=",
       "dev": true
     },
+    "estree-walker": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
+      "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
+      "dev": true,
+      "peer": true
+    },
     "esutils": {
       "version": "2.0.3",
       "resolved": "https://registry.nlark.com/esutils/download/esutils-2.0.3.tgz",
@@ -23286,6 +23572,16 @@
         "yallist": "^3.0.2"
       }
     },
+    "magic-string": {
+      "version": "0.25.9",
+      "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz",
+      "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==",
+      "dev": true,
+      "peer": true,
+      "requires": {
+        "sourcemap-codec": "^1.4.8"
+      }
+    },
     "make-dir": {
       "version": "3.1.0",
       "resolved": "https://registry.npm.taobao.org/make-dir/download/make-dir-3.1.0.tgz",
@@ -23625,6 +23921,13 @@
       "dev": true,
       "optional": true
     },
+    "nanoid": {
+      "version": "3.3.4",
+      "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
+      "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==",
+      "dev": true,
+      "peer": true
+    },
     "nanomatch": {
       "version": "1.2.13",
       "resolved": "https://registry.nlark.com/nanomatch/download/nanomatch-1.2.13.tgz",
@@ -24379,6 +24682,13 @@
       "resolved": "https://registry.nlark.com/performance-now/download/performance-now-2.1.0.tgz",
       "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
     },
+    "picocolors": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+      "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
+      "dev": true,
+      "peer": true
+    },
     "picomatch": {
       "version": "2.3.0",
       "resolved": "https://registry.nlark.com/picomatch/download/picomatch-2.3.0.tgz?cache=0&sync_timestamp=1621648246651&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpicomatch%2Fdownload%2Fpicomatch-2.3.0.tgz",
@@ -26208,6 +26518,13 @@
       "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
       "dev": true
     },
+    "source-map-js": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
+      "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
+      "dev": true,
+      "peer": true
+    },
     "source-map-resolve": {
       "version": "0.5.3",
       "resolved": "https://registry.nlark.com/source-map-resolve/download/source-map-resolve-0.5.3.tgz",
@@ -26245,6 +26562,13 @@
       "integrity": "sha1-CvZmBadFpaL5HPG7+KevvCg97FY=",
       "dev": true
     },
+    "sourcemap-codec": {
+      "version": "1.4.8",
+      "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
+      "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
+      "dev": true,
+      "peer": true
+    },
     "spdx-correct": {
       "version": "3.1.1",
       "resolved": "https://registry.npm.taobao.org/spdx-correct/download/spdx-correct-3.1.1.tgz",

+ 2 - 2
frontend/src/util/request.js

@@ -1,5 +1,5 @@
-export const requestUrl = '127.0.0.1:'
-export const httpUrl = '127.0.0.1'
+export const requestUrl = 'http://106.15.1.178:8090/v1/'
+export const httpUrl = '??? IDK this usage'
 export default{
     requestUrl,
     httpUrl

+ 9 - 6
frontend/src/views/dynamic/Dynamic.vue

@@ -15,15 +15,18 @@
     
     <!-- <display /> -->
     <div id="button_group">
-      <el-button size="small" style="margin: 10px 5px 10px 0" @click="back_step"
-        >上一步</el-button
-      >
+      <el-button
+          size="small"
+          style="margin: 10px 5px 10px 0"
+          @click="back_step">
+        上一步
+      </el-button>
       <el-button
         size="small"
         style="margin: 10px 0 10px 5px"
-        @click="forward_step"
-        >下一步</el-button
-      >
+        @click="forward_step">
+        下一步
+      </el-button>
     </div>
   </el-card>
 </template>

+ 4 - 5
frontend/src/views/dynamic/components/analyze.vue

@@ -1,15 +1,14 @@
 <template>
   <div id="analyzeCard">
-      analyze
+    analyze
+    ??? IDK this usage
   </div>
 </template>
 
 <script>
 export default {
-    name: 'analyzer',
-    components: {
-        
-    }
+  name: 'analyzer',
+  components: {}
 }
 </script>
 

+ 2 - 2
frontend/src/views/dynamic/components/display.vue

@@ -1,7 +1,7 @@
 <template>
   <div id="dynamic-display">
-    <visualizer />
-    <analyzer />
+    <visualizer/>
+    <analyzer/>
   </div>
 </template>
 

+ 55 - 91
frontend/src/views/dynamic/components/uploadCard.vue

@@ -1,30 +1,14 @@
 <template>
   <el-form ref="dynamicForm" class="dynamic_uploader">
-    <el-form-item class="dynamic_form_item">
-      <el-select
-        class="action-selector"
-        v-model="actionValue"
-        filterable
-        placeholder="请选择运动类型"
-      >
-        <el-option
-          v-for="item in options"
-          :key="item.value"
-          :label="item.label"
-          :value="item.value"
-        >
-        </el-option>
-      </el-select>
-    </el-form-item>
     <el-form-item class="dynamic_form_item">
       <el-upload
-        class="video-uploader"
-        drag
-        :action="video_upload_url"
-        :auto-upload="false"
-        :file-list="fileList"
-        :data="{ filename: filename }"
-        :on-change="handleChange"
+          class="video-uploader"
+          drag
+          :action="video_upload_url"
+          :auto-upload="false"
+          :file-list="fileList"
+          :data="{ filename: filename }"
+          :on-change="handleChange"
       >
         <i class="el-icon-upload"></i>
         <div class="el-upload__text">
@@ -34,48 +18,17 @@
     </el-form-item>
     <el-form-item class="dynamic_form_item">
       <el-button
-        type="primary"
-        size="small"
-        style="margin-top: 10px"
-        @click="doSubmit"
-        >确认提交视频</el-button
+          type="primary"
+          size="small"
+          style="margin-top: 10px"
+          @click="doSubmit"
+      >确认提交视频
+      </el-button
       >
     </el-form-item>
   </el-form>
 </template>
 
-<style>
-.text {
-  font-size: 14px;
-}
-
-.dynamic_form_item {
-  display: flex;
-  justify-content: center;
-  align-items: center;
-}
-
-.clearfix:after {
-  clear: both;
-}
-
-/* .box-card {
-  width: 480px;
-} */
-.dynamic_uploader {
-  margin-top: 20px;
-  margin-left: 30%;
-  margin-right: 30%;
-  height: 330px;
-  /* text-align: center; */
-}
-
-.video-uploader {
-  margin-top: 10px;
-  /* width: 300px; */
-  margin: auto;
-}
-</style>
 <script>
 // import uploadForm from "./uploadForm.vue";
 import {requestUrl} from "@/util/request.js";
@@ -85,30 +38,8 @@ export default {
   name: "dynamic-uploader",
   data() {
     return {
-      options: [
-        {
-          value: "jump",
-          label: "立定跳远",
-        },
-        {
-          value: "juanfu",
-          label: "卷腹",
-        },
-        {
-          value: "pingban",
-          label: "平板支撑",
-        },
-        {
-          value: "gaotaitui",
-          label: "高抬腿",
-        },
-        {
-          value: "shendun",
-          label: "深蹲",
-        },
-      ],
-      actionValue: "",
-      video_upload_url: requestUrl + "get_videoid",
+
+      video_upload_url: requestUrl + "videos",
       fileList: [],
       filename: '',
     };
@@ -117,7 +48,7 @@ export default {
     // uploadForm,
   },
   methods: {
-    handleChange(file,fileList){
+    handleChange(file, fileList) {
       let _this = this;
       console.log(file)
       _this.fileList = fileList
@@ -127,15 +58,15 @@ export default {
     doSubmit() {
       let data = new FormData();
       // let _this = this;
-      data.append("mode", this.actionValue);
-      console.log(this.fileList[0])
-      data.append("video", this.fileList[0].raw);
-      console.log(requestUrl + "get_videoid");
-      axios.post(requestUrl + "get_videoid", data).then((response) => {
+      // data.append("mode", this.actionValue);
+      // console.log(this.fileList[0])
+      data.append("file", this.fileList[0].raw);
+      console.log(this.video_upload_url);
+      axios.post(this.video_upload_url, data).then((response) => {
         console.log(response)
         this.$message({
           showClose: true,
-          message: "您的视频分析ID为: " + response.data.id,
+          message: "您的视频分析ID为: " + response.data.uuid,
           type: 'success'
         });
       });
@@ -143,3 +74,36 @@ export default {
   },
 };
 </script>
+
+<style>
+.text {
+  font-size: 14px;
+}
+
+.dynamic_form_item {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+
+.clearfix:after {
+  clear: both;
+}
+
+/* .box-card {
+  width: 480px;
+} */
+.dynamic_uploader {
+  margin-top: 20px;
+  margin-left: 30%;
+  margin-right: 30%;
+  height: 330px;
+  /* text-align: center; */
+}
+
+.video-uploader {
+  margin-top: 10px;
+  /* width: 300px; */
+  margin: auto;
+}
+</style>

+ 132 - 65
frontend/src/views/dynamic/components/visualize.vue

@@ -1,18 +1,32 @@
 <template>
   <div id="video-container">
+    <el-select
+        class="action-selector"
+        v-model="actionValue"
+        filterable
+        placeholder="请选择运动类型"
+    >
+      <el-option
+          v-for="item in options"
+          :key="item.value"
+          :label="item.label"
+          :value="item.value"
+      >
+      </el-option>
+    </el-select>
     <el-input
-      id="video_search_bar"
-      placeholder="输入您的视频分析ID"
-      v-model="video_id"
-      style="width: 300px; margin-bottom: 20px"
+        id="video_search_bar"
+        placeholder="输入您的视频分析ID"
+        v-model="video_uuid"
+        style="width: 300px; margin-bottom: 20px"
     >
       <el-button
-        slot="suffix"
-        round
-        plain
-        @click="getVideoAnalysis"
-        size="small"
-        style="margin-top: 4px"
+          slot="suffix"
+          round
+          plain
+          @click="getVideoAnalysis"
+          size="small"
+          style="margin-top: 4px"
       >
         获取分析结果
       </el-button>
@@ -22,10 +36,10 @@
         <span>1. 运动3D还原</span>
       </div>
       <video
-        id="reconstructed_video"
-        controls
-        style="display: block; margin: auto; width: 1000px; height: 400px"
-        v-show="video_3d_analyze_status"
+          id="reconstructed_video"
+          controls
+          style="display: block; margin: auto; width: 1000px; height: 400px"
+          v-show="video_3d_analyze_status"
       ></video>
     </el-card>
     <el-card id="video_analyze" class="video_result">
@@ -34,8 +48,8 @@
       </div>
       <div class="video_analyze_content">
         <el-card
-          id="capability_container"
-          style="width: 100%; height: 300px; margin-right:20px"
+            id="capability_container"
+            style="width: 100%; height: 300px; margin-right:20px"
         >
           <span style="float: left">
             <i class="el-icon-data-analysis"></i>
@@ -43,26 +57,26 @@
             </span>
         </el-card>
         <el-card
-          id="advice_container"
-          style="width: 100%; height: 300px; margin: auto"
+            id="advice_container"
+            style="width: 100%; height: 300px; margin: auto"
         >
           <span style="display: block; text-align: left; margin-bottom: 6px"
-            >
+          >
             <i class="el-icon-s-order"></i>
             运动建议
             </span
-          >
+            >
           <div
-            id="advice"
-            v-show="show_advice"
-            style="
+              id="advice"
+              v-show="show_advice"
+              style="
               display: block;
               text-align: left;
               border-radius: 4px;
               height: 200px;
             "
           >
-          <i class="el-icon-s-order"></i>
+            <i class="el-icon-s-order"></i>
           </div>
         </el-card>
       </div>
@@ -71,33 +85,80 @@
 </template>
 
 <script>
-import { httpUrl, requestUrl } from "@/util/request.js";
+import {requestUrl} from "@/util/request.js";
 import axios from "axios";
 import DataSet from "@antv/data-set";
-import { Chart } from "@antv/g2";
+import {Chart} from "@antv/g2";
 
 export default {
   name: "visualizer",
   data() {
     return {
+      options: [
+        {
+          value: "VIDEO_HIGHKNEES",
+          label: "高抬腿",
+        },
+        {
+          value: "VIDEO_CRUNCH",
+          label: "卷腹",
+        },
+        {
+          value: "VIDEO_STANDINGLONGJUMP",
+          label: "立定跳远",
+        },
+        {
+          value: "VIDEO_MULTIJUMP",
+          label: "双脚连续跳",
+        },
+        {
+          value: "VIDEO_SITANDREACH",
+          label: "坐位体前屈",
+        },
+        {
+          value: "VIDEO_RUNBACKANDFORTH",
+          label: "十米往返跑",
+        },
+        {
+          value: "VIDEO_TENNISTHROW",
+          label: "网球掷远",
+        },
+        {
+          value: "VIDEO_BALANCEBEAM",
+          label: "走平衡木",
+        },
+        {
+          value: "VIDEO_SINGLELEGSTAND",
+          label: "单脚站立",
+        },
+        {
+          value: "VIDEO_PLANK",
+          label: "平板支撑",
+        },
+        {
+          value: "VIDEO_SQUAT",
+          label: "深蹲",
+        },
+      ],
+      actionValue: "",
       requestUrl: requestUrl,
-      httpUrl: httpUrl,
-      video_id: "",
+      video_uuid: "",
       analyzed_data: [
-        { item: "Design", a: 70 },
-        { item: "Development", a: 60 },
-        { item: "Marketing", a: 50 },
-        { item: "Users", a: 40 },
-        { item: "Test", a: 60 },
-        { item: "Language", a: 70 },
-        { item: "Technology", a: 50 },
-        { item: "Support", a: 30 },
-        { item: "Sales", a: 60 },
-        { item: "UX", a: 50 },
+        {item: "Design", a: 70},
+        {item: "Development", a: 60},
+        {item: "Marketing", a: 50},
+        {item: "Users", a: 40},
+        {item: "Test", a: 60},
+        {item: "Language", a: 70},
+        {item: "Technology", a: 50},
+        {item: "Support", a: 30},
+        {item: "Sales", a: 60},
+        {item: "UX", a: 50},
       ],
       video_3d_analyze_status: false,
       show_advice: false,
       advice: "",
+      result: ''
     };
   },
   mounted() {
@@ -105,7 +166,7 @@ export default {
   },
   methods: {
     draw_chart() {
-      const { DataView } = DataSet;
+      const {DataView} = DataSet;
       const dv = new DataView().source(this.analyzed_data);
       dv.transform({
         type: "fold",
@@ -166,26 +227,28 @@ export default {
 
       chart.line().position("item*score").color("user").size(1);
       chart
-        .point()
-        .position("item*score")
-        .color("user")
-        .shape("circle")
-        .size(4)
-        .style({
-          stroke: "#fff",
-          lineWidth: 1,
-          fillOpacity: 1,
-        });
+          .point()
+          .position("item*score")
+          .color("user")
+          .shape("circle")
+          .size(4)
+          .style({
+            stroke: "#fff",
+            lineWidth: 1,
+            fillOpacity: 1,
+          });
       chart.area().position("item*score").color("user");
       chart.render();
     },
     async getVideoAnalysis() {
-      let id = this.video_id;
+      let video_uuid = this.video_uuid;
       let _this = this;
-      let formData = new FormData();
-      formData.append("id", id);
+      let data = new FormData();
+      let type = this.actionValue;
+      let task_uuid = "";
+      data.append("video_uuid", video_uuid);
       // _this.draw_chart();
-      await axios.post(requestUrl + "query_3D", formData).then((response) => {
+      await axios.post(requestUrl + "analysis", type, data).then((response) => {
         const data = response.data;
         // _this.information = JSON.parse(data.data);
         //   // if (data.status == "processing") {
@@ -196,23 +259,25 @@ export default {
         //   //   _this.video_3d_analyze_status = false;
 
         //   // } else {
-        let video_obj = document.getElementById("reconstructed_video");
-        video_obj.src = data.url;
+        // let video_obj = document.getElementById("reconstructed_video");
+        // video_obj.src = data.url;
+        task_uuid = data["task_uuid"];
         _this.video_3d_analyze_status = true;
         // }
       });
       // _this.draw_chart();
       await axios
-        .post(requestUrl + "query_video", formData)
-        .then((response) => {
-          const data = response.data;
-          console.log(response.data);
-          _this.analyzed_data = data["analyzed_data"];
-          _this.draw_chart();
-          let ad_obj = document.getElementById("advice");
-          ad_obj.innerText = data["advice"];
-          _this.show_advice = true;
-        });
+          .post(requestUrl + "result" + task_uuid, data)
+          .then((response) => {
+            const data = response.data;
+            console.log(response.data);
+            _this.result = data["result"];
+            // _this.analyzed_data = data["analyzed_data"];
+            // _this.draw_chart();
+            // let ad_obj = document.getElementById("advice");
+            // ad_obj.innerText = data["advice"];
+            // _this.show_advice = true;
+          });
     },
   },
 };
@@ -228,11 +293,13 @@ export default {
   align-items: center;
   justify-content: center;
 }
+
 .video_analyze_content {
   display: flex;
   justify-content: center;
   align-items: center;
 }
+
 .video_result {
   /* width: 700px; */
   margin-bottom: 20px;

+ 8 - 5
frontend/src/views/static/Static.vue

@@ -23,7 +23,7 @@ import uploadCard from '@/views/static/components/upload/uploadCard.vue'
 import displayCard from '@/views/static/components/display/displayCard.vue'
 
 export default {
-  mounted(){
+  mounted() {
   },
   data() {
     return {
@@ -35,7 +35,7 @@ export default {
     uploadCard,
     displayCard
   },
-  methods:{
+  methods: {
     getInfor(id) {
       console.log(id)
       this.$refs.dCard.getInfor(id)
@@ -53,16 +53,19 @@ export default {
   color: #2c3e50;
   /* margin-top: 60px; */
 }
-#header{
+
+#header {
   margin-top: 1%;
   height: 10px;
 }
-#static-content{
+
+#static-content {
   display: grid;
   height: 500px;
   grid-template-columns: 1fr 1fr;
 }
-#footer{
+
+#footer {
   margin-top: 20px;
   padding-top: 30px;
 }

+ 109 - 87
frontend/src/views/static/components/display/displayCard.vue

@@ -4,26 +4,26 @@
       <span>姿势矫正分析</span>
     </div>
     <el-input
-      id="search_bar"
-      placeholder="输入您的图片分析ID"
-      v-model="correction_id"
-      style="width: 250px"
+        id="search_bar"
+        placeholder="输入您的图片分析ID"
+        v-model="photo_uuid"
+        style="width: 250px"
     >
       <el-button
-        slot="suffix"
-        icon="el-icon-search"
-        circle
-        @click="getAnalysis"
-        size="small"
-        style="margin-top:4px"
+          slot="suffix"
+          icon="el-icon-search"
+          circle
+          @click="getAnalysis"
+          size="small"
+          style="margin-top:4px"
       ></el-button>
     </el-input>
     <div id="corrected-image-container">
       <div class="corrected-image-group">
         <el-image
-          :src="images['front-correction']"
-          class="corrected-image"
-          id="front-correction"
+            :src="images['front-correction']"
+            class="corrected-image"
+            id="front-correction"
         >
           <div slot="placeholder" class="image-slot">
             图片正在分析中...
@@ -31,20 +31,21 @@
         </el-image>
         <div class="corrected-text-group">
           <el-button
-            size="small"
-            type="primary"
-            icon="el-icon-download"
-            class="correction-download"
-            @click="downloadImage('front-correction')"
-            >下载</el-button
+              size="small"
+              type="primary"
+              icon="el-icon-download"
+              class="correction-download"
+              @click="downloadImage('front-correction')"
+          >下载
+          </el-button
           >
         </div>
       </div>
       <div class="corrected-image-group" style="margin-left: 3%">
         <el-image
-          :src="images['right-correction']"
-          class="corrected-image"
-          id="right-correction"
+            :src="images['right-correction']"
+            class="corrected-image"
+            id="right-correction"
         >
           <div slot="placeholder" class="image-slot">
             图片正在分析中...
@@ -52,12 +53,13 @@
         </el-image>
         <div class="corrected-text-group">
           <el-button
-            size="small"
-            type="primary"
-            icon="el-icon-download"
-            class="correction-download"
-            @click="downloadImage('right-correction')"
-            >下载</el-button
+              size="small"
+              type="primary"
+              icon="el-icon-download"
+              class="correction-download"
+              @click="downloadImage('right-correction')"
+          >下载
+          </el-button
           >
         </div>
       </div>
@@ -80,17 +82,17 @@
       <div v-for="item in information" :key="item.index" class="text-item">
         <div class="item-title">{{ item.title }}</div>
         <div
-          v-for="detail in item.detail"
-          :key="detail.index"
-          class="detail-item"
-          :style="{ 'margin-top': '3%' }"
+            v-for="detail in item.detail"
+            :key="detail.index"
+            class="detail-item"
+            :style="{ 'margin-top': '3%' }"
         >
           <div>
             {{ detail.name }}
           </div>
           <div
-            class="detail-value"
-            :style="{
+              class="detail-value"
+              :style="{
               'background-color': level_color[detail.level],
               color: 'white',
               'border-radius': '2px',
@@ -105,6 +107,66 @@
   </el-card>
 </template>
 
+<script>
+import axios from "axios";
+import {requestUrl} from '@/util/request.js'
+
+export default {
+  mounted() {
+  },
+  data() {
+    return {
+      information: [],
+      images: {
+        "front-correction": "",
+        "right-correction": "",
+      },
+      level_color: ["#67C23A", "#CDDC39", "#E6A23C", "#F56C6C"],
+      photo_uuid: "",
+      result: '',
+    };
+  },
+  props: {},
+  methods: {
+    getInfor(id) {
+      console.log(id)
+      this.photo_uuid = id;
+    },
+    getAnalysis() {
+      let right_id = this.photo_uuid;
+      let front_id = this.photo_uuid;
+      let height_id = this.photo_uuid;
+      let _this = this;
+      let formData = new FormData();
+      let type = 'PHOTO_STANDPOSE';
+      formData.append("right", right_id);
+      formData.append("front", front_id);
+      formData.append("height", height_id);
+      axios
+          .post(requestUrl + "analysis", type, formData)
+          .then((response) => {
+            // const data = response.data;
+            _this.result = response.data.result;
+            // _this.information = JSON.parse(data.data);
+            // _this.images["front-correction"] =
+            //     "data:image/png;base64," + data.front;
+            // _this.images["right-correction"] =
+            //     "data:image/png;base64," + data.right;
+            // console.log(_this.information);
+          });
+    },
+    downloadImage(name) {
+      // let _this  = this;
+      const url = this.images[name];
+      let a = document.createElement("a");
+      a.download = "";
+      a.href = url;
+      a.click();
+    },
+  },
+};
+</script>
+
 <style>
 .text {
   font-size: 14px;
@@ -127,17 +189,20 @@
   align-items: center;
   margin-bottom: 5%;
 }
+
 .box-card {
   margin-left: 10%;
   margin-right: 10%;
-  height: 520px;
-  overflow: auto;
+  height: 600px;
+  /*overflow: auto;*/
 }
+
 #level-desc {
   display: flex;
   justify-content: baseline;
   align-items: center;
 }
+
 .level-item {
   color: white;
   margin-left: 3%;
@@ -145,6 +210,7 @@
   font-size: 14px;
   padding: 2px 4px 2px 4px;
 }
+
 #corrected-image-container {
   display: flex;
   justify-content: center;
@@ -153,19 +219,23 @@
   border-radius: 5px;
   margin-bottom: 5%;
 }
+
 .corrected-image-group {
   width: 45%;
   text-align: center;
   padding: 8px 10px 5px 10px;
 }
+
 .corrected-image {
   height: 200px;
   text-align: center;
   width: 100%;
 }
+
 .corrected-text-group {
   text-align: center;
 }
+
 /* .corrected-text-group .correction-download {
   float: right;
 } */
@@ -175,10 +245,12 @@
   border: 1px solid lightblue;
   border-radius: 5px;
 }
+
 .text-item {
   margin-bottom: 10px;
   padding: 5px 8px 5px 5px;
 }
+
 .item-title {
   display: block;
   margin-bottom: 8px;
@@ -189,54 +261,4 @@
   display: grid;
   grid-template-columns: 1fr 3fr;
 }
-</style>
-<script>
-import axios from "axios";
-import {requestUrl} from '@/util/request.js'
-export default {
-  mounted() {},
-  data() {
-    return {
-      information: [],
-      images: {
-        "front-correction": "",
-        "right-correction": "",
-      },
-      level_color: ["#67C23A", "#CDDC39", "#E6A23C", "#F56C6C"],
-      correction_id: "",
-    };
-  },
-  props: {},
-  methods: {
-    getInfor(id){
-      console.log(id)
-      this.correction_id = id;
-    },
-    getAnalysis() {
-      let id = this.correction_id;
-      let _this = this;
-      let formData = new FormData();
-      formData.append("id", id);
-      axios
-        .post(requestUrl+"/get_result", formData)
-        .then((response) => {
-          const data = response.data;
-          _this.information = JSON.parse(data.data);
-          _this.images["front-correction"] =
-            "data:image/png;base64," + data.front;
-          _this.images["right-correction"] =
-            "data:image/png;base64," + data.right;
-          console.log(_this.information);
-        });
-    },
-    downloadImage(name) {
-      // let _this  = this;
-      const url = this.images[name];
-      let a = document.createElement("a");
-      a.download = "";
-      a.href = url;
-      a.click();
-    },
-  },
-};
-</script>
+</style>

+ 32 - 30
frontend/src/views/static/components/upload/uploadCard.vue

@@ -7,13 +7,39 @@
     <div id="upload-rules">
       <p style="color:deepskyblue;font-weight: bold; font-size: 14px">上传规则</p>
       <div v-for="item in rules" :key="item.index" class="rule">
-        <div>{{item.index}}. {{item.content}}</div>
+        <div>{{ item.index }}. {{ item.content }}</div>
       </div>
     </div>
   </el-card>
 </template>
 
-<style>
+<script>
+import uploadForm from "./uploadForm.vue";
+
+export default {
+  name: "uploadCard",
+  data() {
+    return {
+      rules: [
+        {"index": 1, "content": "图片必须是.png或者.jpg的格式。"},
+        {"index": 2, "content": "图片名称必须是front/right.png。"},
+        {"index": 3, "content": "身高的单位为厘米。"},
+        {"index": 4, "content": "一次只能上传一个人的两张姿势图片(包括正面和侧面)。"}
+      ],
+    };
+  },
+  components: {
+    uploadForm,
+  },
+  methods: {
+    infor(id) {
+      this.$emit("infor", id)
+    }
+  },
+};
+</script>
+
+<style scoped>
 .text {
   font-size: 14px;
 }
@@ -32,37 +58,13 @@
 .box-card {
   margin-left: 10%;
   margin-right: 10%;
-  height: 520px;
+  height: 600px;
   /* text-align: center; */
 }
-#upload-rules{
+
+#upload-rules {
   position: relative;
   text-align: left;
   width: 500px;
 }
-</style>
-<script>
-import uploadForm from "./uploadForm.vue";
-
-export default {
-  name: "uploadCard",
-  data() {
-    return {
-      rules: [
-        {"index":1,"content":"图片必须是.png或者.jpg的格式。"},
-        {"index":2,"content":"图片名称必须是front/right.png。"},
-        {"index":3,"content":"身高的单位为厘米。"},
-        {"index":4,"content":"一次只能上传一个人的两张姿势图片(包括正面和侧面)。"}
-      ],
-    };
-  },
-  components: {
-    uploadForm,
-  },
-  methods: {
-    infor(id) {
-      this.$emit("infor",id)
-    }
-  },
-};
-</script>
+</style>

+ 60 - 51
frontend/src/views/static/components/upload/uploadForm.vue

@@ -2,80 +2,66 @@
   <el-form ref="form" :model="form" label-width="120px">
     <div id="form-content">
       <el-form-item label="站姿图片" class="image-container">
-        <imageUpload @fileList="getFileList" />
+        <imageUpload @fileList="getFileList"/>
       </el-form-item>
 
       <el-form-item label="身高" id="height">
         <el-input
-          type="text"
-          placeholder="请输入您的身高: (单位:厘米)"
-          autocomplete="off"
-          v-model="form.height"
-          size="small"
-          @input="getHeight"
+            type="text"
+            placeholder="请输入您的身高: (单位:厘米)"
+            autocomplete="off"
+            v-model="form.height"
+            size="small"
+            @input="getHeight"
         ></el-input>
       </el-form-item>
     </div>
     <el-form-item id="form-button-group">
       <el-button
-        class="form-button"
-        type="primary"
-        size="small"
-        @click="onSubmit"
-        >上传</el-button
+          class="form-button"
+          type="primary"
+          size="small"
+          @click="onSubmit"
+      >上传
+      </el-button
       >
       <el-button class="form-button" disabled size="small">取消</el-button>
     </el-form-item>
     <el-dialog
-      title="提示"
-      :visible.sync="dialogVisible"
-      width="30%"
-      :before-close="handleClose"
+        title="提示"
+        :visible.sync="dialogVisible"
+        width="30%"
+        :before-close="handleClose"
     >
-      <span>您的姿势分析 ID is {{ correction_id }}.</span>
+      <span>您的姿势分析 ID is {{ photo_uuid }}.</span>
       <span slot="footer" class="dialog-footer">
         <!-- <el-button @click="dialogVisible = false">Cancel</el-button> -->
         <el-button type="primary" @click="dialogVisible = false"
-          >确认</el-button
+        >确认</el-button
         >
       </span>
     </el-dialog>
   </el-form>
 </template>
-<style scoped>
-#form-content {
-  border: 1px solid lightgrey;
-  padding: 10px 10px 10px 10px;
-  border-radius: 5px;
-}
-.image-container {
-  display: flex;
-  /* align-items: center; */
-  justify-content: center;
-  height: 6rem;
-}
-#form-button-group {
-  margin-top: 5%;
-  margin-left: 50%;
-  /* margin-right: -5em; */
-  /* padding-right: -10px; */
-}
-</style>
+
 <script>
 import imageUpload from "./imageUpload.vue";
 import axios from "axios";
-import { requestUrl } from "@/util/request.js";
+import {requestUrl} from "@/util/request.js";
+
 export default {
-  mounted() {},
+  mounted() {
+  },
   data() {
     return {
       form: {
         fileList: [],
-        poseList: [{ name: "front" }, { name: "side" }],
+        poseList: [{name: "front"}, {name: "side"}],
         displayFlag: false,
       },
       dialogVisible: false,
-      correction_id: 0,
+      photo_uuid: 0,
+      file: '',
     };
   },
   components: {
@@ -91,18 +77,19 @@ export default {
     onSubmit() {
       // let _this = this;
       let data = new FormData();
-      data.append("height", this.height);
-      Object.entries(this.form.fileList).forEach((file) => {
-        data.append("images" + file[1].name, file[1].raw);
-      });
-      axios.post(requestUrl + "send_form", data).then((response) => {
-        this.correction_id = response.data.id;
+      data.append("file", this.file.raw)
+      // data.append("height", this.height);
+      // Object.entries(this.form.fileList).forEach((file) => {
+      //   data.append("images" + file[1].name, file[1].raw);
+      // });
+      axios.post(requestUrl + "photos", data).then((response) => {
+        this.photo_uuid = response.data.uuid;
         // this.dialogVisible = true;
-        console.log(response.data.id);
-        this.$emit("infor", response.data.id);
+        console.log(response.data.uuid);
+        this.$emit("infor", response.data.uuid);
         this.$message({
           showClose: true,
-          message: "您的图片分析ID为: " + response.data.id,
+          message: "您的图片分析ID为: " + response.data.uuid,
           type: "success",
         });
       });
@@ -112,4 +99,26 @@ export default {
     },
   },
 };
-</script>
+</script>
+
+<style scoped>
+#form-content {
+  border: 1px solid lightgrey;
+  padding: 10px 10px 10px 10px;
+  border-radius: 5px;
+}
+
+.image-container {
+  display: flex;
+  /* align-items: center; */
+  justify-content: center;
+  height: 6rem;
+}
+
+#form-button-group {
+  margin-top: 5%;
+  margin-left: 50%;
+  /* margin-right: -5em; */
+  /* padding-right: -10px; */
+}
+</style>