瀏覽代碼

提交代码3

pqy 5 月之前
父節點
當前提交
a6ceba5c1a
共有 34 個文件被更改,包括 821 次插入197 次删除
  1. 13 0
      .hintrc
  2. 147 84
      package-lock.json
  3. 6 2
      package.json
  4. 23 0
      proxy.js
  5. 2 1
      src/app/app.module.ts
  6. 8 6
      src/app/ceramic-details/ceramic-details.page.html
  7. 85 26
      src/app/ceramic-details/ceramic-details.page.scss
  8. 2 1
      src/app/tab1/tab1.module.ts
  9. 35 0
      src/app/tab1/tab1.page.html
  10. 163 4
      src/app/tab1/tab1.page.scss
  11. 192 28
      src/app/tab1/tab1.page.ts
  12. 11 7
      src/app/tab3/tab3.page.html
  13. 40 1
      src/app/tab3/tab3.page.scss
  14. 62 14
      src/app/tab3/tab3.page.ts
  15. 二進制
      src/assets/images/Ceramics/daimaoyouzhan.jpg
  16. 二進制
      src/assets/images/Ceramics/fengwenzhan.jpg
  17. 二進制
      src/assets/images/Ceramics/heiyouhan.jpg
  18. 二進制
      src/assets/images/Ceramics/jianzhitiehuazhan.jpg
  19. 二進制
      src/assets/images/Ceramics/meiping.jpg
  20. 二進制
      src/assets/images/Ceramics/meiwenzhan.jpg
  21. 二進制
      src/assets/images/Ceramics/muyetianmuzhan.jpg
  22. 二進制
      src/assets/images/Ceramics/tuhaozhan.jpg
  23. 二進制
      src/assets/images/Ceramics/zhegubanzhan.jpg
  24. 二進制
      src/assets/images/KG-background.png
  25. 二進制
      src/assets/images/ceramics-background.png
  26. 二進制
      src/assets/images/details-background.png
  27. 0 0
      src/assets/images/recognition-background1.png
  28. 二進制
      src/assets/images/recognition-background2.png
  29. 二進制
      src/assets/images/slide1.jpg
  30. 二進制
      src/assets/images/slide2.jpg
  31. 二進制
      src/assets/images/slide3.jpg
  32. 二進制
      src/assets/images/slide4.jpg
  33. 31 0
      src/assets/json/graph.json
  34. 1 23
      src/global.scss

+ 13 - 0
.hintrc

@@ -0,0 +1,13 @@
+{
+  "extends": [
+    "development"
+  ],
+  "hints": {
+    "axe/text-alternatives": [
+      "default",
+      {
+        "image-alt": "off"
+      }
+    ]
+  }
+}

+ 147 - 84
package-lock.json

@@ -21,12 +21,16 @@
         "@capacitor/haptics": "6.0.2",
         "@capacitor/haptics": "6.0.2",
         "@capacitor/keyboard": "6.0.3",
         "@capacitor/keyboard": "6.0.3",
         "@capacitor/status-bar": "6.0.2",
         "@capacitor/status-bar": "6.0.2",
-        "@ionic/angular": "^8.0.0",
-        "axios": "^1.7.8",
+        "@ionic/angular": "^8.4.1",
+        "axios": "^1.7.9",
+        "cors": "^2.8.5",
+        "express": "^4.21.2",
         "fmode-ng": "^0.0.62",
         "fmode-ng": "^0.0.62",
         "ionicons": "^7.0.0",
         "ionicons": "^7.0.0",
         "rxjs": "~7.8.0",
         "rxjs": "~7.8.0",
+        "swiper": "^8.4.7",
         "tslib": "^2.3.0",
         "tslib": "^2.3.0",
+        "vis-network": "^9.1.9",
         "zone.js": "~0.14.2"
         "zone.js": "~0.14.2"
       },
       },
       "devDependencies": {
       "devDependencies": {
@@ -3040,6 +3044,19 @@
         "node": ">=14.17.0"
         "node": ">=14.17.0"
       }
       }
     },
     },
+    "node_modules/@egjs/hammerjs": {
+      "version": "2.0.17",
+      "resolved": "https://registry.npmmirror.com/@egjs/hammerjs/-/hammerjs-2.0.17.tgz",
+      "integrity": "sha512-XQsZgjm2EcVUiZQf11UBJQfmZeEmOW8DpI1gsFeln6w0ae0ii4dMQEQ0kjl6DspdWX1aGY1/loyXnP0JS06e/A==",
+      "license": "MIT",
+      "peer": true,
+      "dependencies": {
+        "@types/hammerjs": "^2.0.36"
+      },
+      "engines": {
+        "node": ">=0.8.0"
+      }
+    },
     "node_modules/@es-joy/jsdoccomment": {
     "node_modules/@es-joy/jsdoccomment": {
       "version": "0.46.0",
       "version": "0.46.0",
       "resolved": "https://registry.npmmirror.com/@es-joy/jsdoccomment/-/jsdoccomment-0.46.0.tgz",
       "resolved": "https://registry.npmmirror.com/@es-joy/jsdoccomment/-/jsdoccomment-0.46.0.tgz",
@@ -5951,6 +5968,13 @@
         "@types/node": "*"
         "@types/node": "*"
       }
       }
     },
     },
+    "node_modules/@types/hammerjs": {
+      "version": "2.0.46",
+      "resolved": "https://registry.npmmirror.com/@types/hammerjs/-/hammerjs-2.0.46.tgz",
+      "integrity": "sha512-ynRvcq6wvqexJ9brDMS4BnBLzmr0e14d6ZJTEShTBWKymQiHwlAyGu0ZPEFI2Fh1U53F7tN9ufClWM5KvqkKOw==",
+      "license": "MIT",
+      "peer": true
+    },
     "node_modules/@types/http-errors": {
     "node_modules/@types/http-errors": {
       "version": "2.0.4",
       "version": "2.0.4",
       "resolved": "https://registry.npmmirror.com/@types/http-errors/-/http-errors-2.0.4.tgz",
       "resolved": "https://registry.npmmirror.com/@types/http-errors/-/http-errors-2.0.4.tgz",
@@ -6824,7 +6848,6 @@
       "version": "1.3.8",
       "version": "1.3.8",
       "resolved": "https://registry.npmmirror.com/accepts/-/accepts-1.3.8.tgz",
       "resolved": "https://registry.npmmirror.com/accepts/-/accepts-1.3.8.tgz",
       "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
       "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "dependencies": {
       "dependencies": {
         "mime-types": "~2.1.34",
         "mime-types": "~2.1.34",
@@ -6838,7 +6861,6 @@
       "version": "0.6.3",
       "version": "0.6.3",
       "resolved": "https://registry.npmmirror.com/negotiator/-/negotiator-0.6.3.tgz",
       "resolved": "https://registry.npmmirror.com/negotiator/-/negotiator-0.6.3.tgz",
       "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
       "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "engines": {
       "engines": {
         "node": ">= 0.6"
         "node": ">= 0.6"
@@ -7118,7 +7140,6 @@
       "version": "1.1.1",
       "version": "1.1.1",
       "resolved": "https://registry.npmmirror.com/array-flatten/-/array-flatten-1.1.1.tgz",
       "resolved": "https://registry.npmmirror.com/array-flatten/-/array-flatten-1.1.1.tgz",
       "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
       "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
-      "dev": true,
       "license": "MIT"
       "license": "MIT"
     },
     },
     "node_modules/array-includes": {
     "node_modules/array-includes": {
@@ -7315,9 +7336,9 @@
       }
       }
     },
     },
     "node_modules/axios": {
     "node_modules/axios": {
-      "version": "1.7.8",
-      "resolved": "https://registry.npmmirror.com/axios/-/axios-1.7.8.tgz",
-      "integrity": "sha512-Uu0wb7KNqK2t5K+YQyVCLM76prD5sRFjKHbJYCP1J7JFGEQ6nN7HWn9+04LAeiJ3ji54lgS/gZCH1oxyrf1SPw==",
+      "version": "1.7.9",
+      "resolved": "https://registry.npmmirror.com/axios/-/axios-1.7.9.tgz",
+      "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==",
       "license": "MIT",
       "license": "MIT",
       "dependencies": {
       "dependencies": {
         "follow-redirects": "^1.15.6",
         "follow-redirects": "^1.15.6",
@@ -7524,7 +7545,6 @@
       "version": "1.20.3",
       "version": "1.20.3",
       "resolved": "https://registry.npmmirror.com/body-parser/-/body-parser-1.20.3.tgz",
       "resolved": "https://registry.npmmirror.com/body-parser/-/body-parser-1.20.3.tgz",
       "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==",
       "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "dependencies": {
       "dependencies": {
         "bytes": "3.1.2",
         "bytes": "3.1.2",
@@ -7549,7 +7569,6 @@
       "version": "2.6.9",
       "version": "2.6.9",
       "resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz",
       "resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz",
       "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
       "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "dependencies": {
       "dependencies": {
         "ms": "2.0.0"
         "ms": "2.0.0"
@@ -7559,7 +7578,6 @@
       "version": "2.0.0",
       "version": "2.0.0",
       "resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz",
       "resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz",
       "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
       "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
-      "dev": true,
       "license": "MIT"
       "license": "MIT"
     },
     },
     "node_modules/bonjour-service": {
     "node_modules/bonjour-service": {
@@ -7711,7 +7729,6 @@
       "version": "3.1.2",
       "version": "3.1.2",
       "resolved": "https://registry.npmmirror.com/bytes/-/bytes-3.1.2.tgz",
       "resolved": "https://registry.npmmirror.com/bytes/-/bytes-3.1.2.tgz",
       "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
       "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "engines": {
       "engines": {
         "node": ">= 0.8"
         "node": ">= 0.8"
@@ -7796,7 +7813,6 @@
       "version": "1.0.7",
       "version": "1.0.7",
       "resolved": "https://registry.npmmirror.com/call-bind/-/call-bind-1.0.7.tgz",
       "resolved": "https://registry.npmmirror.com/call-bind/-/call-bind-1.0.7.tgz",
       "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
       "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "dependencies": {
       "dependencies": {
         "es-define-property": "^1.0.0",
         "es-define-property": "^1.0.0",
@@ -8185,6 +8201,16 @@
       "dev": true,
       "dev": true,
       "license": "ISC"
       "license": "ISC"
     },
     },
+    "node_modules/component-emitter": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmmirror.com/component-emitter/-/component-emitter-1.3.1.tgz",
+      "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==",
+      "license": "MIT",
+      "peer": true,
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/compressible": {
     "node_modules/compressible": {
       "version": "2.0.18",
       "version": "2.0.18",
       "resolved": "https://registry.npmmirror.com/compressible/-/compressible-2.0.18.tgz",
       "resolved": "https://registry.npmmirror.com/compressible/-/compressible-2.0.18.tgz",
@@ -8288,7 +8314,6 @@
       "version": "0.5.4",
       "version": "0.5.4",
       "resolved": "https://registry.npmmirror.com/content-disposition/-/content-disposition-0.5.4.tgz",
       "resolved": "https://registry.npmmirror.com/content-disposition/-/content-disposition-0.5.4.tgz",
       "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
       "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "dependencies": {
       "dependencies": {
         "safe-buffer": "5.2.1"
         "safe-buffer": "5.2.1"
@@ -8301,7 +8326,6 @@
       "version": "1.0.5",
       "version": "1.0.5",
       "resolved": "https://registry.npmmirror.com/content-type/-/content-type-1.0.5.tgz",
       "resolved": "https://registry.npmmirror.com/content-type/-/content-type-1.0.5.tgz",
       "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
       "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "engines": {
       "engines": {
         "node": ">= 0.6"
         "node": ">= 0.6"
@@ -8328,7 +8352,6 @@
       "version": "1.0.6",
       "version": "1.0.6",
       "resolved": "https://registry.npmmirror.com/cookie-signature/-/cookie-signature-1.0.6.tgz",
       "resolved": "https://registry.npmmirror.com/cookie-signature/-/cookie-signature-1.0.6.tgz",
       "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
       "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
-      "dev": true,
       "license": "MIT"
       "license": "MIT"
     },
     },
     "node_modules/copy-anything": {
     "node_modules/copy-anything": {
@@ -8472,7 +8495,6 @@
       "version": "2.8.5",
       "version": "2.8.5",
       "resolved": "https://registry.npmmirror.com/cors/-/cors-2.8.5.tgz",
       "resolved": "https://registry.npmmirror.com/cors/-/cors-2.8.5.tgz",
       "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
       "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "dependencies": {
       "dependencies": {
         "object-assign": "^4",
         "object-assign": "^4",
@@ -8809,7 +8831,6 @@
       "version": "1.1.4",
       "version": "1.1.4",
       "resolved": "https://registry.npmmirror.com/define-data-property/-/define-data-property-1.1.4.tgz",
       "resolved": "https://registry.npmmirror.com/define-data-property/-/define-data-property-1.1.4.tgz",
       "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
       "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "dependencies": {
       "dependencies": {
         "es-define-property": "^1.0.0",
         "es-define-property": "^1.0.0",
@@ -8867,7 +8888,6 @@
       "version": "2.0.0",
       "version": "2.0.0",
       "resolved": "https://registry.npmmirror.com/depd/-/depd-2.0.0.tgz",
       "resolved": "https://registry.npmmirror.com/depd/-/depd-2.0.0.tgz",
       "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
       "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "engines": {
       "engines": {
         "node": ">= 0.8"
         "node": ">= 0.8"
@@ -8877,7 +8897,6 @@
       "version": "1.2.0",
       "version": "1.2.0",
       "resolved": "https://registry.npmmirror.com/destroy/-/destroy-1.2.0.tgz",
       "resolved": "https://registry.npmmirror.com/destroy/-/destroy-1.2.0.tgz",
       "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
       "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "engines": {
       "engines": {
         "node": ">= 0.8",
         "node": ">= 0.8",
@@ -8982,6 +9001,15 @@
         "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
         "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
       }
       }
     },
     },
+    "node_modules/dom7": {
+      "version": "4.0.6",
+      "resolved": "https://registry.npmmirror.com/dom7/-/dom7-4.0.6.tgz",
+      "integrity": "sha512-emjdpPLhpNubapLFdjNL9tP06Sr+GZkrIHEXLWvOGsytACUrkbeIdjO5g77m00BrHTznnlcNqgmn7pCN192TBA==",
+      "license": "MIT",
+      "dependencies": {
+        "ssr-window": "^4.0.0"
+      }
+    },
     "node_modules/domelementtype": {
     "node_modules/domelementtype": {
       "version": "2.3.0",
       "version": "2.3.0",
       "resolved": "https://registry.npmmirror.com/domelementtype/-/domelementtype-2.3.0.tgz",
       "resolved": "https://registry.npmmirror.com/domelementtype/-/domelementtype-2.3.0.tgz",
@@ -9037,7 +9065,6 @@
       "version": "1.1.1",
       "version": "1.1.1",
       "resolved": "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz",
       "resolved": "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz",
       "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
       "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
-      "dev": true,
       "license": "MIT"
       "license": "MIT"
     },
     },
     "node_modules/electron-to-chromium": {
     "node_modules/electron-to-chromium": {
@@ -9088,7 +9115,6 @@
       "version": "1.0.2",
       "version": "1.0.2",
       "resolved": "https://registry.npmmirror.com/encodeurl/-/encodeurl-1.0.2.tgz",
       "resolved": "https://registry.npmmirror.com/encodeurl/-/encodeurl-1.0.2.tgz",
       "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
       "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "engines": {
       "engines": {
         "node": ">= 0.8"
         "node": ">= 0.8"
@@ -9309,7 +9335,6 @@
       "version": "1.0.0",
       "version": "1.0.0",
       "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.0.tgz",
       "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.0.tgz",
       "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
       "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "dependencies": {
       "dependencies": {
         "get-intrinsic": "^1.2.4"
         "get-intrinsic": "^1.2.4"
@@ -9322,7 +9347,6 @@
       "version": "1.3.0",
       "version": "1.3.0",
       "resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz",
       "resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz",
       "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
       "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "engines": {
       "engines": {
         "node": ">= 0.4"
         "node": ">= 0.4"
@@ -9458,7 +9482,6 @@
       "version": "1.0.3",
       "version": "1.0.3",
       "resolved": "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz",
       "resolved": "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz",
       "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
       "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
-      "dev": true,
       "license": "MIT"
       "license": "MIT"
     },
     },
     "node_modules/escape-string-regexp": {
     "node_modules/escape-string-regexp": {
@@ -9979,7 +10002,6 @@
       "version": "1.8.1",
       "version": "1.8.1",
       "resolved": "https://registry.npmmirror.com/etag/-/etag-1.8.1.tgz",
       "resolved": "https://registry.npmmirror.com/etag/-/etag-1.8.1.tgz",
       "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
       "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "engines": {
       "engines": {
         "node": ">= 0.6"
         "node": ">= 0.6"
@@ -10056,10 +10078,9 @@
       "license": "Apache-2.0"
       "license": "Apache-2.0"
     },
     },
     "node_modules/express": {
     "node_modules/express": {
-      "version": "4.21.1",
-      "resolved": "https://registry.npmmirror.com/express/-/express-4.21.1.tgz",
-      "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==",
-      "dev": true,
+      "version": "4.21.2",
+      "resolved": "https://registry.npmmirror.com/express/-/express-4.21.2.tgz",
+      "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==",
       "license": "MIT",
       "license": "MIT",
       "dependencies": {
       "dependencies": {
         "accepts": "~1.3.8",
         "accepts": "~1.3.8",
@@ -10081,7 +10102,7 @@
         "methods": "~1.1.2",
         "methods": "~1.1.2",
         "on-finished": "2.4.1",
         "on-finished": "2.4.1",
         "parseurl": "~1.3.3",
         "parseurl": "~1.3.3",
-        "path-to-regexp": "0.1.10",
+        "path-to-regexp": "0.1.12",
         "proxy-addr": "~2.0.7",
         "proxy-addr": "~2.0.7",
         "qs": "6.13.0",
         "qs": "6.13.0",
         "range-parser": "~1.2.1",
         "range-parser": "~1.2.1",
@@ -10096,13 +10117,16 @@
       },
       },
       "engines": {
       "engines": {
         "node": ">= 0.10.0"
         "node": ">= 0.10.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/express"
       }
       }
     },
     },
     "node_modules/express/node_modules/cookie": {
     "node_modules/express/node_modules/cookie": {
       "version": "0.7.1",
       "version": "0.7.1",
       "resolved": "https://registry.npmmirror.com/cookie/-/cookie-0.7.1.tgz",
       "resolved": "https://registry.npmmirror.com/cookie/-/cookie-0.7.1.tgz",
       "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==",
       "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "engines": {
       "engines": {
         "node": ">= 0.6"
         "node": ">= 0.6"
@@ -10112,7 +10136,6 @@
       "version": "2.6.9",
       "version": "2.6.9",
       "resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz",
       "resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz",
       "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
       "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "dependencies": {
       "dependencies": {
         "ms": "2.0.0"
         "ms": "2.0.0"
@@ -10122,7 +10145,6 @@
       "version": "2.0.0",
       "version": "2.0.0",
       "resolved": "https://registry.npmmirror.com/encodeurl/-/encodeurl-2.0.0.tgz",
       "resolved": "https://registry.npmmirror.com/encodeurl/-/encodeurl-2.0.0.tgz",
       "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
       "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "engines": {
       "engines": {
         "node": ">= 0.8"
         "node": ">= 0.8"
@@ -10132,7 +10154,6 @@
       "version": "1.3.1",
       "version": "1.3.1",
       "resolved": "https://registry.npmmirror.com/finalhandler/-/finalhandler-1.3.1.tgz",
       "resolved": "https://registry.npmmirror.com/finalhandler/-/finalhandler-1.3.1.tgz",
       "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==",
       "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "dependencies": {
       "dependencies": {
         "debug": "2.6.9",
         "debug": "2.6.9",
@@ -10151,14 +10172,12 @@
       "version": "2.0.0",
       "version": "2.0.0",
       "resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz",
       "resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz",
       "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
       "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
-      "dev": true,
       "license": "MIT"
       "license": "MIT"
     },
     },
     "node_modules/express/node_modules/statuses": {
     "node_modules/express/node_modules/statuses": {
       "version": "2.0.1",
       "version": "2.0.1",
       "resolved": "https://registry.npmmirror.com/statuses/-/statuses-2.0.1.tgz",
       "resolved": "https://registry.npmmirror.com/statuses/-/statuses-2.0.1.tgz",
       "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
       "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "engines": {
       "engines": {
         "node": ">= 0.8"
         "node": ">= 0.8"
@@ -10533,7 +10552,6 @@
       "version": "0.2.0",
       "version": "0.2.0",
       "resolved": "https://registry.npmmirror.com/forwarded/-/forwarded-0.2.0.tgz",
       "resolved": "https://registry.npmmirror.com/forwarded/-/forwarded-0.2.0.tgz",
       "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
       "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "engines": {
       "engines": {
         "node": ">= 0.6"
         "node": ">= 0.6"
@@ -10557,7 +10575,6 @@
       "version": "0.5.2",
       "version": "0.5.2",
       "resolved": "https://registry.npmmirror.com/fresh/-/fresh-0.5.2.tgz",
       "resolved": "https://registry.npmmirror.com/fresh/-/fresh-0.5.2.tgz",
       "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
       "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "engines": {
       "engines": {
         "node": ">= 0.6"
         "node": ">= 0.6"
@@ -10617,7 +10634,6 @@
       "version": "1.1.2",
       "version": "1.1.2",
       "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz",
       "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz",
       "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
       "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "funding": {
       "funding": {
         "url": "https://github.com/sponsors/ljharb"
         "url": "https://github.com/sponsors/ljharb"
@@ -10688,7 +10704,6 @@
       "version": "1.2.4",
       "version": "1.2.4",
       "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
       "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
       "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
       "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "dependencies": {
       "dependencies": {
         "es-errors": "^1.3.0",
         "es-errors": "^1.3.0",
@@ -10863,7 +10878,6 @@
       "version": "1.1.0",
       "version": "1.1.0",
       "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.1.0.tgz",
       "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.1.0.tgz",
       "integrity": "sha512-FQoVQnqcdk4hVM4JN1eromaun4iuS34oStkdlLENLdpULsuQcTyXj8w7ayhuUfPwEYZ1ZOooOTT6fdA9Vmx/RA==",
       "integrity": "sha512-FQoVQnqcdk4hVM4JN1eromaun4iuS34oStkdlLENLdpULsuQcTyXj8w7ayhuUfPwEYZ1ZOooOTT6fdA9Vmx/RA==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "dependencies": {
       "dependencies": {
         "get-intrinsic": "^1.2.4"
         "get-intrinsic": "^1.2.4"
@@ -10920,7 +10934,6 @@
       "version": "1.0.2",
       "version": "1.0.2",
       "resolved": "https://registry.npmmirror.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
       "resolved": "https://registry.npmmirror.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
       "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
       "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "dependencies": {
       "dependencies": {
         "es-define-property": "^1.0.0"
         "es-define-property": "^1.0.0"
@@ -10933,7 +10946,6 @@
       "version": "1.0.3",
       "version": "1.0.3",
       "resolved": "https://registry.npmmirror.com/has-proto/-/has-proto-1.0.3.tgz",
       "resolved": "https://registry.npmmirror.com/has-proto/-/has-proto-1.0.3.tgz",
       "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
       "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "engines": {
       "engines": {
         "node": ">= 0.4"
         "node": ">= 0.4"
@@ -10946,7 +10958,6 @@
       "version": "1.0.3",
       "version": "1.0.3",
       "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.0.3.tgz",
       "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.0.3.tgz",
       "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
       "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "engines": {
       "engines": {
         "node": ">= 0.4"
         "node": ">= 0.4"
@@ -10975,7 +10986,6 @@
       "version": "2.0.2",
       "version": "2.0.2",
       "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz",
       "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz",
       "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
       "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "dependencies": {
       "dependencies": {
         "function-bind": "^1.1.2"
         "function-bind": "^1.1.2"
@@ -11129,7 +11139,6 @@
       "version": "2.0.0",
       "version": "2.0.0",
       "resolved": "https://registry.npmmirror.com/http-errors/-/http-errors-2.0.0.tgz",
       "resolved": "https://registry.npmmirror.com/http-errors/-/http-errors-2.0.0.tgz",
       "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
       "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "dependencies": {
       "dependencies": {
         "depd": "2.0.0",
         "depd": "2.0.0",
@@ -11146,7 +11155,6 @@
       "version": "2.0.1",
       "version": "2.0.1",
       "resolved": "https://registry.npmmirror.com/statuses/-/statuses-2.0.1.tgz",
       "resolved": "https://registry.npmmirror.com/statuses/-/statuses-2.0.1.tgz",
       "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
       "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "engines": {
       "engines": {
         "node": ">= 0.8"
         "node": ">= 0.8"
@@ -11244,7 +11252,6 @@
       "version": "0.4.24",
       "version": "0.4.24",
       "resolved": "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.4.24.tgz",
       "resolved": "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.4.24.tgz",
       "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
       "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "dependencies": {
       "dependencies": {
         "safer-buffer": ">= 2.1.2 < 3"
         "safer-buffer": ">= 2.1.2 < 3"
@@ -11391,7 +11398,6 @@
       "version": "2.0.4",
       "version": "2.0.4",
       "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz",
       "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz",
       "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
       "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
-      "dev": true,
       "license": "ISC"
       "license": "ISC"
     },
     },
     "node_modules/ini": {
     "node_modules/ini": {
@@ -12658,6 +12664,13 @@
         "node": ">=10"
         "node": ">=10"
       }
       }
     },
     },
+    "node_modules/keycharm": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmmirror.com/keycharm/-/keycharm-0.4.0.tgz",
+      "integrity": "sha512-TyQTtsabOVv3MeOpR92sIKk/br9wxS+zGj4BG7CR8YbK4jM3tyIBaF0zhzeBUMx36/Q/iQLOKKOT+3jOQtemRQ==",
+      "license": "(Apache-2.0 OR MIT)",
+      "peer": true
+    },
     "node_modules/keyv": {
     "node_modules/keyv": {
       "version": "4.5.4",
       "version": "4.5.4",
       "resolved": "https://registry.npmmirror.com/keyv/-/keyv-4.5.4.tgz",
       "resolved": "https://registry.npmmirror.com/keyv/-/keyv-4.5.4.tgz",
@@ -13434,7 +13447,6 @@
       "version": "0.3.0",
       "version": "0.3.0",
       "resolved": "https://registry.npmmirror.com/media-typer/-/media-typer-0.3.0.tgz",
       "resolved": "https://registry.npmmirror.com/media-typer/-/media-typer-0.3.0.tgz",
       "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
       "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "engines": {
       "engines": {
         "node": ">= 0.6"
         "node": ">= 0.6"
@@ -13464,7 +13476,6 @@
       "version": "1.0.3",
       "version": "1.0.3",
       "resolved": "https://registry.npmmirror.com/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
       "resolved": "https://registry.npmmirror.com/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
       "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==",
       "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "funding": {
       "funding": {
         "url": "https://github.com/sponsors/sindresorhus"
         "url": "https://github.com/sponsors/sindresorhus"
@@ -13491,7 +13502,6 @@
       "version": "1.1.2",
       "version": "1.1.2",
       "resolved": "https://registry.npmmirror.com/methods/-/methods-1.1.2.tgz",
       "resolved": "https://registry.npmmirror.com/methods/-/methods-1.1.2.tgz",
       "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
       "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "engines": {
       "engines": {
         "node": ">= 0.6"
         "node": ">= 0.6"
@@ -14490,7 +14500,6 @@
       "version": "4.1.1",
       "version": "4.1.1",
       "resolved": "https://registry.npmmirror.com/object-assign/-/object-assign-4.1.1.tgz",
       "resolved": "https://registry.npmmirror.com/object-assign/-/object-assign-4.1.1.tgz",
       "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
       "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "engines": {
       "engines": {
         "node": ">=0.10.0"
         "node": ">=0.10.0"
@@ -14500,7 +14509,6 @@
       "version": "1.13.3",
       "version": "1.13.3",
       "resolved": "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.13.3.tgz",
       "resolved": "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.13.3.tgz",
       "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==",
       "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "engines": {
       "engines": {
         "node": ">= 0.4"
         "node": ">= 0.4"
@@ -14601,7 +14609,6 @@
       "version": "2.4.1",
       "version": "2.4.1",
       "resolved": "https://registry.npmmirror.com/on-finished/-/on-finished-2.4.1.tgz",
       "resolved": "https://registry.npmmirror.com/on-finished/-/on-finished-2.4.1.tgz",
       "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
       "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "dependencies": {
       "dependencies": {
         "ee-first": "1.1.1"
         "ee-first": "1.1.1"
@@ -15082,7 +15089,6 @@
       "version": "1.3.3",
       "version": "1.3.3",
       "resolved": "https://registry.npmmirror.com/parseurl/-/parseurl-1.3.3.tgz",
       "resolved": "https://registry.npmmirror.com/parseurl/-/parseurl-1.3.3.tgz",
       "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
       "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "engines": {
       "engines": {
         "node": ">= 0.8"
         "node": ">= 0.8"
@@ -15149,10 +15155,9 @@
       "license": "ISC"
       "license": "ISC"
     },
     },
     "node_modules/path-to-regexp": {
     "node_modules/path-to-regexp": {
-      "version": "0.1.10",
-      "resolved": "https://registry.npmmirror.com/path-to-regexp/-/path-to-regexp-0.1.10.tgz",
-      "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==",
-      "dev": true,
+      "version": "0.1.12",
+      "resolved": "https://registry.npmmirror.com/path-to-regexp/-/path-to-regexp-0.1.12.tgz",
+      "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==",
       "license": "MIT"
       "license": "MIT"
     },
     },
     "node_modules/path-type": {
     "node_modules/path-type": {
@@ -15587,7 +15592,6 @@
       "version": "2.0.7",
       "version": "2.0.7",
       "resolved": "https://registry.npmmirror.com/proxy-addr/-/proxy-addr-2.0.7.tgz",
       "resolved": "https://registry.npmmirror.com/proxy-addr/-/proxy-addr-2.0.7.tgz",
       "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
       "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "dependencies": {
       "dependencies": {
         "forwarded": "0.2.0",
         "forwarded": "0.2.0",
@@ -15601,7 +15605,6 @@
       "version": "1.9.1",
       "version": "1.9.1",
       "resolved": "https://registry.npmmirror.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
       "resolved": "https://registry.npmmirror.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
       "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
       "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "engines": {
       "engines": {
         "node": ">= 0.10"
         "node": ">= 0.10"
@@ -15836,7 +15839,6 @@
       "version": "6.13.0",
       "version": "6.13.0",
       "resolved": "https://registry.npmmirror.com/qs/-/qs-6.13.0.tgz",
       "resolved": "https://registry.npmmirror.com/qs/-/qs-6.13.0.tgz",
       "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
       "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
-      "dev": true,
       "license": "BSD-3-Clause",
       "license": "BSD-3-Clause",
       "dependencies": {
       "dependencies": {
         "side-channel": "^1.0.6"
         "side-channel": "^1.0.6"
@@ -15894,7 +15896,6 @@
       "version": "1.2.1",
       "version": "1.2.1",
       "resolved": "https://registry.npmmirror.com/range-parser/-/range-parser-1.2.1.tgz",
       "resolved": "https://registry.npmmirror.com/range-parser/-/range-parser-1.2.1.tgz",
       "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
       "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "engines": {
       "engines": {
         "node": ">= 0.6"
         "node": ">= 0.6"
@@ -15904,7 +15905,6 @@
       "version": "2.5.2",
       "version": "2.5.2",
       "resolved": "https://registry.npmmirror.com/raw-body/-/raw-body-2.5.2.tgz",
       "resolved": "https://registry.npmmirror.com/raw-body/-/raw-body-2.5.2.tgz",
       "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
       "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "dependencies": {
       "dependencies": {
         "bytes": "3.1.2",
         "bytes": "3.1.2",
@@ -16383,7 +16383,6 @@
       "version": "5.2.1",
       "version": "5.2.1",
       "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz",
       "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz",
       "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
       "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
-      "dev": true,
       "funding": [
       "funding": [
         {
         {
           "type": "github",
           "type": "github",
@@ -16422,7 +16421,6 @@
       "version": "2.1.2",
       "version": "2.1.2",
       "resolved": "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz",
       "resolved": "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz",
       "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
       "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
-      "dev": true,
       "license": "MIT"
       "license": "MIT"
     },
     },
     "node_modules/sass": {
     "node_modules/sass": {
@@ -16566,7 +16564,6 @@
       "version": "0.19.0",
       "version": "0.19.0",
       "resolved": "https://registry.npmmirror.com/send/-/send-0.19.0.tgz",
       "resolved": "https://registry.npmmirror.com/send/-/send-0.19.0.tgz",
       "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==",
       "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "dependencies": {
       "dependencies": {
         "debug": "2.6.9",
         "debug": "2.6.9",
@@ -16591,7 +16588,6 @@
       "version": "2.6.9",
       "version": "2.6.9",
       "resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz",
       "resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz",
       "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
       "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "dependencies": {
       "dependencies": {
         "ms": "2.0.0"
         "ms": "2.0.0"
@@ -16601,14 +16597,12 @@
       "version": "2.0.0",
       "version": "2.0.0",
       "resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz",
       "resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz",
       "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
       "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
-      "dev": true,
       "license": "MIT"
       "license": "MIT"
     },
     },
     "node_modules/send/node_modules/mime": {
     "node_modules/send/node_modules/mime": {
       "version": "1.6.0",
       "version": "1.6.0",
       "resolved": "https://registry.npmmirror.com/mime/-/mime-1.6.0.tgz",
       "resolved": "https://registry.npmmirror.com/mime/-/mime-1.6.0.tgz",
       "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
       "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "bin": {
       "bin": {
         "mime": "cli.js"
         "mime": "cli.js"
@@ -16621,7 +16615,6 @@
       "version": "2.0.1",
       "version": "2.0.1",
       "resolved": "https://registry.npmmirror.com/statuses/-/statuses-2.0.1.tgz",
       "resolved": "https://registry.npmmirror.com/statuses/-/statuses-2.0.1.tgz",
       "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
       "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "engines": {
       "engines": {
         "node": ">= 0.8"
         "node": ">= 0.8"
@@ -16717,7 +16710,6 @@
       "version": "1.16.2",
       "version": "1.16.2",
       "resolved": "https://registry.npmmirror.com/serve-static/-/serve-static-1.16.2.tgz",
       "resolved": "https://registry.npmmirror.com/serve-static/-/serve-static-1.16.2.tgz",
       "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==",
       "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "dependencies": {
       "dependencies": {
         "encodeurl": "~2.0.0",
         "encodeurl": "~2.0.0",
@@ -16733,7 +16725,6 @@
       "version": "2.0.0",
       "version": "2.0.0",
       "resolved": "https://registry.npmmirror.com/encodeurl/-/encodeurl-2.0.0.tgz",
       "resolved": "https://registry.npmmirror.com/encodeurl/-/encodeurl-2.0.0.tgz",
       "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
       "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "engines": {
       "engines": {
         "node": ">= 0.8"
         "node": ">= 0.8"
@@ -16750,7 +16741,6 @@
       "version": "1.2.2",
       "version": "1.2.2",
       "resolved": "https://registry.npmmirror.com/set-function-length/-/set-function-length-1.2.2.tgz",
       "resolved": "https://registry.npmmirror.com/set-function-length/-/set-function-length-1.2.2.tgz",
       "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
       "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "dependencies": {
       "dependencies": {
         "define-data-property": "^1.1.4",
         "define-data-property": "^1.1.4",
@@ -16784,7 +16774,6 @@
       "version": "1.2.0",
       "version": "1.2.0",
       "resolved": "https://registry.npmmirror.com/setprototypeof/-/setprototypeof-1.2.0.tgz",
       "resolved": "https://registry.npmmirror.com/setprototypeof/-/setprototypeof-1.2.0.tgz",
       "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
       "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
-      "dev": true,
       "license": "ISC"
       "license": "ISC"
     },
     },
     "node_modules/shallow-clone": {
     "node_modules/shallow-clone": {
@@ -16840,7 +16829,6 @@
       "version": "1.0.6",
       "version": "1.0.6",
       "resolved": "https://registry.npmmirror.com/side-channel/-/side-channel-1.0.6.tgz",
       "resolved": "https://registry.npmmirror.com/side-channel/-/side-channel-1.0.6.tgz",
       "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
       "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "dependencies": {
       "dependencies": {
         "call-bind": "^1.0.7",
         "call-bind": "^1.0.7",
@@ -17240,6 +17228,12 @@
       "dev": true,
       "dev": true,
       "license": "BSD-3-Clause"
       "license": "BSD-3-Clause"
     },
     },
+    "node_modules/ssr-window": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmmirror.com/ssr-window/-/ssr-window-4.0.2.tgz",
+      "integrity": "sha512-ISv/Ch+ig7SOtw7G2+qkwfVASzazUnvlDTwypdLoPoySv+6MqlOV10VwPSE6EWkGjhW50lUmghPmpYZXMu/+AQ==",
+      "license": "MIT"
+    },
     "node_modules/ssri": {
     "node_modules/ssri": {
       "version": "10.0.6",
       "version": "10.0.6",
       "resolved": "https://registry.npmmirror.com/ssri/-/ssri-10.0.6.tgz",
       "resolved": "https://registry.npmmirror.com/ssri/-/ssri-10.0.6.tgz",
@@ -17505,6 +17499,30 @@
         "url": "https://github.com/sponsors/ljharb"
         "url": "https://github.com/sponsors/ljharb"
       }
       }
     },
     },
+    "node_modules/swiper": {
+      "version": "8.4.7",
+      "resolved": "https://registry.npmmirror.com/swiper/-/swiper-8.4.7.tgz",
+      "integrity": "sha512-VwO/KU3i9IV2Sf+W2NqyzwWob4yX9Qdedq6vBtS0rFqJ6Fa5iLUJwxQkuD4I38w0WDJwmFl8ojkdcRFPHWD+2g==",
+      "funding": [
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/swiperjs"
+        },
+        {
+          "type": "open_collective",
+          "url": "http://opencollective.com/swiper"
+        }
+      ],
+      "hasInstallScript": true,
+      "license": "MIT",
+      "dependencies": {
+        "dom7": "^4.0.4",
+        "ssr-window": "^4.0.2"
+      },
+      "engines": {
+        "node": ">= 4.7.0"
+      }
+    },
     "node_modules/symbol-observable": {
     "node_modules/symbol-observable": {
       "version": "4.0.0",
       "version": "4.0.0",
       "resolved": "https://registry.npmmirror.com/symbol-observable/-/symbol-observable-4.0.0.tgz",
       "resolved": "https://registry.npmmirror.com/symbol-observable/-/symbol-observable-4.0.0.tgz",
@@ -17790,7 +17808,6 @@
       "version": "1.0.1",
       "version": "1.0.1",
       "resolved": "https://registry.npmmirror.com/toidentifier/-/toidentifier-1.0.1.tgz",
       "resolved": "https://registry.npmmirror.com/toidentifier/-/toidentifier-1.0.1.tgz",
       "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
       "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "engines": {
       "engines": {
         "node": ">=0.6"
         "node": ">=0.6"
@@ -17913,7 +17930,6 @@
       "version": "1.6.18",
       "version": "1.6.18",
       "resolved": "https://registry.npmmirror.com/type-is/-/type-is-1.6.18.tgz",
       "resolved": "https://registry.npmmirror.com/type-is/-/type-is-1.6.18.tgz",
       "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
       "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "dependencies": {
       "dependencies": {
         "media-typer": "0.3.0",
         "media-typer": "0.3.0",
@@ -18175,7 +18191,6 @@
       "version": "1.0.0",
       "version": "1.0.0",
       "resolved": "https://registry.npmmirror.com/unpipe/-/unpipe-1.0.0.tgz",
       "resolved": "https://registry.npmmirror.com/unpipe/-/unpipe-1.0.0.tgz",
       "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
       "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "engines": {
       "engines": {
         "node": ">= 0.8"
         "node": ">= 0.8"
@@ -18260,7 +18275,6 @@
       "version": "1.0.1",
       "version": "1.0.1",
       "resolved": "https://registry.npmmirror.com/utils-merge/-/utils-merge-1.0.1.tgz",
       "resolved": "https://registry.npmmirror.com/utils-merge/-/utils-merge-1.0.1.tgz",
       "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
       "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "engines": {
       "engines": {
         "node": ">= 0.4.0"
         "node": ">= 0.4.0"
@@ -18270,7 +18284,6 @@
       "version": "8.3.2",
       "version": "8.3.2",
       "resolved": "https://registry.npmmirror.com/uuid/-/uuid-8.3.2.tgz",
       "resolved": "https://registry.npmmirror.com/uuid/-/uuid-8.3.2.tgz",
       "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
       "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "bin": {
       "bin": {
         "uuid": "dist/bin/uuid"
         "uuid": "dist/bin/uuid"
@@ -18312,12 +18325,62 @@
       "version": "1.1.2",
       "version": "1.1.2",
       "resolved": "https://registry.npmmirror.com/vary/-/vary-1.1.2.tgz",
       "resolved": "https://registry.npmmirror.com/vary/-/vary-1.1.2.tgz",
       "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
       "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
-      "dev": true,
       "license": "MIT",
       "license": "MIT",
       "engines": {
       "engines": {
         "node": ">= 0.8"
         "node": ">= 0.8"
       }
       }
     },
     },
+    "node_modules/vis-data": {
+      "version": "7.1.9",
+      "resolved": "https://registry.npmmirror.com/vis-data/-/vis-data-7.1.9.tgz",
+      "integrity": "sha512-COQsxlVrmcRIbZMMTYwD+C2bxYCFDNQ2EHESklPiInbD/Pk3JZ6qNL84Bp9wWjYjAzXfSlsNaFtRk+hO9yBPWA==",
+      "license": "(Apache-2.0 OR MIT)",
+      "peer": true,
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/visjs"
+      },
+      "peerDependencies": {
+        "uuid": "^3.4.0 || ^7.0.0 || ^8.0.0 || ^9.0.0",
+        "vis-util": "^5.0.1"
+      }
+    },
+    "node_modules/vis-network": {
+      "version": "9.1.9",
+      "resolved": "https://registry.npmmirror.com/vis-network/-/vis-network-9.1.9.tgz",
+      "integrity": "sha512-Ft+hLBVyiLstVYSb69Q1OIQeh3FeUxHJn0WdFcq+BFPqs+Vq1ibMi2sb//cxgq1CP7PH4yOXnHxEH/B2VzpZYA==",
+      "license": "(Apache-2.0 OR MIT)",
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/visjs"
+      },
+      "peerDependencies": {
+        "@egjs/hammerjs": "^2.0.0",
+        "component-emitter": "^1.3.0",
+        "keycharm": "^0.2.0 || ^0.3.0 || ^0.4.0",
+        "uuid": "^3.4.0 || ^7.0.0 || ^8.0.0 || ^9.0.0",
+        "vis-data": "^6.3.0 || ^7.0.0",
+        "vis-util": "^5.0.1"
+      }
+    },
+    "node_modules/vis-util": {
+      "version": "5.0.7",
+      "resolved": "https://registry.npmmirror.com/vis-util/-/vis-util-5.0.7.tgz",
+      "integrity": "sha512-E3L03G3+trvc/X4LXvBfih3YIHcKS2WrP0XTdZefr6W6Qi/2nNCqZfe4JFfJU6DcQLm6Gxqj2Pfl+02859oL5A==",
+      "license": "(Apache-2.0 OR MIT)",
+      "peer": true,
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/visjs"
+      },
+      "peerDependencies": {
+        "@egjs/hammerjs": "^2.0.0",
+        "component-emitter": "^1.3.0 || ^2.0.0"
+      }
+    },
     "node_modules/vite": {
     "node_modules/vite": {
       "version": "5.4.6",
       "version": "5.4.6",
       "resolved": "https://registry.npmmirror.com/vite/-/vite-5.4.6.tgz",
       "resolved": "https://registry.npmmirror.com/vite/-/vite-5.4.6.tgz",

+ 6 - 2
package.json

@@ -26,12 +26,16 @@
     "@capacitor/haptics": "6.0.2",
     "@capacitor/haptics": "6.0.2",
     "@capacitor/keyboard": "6.0.3",
     "@capacitor/keyboard": "6.0.3",
     "@capacitor/status-bar": "6.0.2",
     "@capacitor/status-bar": "6.0.2",
-    "@ionic/angular": "^8.0.0",
-    "axios": "^1.7.8",
+    "@ionic/angular": "^8.4.1",
+    "axios": "^1.7.9",
+    "cors": "^2.8.5",
+    "express": "^4.21.2",
     "fmode-ng": "^0.0.62",
     "fmode-ng": "^0.0.62",
     "ionicons": "^7.0.0",
     "ionicons": "^7.0.0",
     "rxjs": "~7.8.0",
     "rxjs": "~7.8.0",
+    "swiper": "^8.4.7",
     "tslib": "^2.3.0",
     "tslib": "^2.3.0",
+    "vis-network": "^9.1.9",
     "zone.js": "~0.14.2"
     "zone.js": "~0.14.2"
   },
   },
   "devDependencies": {
   "devDependencies": {

+ 23 - 0
proxy.js

@@ -0,0 +1,23 @@
+const express = require('express');
+const cors = require('cors');
+const axios = require('axios');
+
+const app = express();
+app.use(cors());
+
+const PORT = 3000;
+
+// 处理百度搜索请求
+app.get('/search', async (req, res) => {
+  const query = req.query.q; // 获取前端传来的搜索关键词
+  try {
+    const response = await axios.get(`https://www.baidu.com/s?wd=${encodeURIComponent(query)}`);
+    res.send(response.data); // 将百度返回的 HTML 数据转发给前端
+  } catch (error) {
+    res.status(500).send('Error fetching data from Baidu');
+  }
+});
+
+app.listen(PORT, () => {
+  console.log(`Proxy server running on http://localhost:${PORT}`);
+});

+ 2 - 1
src/app/app.module.ts

@@ -9,6 +9,7 @@ import { AppComponent } from './app.component';
 import { provideHttpClient } from '@angular/common/http'; // 引用HttpClient方法
 import { provideHttpClient } from '@angular/common/http'; // 引用HttpClient方法
 import { Diagnostic } from '@awesome-cordova-plugins/diagnostic/ngx'; // 引用移动端授权检测供应器
 import { Diagnostic } from '@awesome-cordova-plugins/diagnostic/ngx'; // 引用移动端授权检测供应器
 import Parse from "parse";// 设置Parse服务属性
 import Parse from "parse";// 设置Parse服务属性
+import { SwiperModule } from 'swiper/angular'; // 导入 SwiperModule
 Parse.initialize("ncloudmaster");
 Parse.initialize("ncloudmaster");
 Parse.serverURL = "https://server.fmode.cn/parse";
 Parse.serverURL = "https://server.fmode.cn/parse";
 localStorage.setItem("NOVA_APIG_SERVER", 'aHR0cHMlM0ElMkYlMkZzZXJ2ZXIuZm1vZGUuY24lMkZhcGklMkZhcGlnJTJG')
 localStorage.setItem("NOVA_APIG_SERVER", 'aHR0cHMlM0ElMkYlMkZzZXJ2ZXIuZm1vZGUuY24lMkZhcGklMkZhcGlnJTJG')
@@ -16,7 +17,7 @@ localStorage.setItem("NOVA_APIG_SERVER", 'aHR0cHMlM0ElMkYlMkZzZXJ2ZXIuZm1vZGUuY2
 Parse.User.become('r:b86ae57d94d26cbbfce6a1515c3946ee')
 Parse.User.become('r:b86ae57d94d26cbbfce6a1515c3946ee')
 @NgModule({
 @NgModule({
   declarations: [AppComponent],
   declarations: [AppComponent],
-  imports: [BrowserModule, IonicModule.forRoot(), AppRoutingModule],
+  imports: [BrowserModule, IonicModule.forRoot(), AppRoutingModule, SwiperModule],
   providers: [
   providers: [
     // 添加HttpClient供应器
     // 添加HttpClient供应器
     provideHttpClient(),
     provideHttpClient(),

+ 8 - 6
src/app/ceramic-details/ceramic-details.page.html

@@ -1,15 +1,17 @@
-<ion-header>
+<ion-header [translucent]="true">
   <ion-toolbar>
   <ion-toolbar>
-    <ion-title>{{ title }}</ion-title>
-    <ion-buttons slot="end">
-      <ion-button (click)="close()">关闭</ion-button>
-    </ion-buttons>
+    <ion-title class="header-title">窑忆</ion-title>
+    <ion-buttons slot = "end">
+      <ion-button (click)="close()" class="close - button">
+          <ion-icon name="close"></ion-icon>
+      </ion-button>
+  </ion-buttons>
   </ion-toolbar>
   </ion-toolbar>
 </ion-header>
 </ion-header>
 
 
 <ion-content>
 <ion-content>
   <div class="ceramic-container">
   <div class="ceramic-container">
-    <ion-img [src]="imageUrl" alt="{{ title }}"></ion-img>
+    <ion-img [src]="imageUrl" alt="{{ title }}" class="ceramic-img"></ion-img>
     <div class="description">
     <div class="description">
       <h2>{{ title }}</h2>
       <h2>{{ title }}</h2>
       <p>{{ description }}</p>
       <p>{{ description }}</p>

+ 85 - 26
src/app/ceramic-details/ceramic-details.page.scss

@@ -1,29 +1,88 @@
+/* 主体内容容器 */
 .ceramic-container {
 .ceramic-container {
-    text-align: center;
-    padding: 16px;
+  text-align: center;
+  padding: 20px;
+  font-family: "FangSong", serif; /* 使用仿宋体 */
+  border-radius: 16px; /* 圆角效果 */
+  background: url('/assets/images/ceramics-background.png') no-repeat center/cover;
+  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); /* 更柔和的阴影 */
+  margin: 20px auto;
+}
+
+/* 图片样式 */
+.ceramic-img {
+  max-width: 100%;
+  height: auto;
+  border-radius: 10px;
+  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
+  margin-bottom: 10px;
+  transition: transform 0.8s ease-in-out; /* 动效 */
+}
+
+/* 图片 hover 动效 */
+.ceramic-img:hover {
+  transform: scale(1.05); /* 鼠标悬停时图片放大 */
+}
+
+/* 文字描述 */
+.description {
+  text-align: center;
+  padding: 10px;
+}
+
+/* 标题样式 */
+.description h2 {
+  font-size: 2rem;
+  font-weight: bold;
+  color: #333;
+  margin-bottom: 10px;
+}
+
+/* 描述文本 */
+.description p {
+  font-size: 1.1rem;
+  font-weight: bold; /* 加粗 */
+  color: #666;
+  line-height: 1.6;
+  margin-top: 10px;
+  text-align: left; /* 左对齐 */
+}
+
+/* Header 样式 */
+.header-title {
+  font-family: "FangSong", serif; /* 使用仿宋体 */
+  font-weight: bold; /* 加粗 */
+  text-align: center; /* 居中 */
+}
+
+/* 关闭按钮 */
+.close-button {
+  --color:gray;
+  transition: background-color 0.3s ease;
+}
+
+.close-button:hover {
+  background-color: #ff2a20; /* 鼠标悬停时背景颜色 */
+}
+/* 定义模态框样式 */
+.custom-modal {
+  position: fixed;
+  bottom: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  background: white;
+  border-radius: 20px 20px 0 0;
+  box-shadow: 0px -4px 10px rgba(0, 0, 0, 0.2);
+  z-index: 1000;
+  overflow-y: auto;
+}
+/* 模态框从底部滑入的动画 */
+@keyframes slide-up {
+  from {
+    transform: translateY(100%);
   }
   }
-  
-  ion-img {
-    max-width: 100%;
-    max-height: 200px;
-    margin: 16px auto;
-    border-radius: 10px;
-    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
+  to {
+    transform: translateY(0);
   }
   }
-  
-  .description {
-    margin-top: 16px;
-    text-align: center;
-  }
-  
-  .description h2 {
-    font-size: 1.5rem;
-    font-weight: bold;
-    margin-bottom: 8px;
-  }
-  
-  .description p {
-    font-size: 1rem;
-    color: #666;
-  }
-  
+}

+ 2 - 1
src/app/tab1/tab1.module.ts

@@ -2,9 +2,9 @@ import { IonicModule } from '@ionic/angular';
 import { NgModule } from '@angular/core';
 import { NgModule } from '@angular/core';
 import { CommonModule } from '@angular/common';
 import { CommonModule } from '@angular/common';
 import { FormsModule } from '@angular/forms';
 import { FormsModule } from '@angular/forms';
+import { SwiperModule } from 'swiper/angular';  // 导入 SwiperModule
 import { Tab1Page } from './tab1.page';
 import { Tab1Page } from './tab1.page';
 import { ExploreContainerComponentModule } from '../explore-container/explore-container.module';
 import { ExploreContainerComponentModule } from '../explore-container/explore-container.module';
-
 import { Tab1PageRoutingModule } from './tab1-routing.module';
 import { Tab1PageRoutingModule } from './tab1-routing.module';
 
 
 @NgModule({
 @NgModule({
@@ -12,6 +12,7 @@ import { Tab1PageRoutingModule } from './tab1-routing.module';
     IonicModule,
     IonicModule,
     CommonModule,
     CommonModule,
     FormsModule,
     FormsModule,
+    SwiperModule,
     ExploreContainerComponentModule,
     ExploreContainerComponentModule,
     Tab1PageRoutingModule
     Tab1PageRoutingModule
   ],
   ],

+ 35 - 0
src/app/tab1/tab1.page.html

@@ -5,4 +5,39 @@
 </ion-header>
 </ion-header>
 
 
 <ion-content [fullscreen]="true" style="--background: url('/assets/images/background.jpg') no-repeat center/cover;">
 <ion-content [fullscreen]="true" style="--background: url('/assets/images/background.jpg') no-repeat center/cover;">
+  <!-- 透明盒子容器 -->
+  <div class="transparent-box">
+    <!-- 添加轮播图 -->
+    <div class="swiper-container">
+      <!-- 轮播图的每一张幻灯片 -->
+      <div class="swiper-wrapper">
+        <div class="swiper-slide" *ngFor="let slide of slides">
+          <img [src]="slide.image" alt="{{ slide.title }}">
+          <p>{{ slide.title }}</p>
+        </div>
+      </div>
+      <!-- 分页器 -->
+      <div class="swiper-pagination"></div>
+    </div>
+  </div>
+  <ion-item lines="none" class="search-container">
+    <!-- 添加搜索框 -->
+    <ion-searchbar [(ngModel)]="searchQuery" (ionInput)="onSearch()" debounce="500" placeholder="请输入搜索内容..."></ion-searchbar>
+    <!-- 搜索按钮 -->
+    <ion-icon slot="end" name="search-outline" size="large"></ion-icon>
+  </ion-item>
+  <!-- 分隔线 -->
+  <hr class="divider" />
+  <div class="background-box">
+    <!-- 灰色半透明盒子 -->
+    <div class="square-box">
+      <!-- 容器 -->
+      <div id="graph-container" style="width: 100%; height: 400px;"></div>
+      <!-- 显示节点详细信息 -->
+      <div *ngIf="selectedNodeDetails" class="node-details" [ngStyle]="{ top: position.top, left: position.left }">
+        <p>{{ selectedNodeDetails }}</p>
+        <ion-icon name="close-circle-outline" (click)="closeMessageBox()" class="close-icon"></ion-icon>
+      </div>
+    </div>
+  </div>
 </ion-content>
 </ion-content>

+ 163 - 4
src/app/tab1/tab1.page.scss

@@ -1,5 +1,164 @@
+@import 'swiper/swiper-bundle.min.css';
 .header-title {
 .header-title {
-    font-family: "FangSong", serif; /* 使用仿宋体 */
-    font-weight: bold; /* 加粗 */
-    text-align: center; /* 居中 */
-  }
+  font-family: "FangSong", serif; /* 使用仿宋体 */
+  font-weight: bold; /* 加粗 */
+  text-align: center; /* 居中 */
+}
+/* 透明盒子容器样式 */
+.transparent-box {
+  position: relative;
+  width: 100%;
+  height: 250px; /* 轮播图的高度,根据需要调整 */
+  background-color: rgba(0, 0, 0, 0); /* 设置透明背景 */
+  overflow: hidden; /* 防止图片溢出 */
+  box-sizing: border-box;
+  padding: 0;
+  /* 圆角效果 */
+  border-radius: 10px; /* 根据需要调整圆角半径 */
+  /* 浮动效果 */
+  box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.2); /* 轻微的浮动效果,模拟阴影 */
+  transition: box-shadow 0.3s ease, transform 0.3s ease; /* 平滑过渡效果 */
+  /* 鼠标悬停时的效果:稍微浮动起来 */
+  &:hover {
+    transform: translateY(5px); /* 上浮效果 */
+    box-shadow: 0px 8px 20px rgba(0, 0, 0, 0.3); /* 增加阴影效果 */
+  }
+  margin-bottom: 20px;
+}
+/* 轮播图容器样式 */
+swiper {
+  width: 100%;
+  height: 100%;
+}
+/* 轮播图的每一页样式 */
+.swiper-slide {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  text-align: center;
+  position: relative;
+  width: 100%;
+  height: 100%;
+  background-color: #000; /* 背景色可以设置为黑色或其他颜色 */
+}
+/* 轮播图中的图片样式 */
+.swiper-slide img {
+  width: 100%;
+  height: 100%;
+  object-fit: cover; /* 图片自适应容器 */
+}
+/* 分页器样式:小圆点 */
+.swiper-pagination {
+  position: absolute;
+  bottom: 10px;  /* 距离底部10px */
+  left: 50%;
+  transform: translateX(-50%);
+  z-index: 10;
+}
+/* 搜索框容器 */
+ion-searchbar {
+  --background: #ffffff !important; /* 设置背景色 */
+  --border-radius: 10px !important; /* 设置圆角 */
+  --height: 60px !important;  /* 设置搜索框的高度 */
+  --box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1) !important; /* 添加阴影效果 */
+  --border: 1px solid #ccc !important; /* 设置边框颜色 */
+  --placeholder-color: #888 !important; /* 设置占位符颜色 */
+  font-family: "FangSong", serif !important; /* 使用仿宋体 */
+}
+/* 容器内的搜索框和按钮布局 */
+.search-container {
+  display: flex; /* 使用 Flexbox 布局 */
+  align-items: center; /* 垂直居中 */
+  width: 100%; /* 容器宽度为 100% */
+  padding: 0; /* 移除内边距 */
+}
+
+.searchbar {
+  flex-grow: 1; /* 使搜索框扩展占据剩余空间 */
+}
+
+ion-button {
+  --background: #ee1717 !important; /* 设置背景色 */
+  --border-radius: 10px !important; /* 设置圆角 */
+}
+.divider {
+  border: none; /* 去掉默认边框 */
+  height: 40px; /* 分割线高度 */
+  width: calc 100%; /* 总宽度减去左右空出20px */
+  margin: 16px auto; /* 自动居中 */
+  background: url('/assets/images/divider.png') repeat-x center; /* 设置图片作为分割线 */
+  background-size: contain; /* 确保图片在水平方向完整显示 */
+  }
+.background-box {
+  width: 100%; /* 容器宽度为100% */
+  height: 430px; /* 可以根据需要调整容器的高度 */
+  background-image: url('/assets/images/KG-background.png'); /* 设置背景图片 */
+  background-size: cover; /* 让背景图片覆盖整个容器 */
+  background-position: center; /* 背景图片居中 */
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+  padding: 20px; /* 给容器添加内边距 */
+  color: white; /* 设置文本颜色为白色 */
+}
+.square-box {
+  position: absolute;
+  top: 49%;
+  left: 2%;
+  width: 410px;
+  height: 410px;
+  background: rgb(196, 191, 191 ,0.8); /* 半透明灰色背景 */
+  display: flex; /* 使用 Flexbox 布局 */
+  justify-content: center; /* 水平居中 */
+  align-items: center; /* 垂直居中 */
+  border-radius: 20%;
+}
+.node-details {
+  position: absolute;
+  width: 200px;
+  height: 300px;
+  background-image: url('/assets/images/details-background.png'); /* 设置背景图片 */
+  background-size: cover; /* 让背景图片覆盖整个容器 */
+  background-position: center; /* 背景图片居中 */
+  border: 1px solid #ccc;
+  border-radius: 8px;
+  box-shadow: 0 6px 12px rgba(0, 0, 0, 0.4);
+  color:black;
+  z-index: 1000;
+  flex-grow: 1; /* 让 p 标签占据剩余空间 */
+  text-align: left; /* 确保文本左对齐 */
+  padding-left: 10px;
+  padding-right: 10px;
+  padding-top: 15px;
+  padding-bottom: 15px;
+  border-radius: 10px;
+  font-family: "FangSong", serif; /* 使用仿宋体 */
+  line-height: 1.8; /* 设置行间距 */
+  overflow-y: auto; /* 启用竖向滚动条 */
+  /* 初始状态:隐藏 */
+  opacity: 0;
+  transform: translateY(10px);
+  animation: fadeIn 0.3s ease-out forwards; /* 应用动画 */
+}
+@keyframes fadeIn {
+  0% {
+    opacity: 0;
+    transform: translateY(10px); /* 从下方轻微移动 */
+  }
+  100% {
+    opacity: 1;
+    transform: translateY(0); /* 回到原位置 */
+  }
+}
+.close-icon {
+  font-size: 24px;
+  color: gray;
+  cursor: pointer;
+  position: absolute; /* 使图标绝对定位 */
+  top: 5px; /* 距离顶部5px */
+  right: 10px; /* 距离右边10px */
+}
+.close-icon:hover {
+  color: #ff6f61; /* 鼠标悬停时改变颜色 */
+}

+ 192 - 28
src/app/tab1/tab1.page.ts

@@ -1,43 +1,207 @@
-import { Component } from '@angular/core';
-
+import { Component , AfterViewInit } from '@angular/core';
+import { HttpClient, HttpHeaders } from '@angular/common/http';
+import Swiper from 'swiper';
+import { Network, DataSet, Node, Edge } from 'vis-network/standalone';
+// 扩展 Node 和 Edge 类型以支持自定义属性
+interface CustomNode extends Node {
+  details: string;
+}
 @Component({
 @Component({
   selector: 'app-tab1',
   selector: 'app-tab1',
   templateUrl: './tab1.page.html',
   templateUrl: './tab1.page.html',
   styleUrls: ['./tab1.page.scss'],
   styleUrls: ['./tab1.page.scss'],
 })
 })
-export class Tab1Page {
-  userQuery: string = ''; // 用户输入的文本
-  agentAnswer: string = ''; // 智能体的回答
-  recommendedQuestion: string = '吉州窑的典型纹饰是什么?'; // 每日推荐问题
 
 
-  constructor() {}
+export class Tab1Page implements AfterViewInit{
+  // 定义 slides 属性,数组中的每个对象代表一个轮播图项目
+  slides = [
+    { image: '/assets/images/slide1.jpg', title: 'Slide 1' },
+    { image: '/assets/images/slide2.jpg', title: 'Slide 2' },
+    { image: '/assets/images/slide3.jpg', title: 'Slide 3' },
+    { image: '/assets/images/slide4.jpg', title: 'Slide 4' }
+  ];
+  selectedNodeDetails: string | null = null;
+  position = { top: '100px', left: '100px' }; // 消息框初始位置
+  isDragging = false;
+  dragOffset = { x: 0, y: 0 };
+  searchQuery: string = '';  // 搜索框的绑定变量
+  searchResults: any[] = []; // 存放搜索结果的数组
+  constructor(private http: HttpClient) {}
 
 
-  // 处理用户输入变化
-  onInputChange(event: any) {
-    this.userQuery = event.target.value;
+  ngAfterViewInit() {
+    // 初始化 Swiper
+    const swiper = new Swiper('.swiper-container', {
+      autoplay: {
+        delay: 3000,
+        disableOnInteraction: false,
+      },
+      loop: true,
+      pagination: {
+        el: '.swiper-pagination',
+        clickable: true,
+      },
+    });
+    console.log('Swiper initialized');
+    // 初始化知识图谱
+    this.createGraph();
   }
   }
+  // 创建知识图谱的函数
+  createGraph() {
+    // 从 JSON 文件加载数据
+    this.http.get('/assets/json/graph.json').subscribe({
+      next: (data: any) => {
+        // 使用 DataSet 包装数据
+        const nodes = new DataSet<CustomNode>(data.nodes);
+        const edges = new DataSet<Edge>(data.edges);
+        // 获取容器
+        const container = document.getElementById('graph-container') as HTMLElement;
+        // 定义图表配置
+        const options = {
+          autoResize: true,
+          height: '100%',
+          width: '100%',
+          nodes: {
+            shape: 'circle',
+            size: 12,
+            color: {
+              background: '#d7ccc8',
+              border: '#6d4c41',
+              highlight: {
+                background: '#bcaaa4',
+                border: '#5d4037',
+              },
+            },
+            font: {
+              size: 12,
+              color: '#3e2723',
+              face: 'serif',
+            },
+            borderWidth: 3,
+            borderWidthSelected: 5,
+          },
+          edges: {
+            width: 2,
+            color: {
+              color: '#795548',
+              highlight: '#5d4037',
+              hover: '#6d4c41',
+            },
+            font: {
+              size: 14,
+              color: '#5d4037',
+              face: 'serif',
+              align: 'middle',
+            },
+            smooth: {
+              enabled: true,
+              type: 'continuous',
+              roundness: 0.3,
+            },
+            arrows: {
+              to: {
+                enabled: true,
+                scaleFactor: 1.2,
+                type: 'vee',
+              },
+            },
+          },
+          physics: {
+            enabled: true,
+            solver: 'forceAtlas2Based',
+            barnesHut: {
+              gravitationalConstant: -1500,
+              centralGravity: 0.2,
+              springLength: 100,
+            },
+          },
+        };
 
 
-  // 提交问题并获取答案
-  fetchAnswer() {
-    if (this.userQuery.trim() === '') {
-      this.agentAnswer = '请输入有效的问题!';
-      return;
-    }
+        // 创建网络图
+        const network = new Network(container, { nodes, edges }, options);
+
+        // 点击事件:获取被点击节点的详细信息
+        network.on('click', (event: { nodes: number[]; pointer: { DOM: { x: number; y: number } } }) => {
+          if (event.nodes.length > 0) {
+            const clickedNodeId = event.nodes[0]; // 获取点击的节点 ID
+            const clickedNode = nodes.get(clickedNodeId); // 从 DataSet 中获取节点
+
+            if (clickedNode) {
+              this.selectedNodeDetails = clickedNode.details; // 获取节点的详细信息
+              console.log(this.selectedNodeDetails);
+
+              // 计算消息框的位置
+              const containerRect = container.getBoundingClientRect();
+              const clickX = Math.min(
+                Math.max(event.pointer.DOM.x - containerRect.left, 0),
+                containerRect.width - 300
+              );
+              const clickY = Math.min(
+                Math.max(event.pointer.DOM.y - containerRect.top, 0),
+                containerRect.height - 200
+              );
+
+              this.position = {
+                top: `${clickY}px`,
+                left: `${clickX}px`,
+              };
+            }
+          }
+        });
+      },
+      error: (err) => {
+        console.error('Error loading graph data:', err);
+      },
+    });
+  }
 
 
-    // 模拟调用智能体接口
-    this.agentAnswer = `这是关于 "${this.userQuery}" 的回答。`;
+  // 关闭消息框
+  closeMessageBox() {
+    this.selectedNodeDetails = null;
   }
   }
 
 
-  // 启动语音识别
-  startVoiceRecognition() {
-    // 模拟语音识别逻辑
-    this.userQuery = '模拟语音输入内容';
-    this.fetchAnswer();
+  // 处理搜索的函数
+  onSearch() {
+    if (this.searchQuery.trim() === '') {
+      this.searchResults = [];
+      return;
+    }
+  // 调用百度搜索
+  this.fetchBaiduSearchResults(this.searchQuery);
+  }
+  // 使用百度搜索
+  fetchBaiduSearchResults(query: string) {
+    // 使用百度的搜索 URL
+    const url = `http://localhost:3000/search?q=${encodeURIComponent(query)}`;
+    const headers = new HttpHeaders({
+      'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
+      'Referer': 'https://www.baidu.com',
+      'Accept-Language': 'zh-CN,zh;q=0.9',
+      'Connection': 'keep-alive',
+    });
+    // 发起 HTTP 请求获取搜索结果(可以使用第三方代理来避免跨域问题)
+    this.http.get(url, { responseType: 'text' }).subscribe(response => {
+      // 处理搜索结果
+      this.parseBaiduSearchResults(response);
+      console.log(response)
+    });
   }
   }
 
 
-  // 设置推荐问题为查询内容
-  setQuery(question: string) {
-    this.userQuery = question;
-    this.fetchAnswer();
+  // 简单的解析百度搜索结果(这里只是展示了一个基础的解析方式)
+  parseBaiduSearchResults(response: string) {
+    // 通过正则解析百度返回的 HTML 获取搜索结果标题和链接
+    const resultPattern = /<h3 class="t"><a href="([^"]+)"[^>]*>(.*?)<\/a><\/h3>/g;
+    let match;
+    const results = [];
+
+    // 使用正则匹配搜索结果
+    while ((match = resultPattern.exec(response)) !== null) {
+      results.push({
+        title: match[2],  // 搜索结果标题
+        link: match[1],   // 搜索结果链接
+      });
+    }
+
+    // 更新搜索结果数组
+    this.searchResults = results;
   }
   }
-}
+}

+ 11 - 7
src/app/tab3/tab3.page.html

@@ -5,21 +5,25 @@
 </ion-header>
 </ion-header>
 
 
 <ion-content [fullscreen]="true" style="--background: url('/assets/images/background.jpg') no-repeat center/cover;">
 <ion-content [fullscreen]="true" style="--background: url('/assets/images/background.jpg') no-repeat center/cover;">
-  <div class="image-container">
+  <div class="image-container" [ngClass]="{ 'destroyed': isDestroyed }">
     <!-- 背景框 -->
     <!-- 背景框 -->
-    <div class="background-frame">
+    <div class="background-frame" *ngIf="!isDestroyed">
       <!-- 图片显示区域 -->
       <!-- 图片显示区域 -->
-      <img [src]="imageSrc" alt="Selected Image" class="image" *ngIf="!isCameraMode && imageSrc" />
+      <img [src]="imageSrc" alt="Selected Image" class="image" *ngIf="!isDestroyed && !isCameraMode && imageSrc" />
       <!-- 视频流显示 -->
       <!-- 视频流显示 -->
-      <video #video *ngIf="isCameraMode && !imageCaptured && cameraAvailable" autoplay muted></video>
+      <video #video *ngIf="!isDestroyed && isCameraMode && !imageCaptured && cameraAvailable" autoplay muted></video>
       <!-- 占位文本 -->
       <!-- 占位文本 -->
-      <p class="placeholder-text" *ngIf="!imageSrc && !isCameraMode">No Image Selected</p>
-      <p class="placeholder-text" *ngIf="isCameraMode && (!cameraAvailable || imageCaptured)">Camera not available</p>
+      <p class="placeholder-text" *ngIf="!isDestroyed && !imageSrc && !isCameraMode">No Image Selected</p>
+      <p class="placeholder-text" *ngIf="!isDestroyed && isCameraMode && (!cameraAvailable || imageCaptured)">Camera not available</p>
     </div>
     </div>
     <!-- 切换图标 -->
     <!-- 切换图标 -->
-    <ion-button fill="clear" class="toggle-button" (click)="toggleMode()">
+    <ion-button fill="clear" class="toggle-button" *ngIf="!isDestroyed" (click)="toggleMode()">
       <ion-icon [name]="isCameraMode ? 'image' : 'camera'"></ion-icon>
       <ion-icon [name]="isCameraMode ? 'image' : 'camera'"></ion-icon>
     </ion-button>
     </ion-button>
+    <!-- 切换卷轴按钮 -->
+    <ion-button fill="solid" class="toggle-roll-button" (click)="toggleBackground()">
+      <ion-icon [name]="isDestroyed ? 'chevron-down-outline' : 'chevron-up-outline'"></ion-icon>
+    </ion-button>
   </div>
   </div>
   <!-- 上传图片按钮 -->
   <!-- 上传图片按钮 -->
   <div *ngIf="!isCameraMode" class="upload-container">
   <div *ngIf="!isCameraMode" class="upload-container">

+ 40 - 1
src/app/tab3/tab3.page.scss

@@ -13,7 +13,21 @@ align-items: center;
 border-radius: 10px;
 border-radius: 10px;
 overflow: hidden;
 overflow: hidden;
 margin-top: 0px;
 margin-top: 0px;
-background: url('/assets/images/recognition-background.png') no-repeat center/cover;
+background: url('/assets/images/recognition-background1.png') no-repeat center/cover;
+transition: all 0.5s ease-in-out; /* 添加过渡动画 */
+}
+.image-container.destroyed {
+  position: relative;
+  width: 430px;
+  height: 90px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  border-radius: 10px;
+  overflow: hidden;
+  margin-top: 0px;
+  background: url('/assets/images/recognition-background2.png') no-repeat center/cover; /* 切换后的背景 */
+
 }
 }
 .background-frame {
 .background-frame {
 position: relative;
 position: relative;
@@ -50,6 +64,31 @@ right: 40px;
 z-index: 10;
 z-index: 10;
 color: black;
 color: black;
 }
 }
+.toggle-roll-button {
+  --background: none;
+  position: absolute; 
+  bottom: -25px; 
+  left: 50%; 
+  transform: translateX(-50%); 
+  z-index: 10; 
+  background-color: rgba(255, 255, 255, 0.8);
+  border-top-left-radius: 20px; 
+  border-top-right-radius: 20px; 
+  border-bottom-left-radius: 0px; 
+  border-bottom-right-radius: 0px; 
+  width: 200px; 
+  height: 20px; 
+  display: flex; 
+  justify-content: center; 
+  align-items: center; 
+  box-shadow: 0px 6px 10px rgba(0, 0, 0, 0.3);
+  border: 1px solid rgba(0, 0, 0, 0.1); 
+}
+.toggle-roll-button ion-icon {
+  font-size: 20px; /* 设置图标大小 */
+  color: gray;
+  margin-bottom: 0px;
+}
 .button-group {
 .button-group {
 display: flex;
 display: flex;
 flex-direction: column; /* 垂直排列 */
 flex-direction: column; /* 垂直排列 */

+ 62 - 14
src/app/tab3/tab3.page.ts

@@ -17,7 +17,8 @@ export class Tab3Page implements AfterViewInit{
   imageSrc: string | null = null; // 保存图片数据
   imageSrc: string | null = null; // 保存图片数据
   videoStream: MediaStream | null = null; // 保存视频流
   videoStream: MediaStream | null = null; // 保存视频流
   showAlert: boolean = false; // 是否显示弹窗
   showAlert: boolean = false; // 是否显示弹窗
-  recognitionResults: { result: string; confidence: string; details: string }[] = []; // 动态识别结果
+  isDestroyed: boolean = false; // 管理背景和相关元素的状态
+  recognitionResults: { result: string; confidence: string}[] = []; // 动态识别结果
   constructor(private modalController: ModalController) {
   constructor(private modalController: ModalController) {
     this.checkCameraAvailability();
     this.checkCameraAvailability();
   }
   }
@@ -37,6 +38,23 @@ export class Tab3Page implements AfterViewInit{
     console.log('Canvas Element:', this.canvasElement);
     console.log('Canvas Element:', this.canvasElement);
     console.log('File Input Element:', this.fileInput);
     console.log('File Input Element:', this.fileInput);
   }
   }
+  // 卷轴卷起/放下
+  toggleBackground() {
+    this.isDestroyed = !this.isDestroyed;
+    if (this.isDestroyed) {
+       // 销毁视频流
+       if (this.videoStream) {
+        const tracks = this.videoStream.getTracks();
+        tracks.forEach((track) => track.stop());
+        this.videoStream = null;
+      }
+      this.imageSrc = null; // 清除图片数据
+      this.isCameraMode = false; // 停止摄像头模式
+    } else {
+      // 恢复摄像头功能
+      this.checkCameraAvailability();
+    }
+  }
   // 切换模式
   // 切换模式
   toggleMode() {
   toggleMode() {
     this.isCameraMode = !this.isCameraMode;
     this.isCameraMode = !this.isCameraMode;
@@ -47,6 +65,10 @@ export class Tab3Page implements AfterViewInit{
   }
   }
   // 选择图片
   // 选择图片
   selectImage() {
   selectImage() {
+    if (this.isDestroyed) {
+      alert('当前功能已禁用,请先恢复背景!');
+      return;
+    }
     if (this.fileInput) {
     if (this.fileInput) {
       this.fileInput.nativeElement.click();
       this.fileInput.nativeElement.click();
     } else {
     } else {
@@ -66,6 +88,10 @@ export class Tab3Page implements AfterViewInit{
   }
   }
   // 启动摄像头
   // 启动摄像头
   async startCamera() {
   async startCamera() {
+    if (this.isDestroyed) {
+      alert('当前功能已禁用,请先恢复背景!');
+      return;
+    }
     try {
     try {
       this.isCameraMode = true;
       this.isCameraMode = true;
       this.imageCaptured = false;
       this.imageCaptured = false;
@@ -133,12 +159,11 @@ export class Tab3Page implements AfterViewInit{
             confidence: response.prediction.confidence
             confidence: response.prediction.confidence
             ? response.prediction.confidence.toFixed(3) 
             ? response.prediction.confidence.toFixed(3) 
             : '未知置信度',
             : '未知置信度',
-            details: response.prediction.details || '未知详情',
           };
           };
           // 将新结果添加到识别结果数组
           // 将新结果添加到识别结果数组
         this.recognitionResults.push(newResult);
         this.recognitionResults.push(newResult);
         // 显示陶瓷详情页面
         // 显示陶瓷详情页面
-        await this.openCeramicDetails(newResult.result);
+        await this.openCeramicDetails(newResult.result, newResult.confidence); // 传递两个参数
       })
       })
     }
     }
     catch(error) {
     catch(error) {
@@ -147,22 +172,45 @@ export class Tab3Page implements AfterViewInit{
     };
     };
   }
   }
   // 显示陶瓷详情模态框
   // 显示陶瓷详情模态框
-  async openCeramicDetails(ceramicName: string) {
+  async openCeramicDetails(ceramicName: string, confidence: string) {
     // 定义陶瓷信息映射表
     // 定义陶瓷信息映射表
     const ceramicInfo: { [key: string]: { description: string; imageUrl: string } } = {
     const ceramicInfo: { [key: string]: { description: string; imageUrl: string } } = {
       '兔毫盏': {
       '兔毫盏': {
-        description: '兔毫盏是一种经典的陶瓷器具,以其细长如兔毫的纹路闻名。',
-        imageUrl: 'assets/images/tuhazhan.jpg',
+        description: '兔毫盏是一种特殊的黑釉瓷器,以其如丝似毫的窑变色彩流纹命名。它的特点是在黑釉中有丝状黑褐色兔毛般结晶,俗称“兔毫”。兔毫盏在宋代非常流行,与当时的饮茶风气有关,特别是“斗茶”习俗。宋代的兔毫盏以福建省建阳县水吉镇建窑烧造的最为著名,其胎体厚实、坚致,色呈浅黑或紫黑,器型以碗、盏为主。兔毫盏的析晶斑纹为黑色釉层中透出均匀细密的丝状筋脉条纹,形如兔子的毫毛,故得此名。宋代文人对兔毫盏多有赞美之辞,如蔡襄《茶录》云:“兔毫紫瓯新,蟹眼清泉煮。”宋徽宗赵佶在《大观茶论》中称“盏色贵青黑,玉毫条达者为上。”指的就是兔毫盏。',
+        imageUrl: 'assets/images/Ceramics/tuhaozhan.jpg',
       },
       },
       '凤纹盏': {
       '凤纹盏': {
-        description: '凤纹盏是一种以凤纹为装饰的陶瓷,展现高贵的文化气息。',
-        imageUrl: 'assets/images/fengwenzhan.jpg',
+        description: '凤纹盏是一种具有独特装饰的茶盏,常见于宋代吉州窑的作品中。其特点包括敞口外撇、弧腹壁、圈足,盏内彩绘或剪纸贴花装饰有凤纹,凤纹笔意潇洒,具有民间气息。凤纹盏的制作工艺独特,如剪纸贴花是将民间剪纸艺术与瓷器装饰相结合,先在坯体上施一层含铁量较高的釉,贴上剪纸图案,再施一层含铁量较低的釉,揭掉剪纸后入窑高温烧成。凤纹盏不仅具有实用价值,也是宋代瓷器装饰艺术的重要代表,反映了当时的审美风格和文化内涵。',
+        imageUrl: 'assets/images/Ceramics/fengwenzhan.jpg',
       },
       },
       '剪纸贴花盏': {
       '剪纸贴花盏': {
-        description: '剪纸贴花盏以独特的剪纸贴花艺术装饰,工艺精美。',
-        imageUrl: 'assets/images/jianzhitiehuazhan.jpg',
+        description: '剪纸贴花盏是一种将剪纸艺术与瓷器制作相结合的独特装饰手法。这种工艺最早出现在宋代吉州窑,工匠们将传统的剪纸纹样移植到黑釉瓷器上,赋予了沉闷单调的黑瓷以民间艺术之美。剪纸贴花盏的制作过程包括将剪好的图案贴于胎体上,然后施加黑釉,揭掉剪纸后一次烧制成功。常见的剪纸纹饰有双龙、双凤、朵花、花卉飞凤、梅花鹿、梅花竹枝和长命富贵、福寿康宁、福山寿海、金玉满堂等吉语。这种装饰手法在民国时期也曾流行,成为一种具有浓郁民族特色的陶瓷装饰艺术。',
+        imageUrl: 'assets/images/Ceramics/jianzhitiehuazhan.jpg',
+      },
+      '玳瑁釉盏': {
+        description: '玳瑁釉盏是一种具有独特艺术魅力的瓷器,其釉色酷似玳瑁海龟的甲壳花纹,因此得名。玳瑁釉盏的制作工艺复杂,属于窑变釉,每一件作品的花纹都是独一无二的。它在宋代时期非常流行,尤其是在吉州窑的产品中,玳瑁釉盏与木叶盏、剪纸贴花盏一并饮誉中外。玳瑁釉盏的复兴在上世纪80年代取得了成功,如今它仍然是收藏家和茶艺爱好者所珍视的对象。',
+        imageUrl: 'assets/images/Ceramics/daimaoyouzhan.jpg',
+      },
+      '梅瓶': {
+        description: '梅瓶是一种流行于宋辽时期的瓷器,其器形得名较晚,历史上曾被称为“经瓶”。梅瓶的特点是小口、短颈、丰肩、瘦底、圈足,因口小只能插梅枝而得名。它既是酒器,又是观赏品,制作精美,考虑到贮酒容量和造型优美。梅瓶最早出现于唐代,盛行于宋代,元代继承宋代形制并有所发展,明清时期御窑厂大量制造,造型越来越优美,用途也更加多样化,成为身份和地位的象征。',
+        imageUrl: 'assets/images/Ceramics/meiping.jpg',
+      },
+      '黑釉盏': {
+        description: '黑釉盏是一种在宋代流行的茶具,以其独特的黑色釉面闻名。它的设计和制作工艺在宋代达到了巅峰,尤其是福建建阳窑、福清窑、江西吉州窑的黑釉盏最为著名。黑釉盏的流行与宋代的斗茶风俗密切相关,其深沉的釉色能够很好地衬托出白色的茶沫,因此受到了斗茶者的喜爱。黑釉盏不仅在国内享有盛誉,还曾一度成为宫廷御用的茶具,其影响甚至远播至日本等国。',
+        imageUrl: 'assets/images/Ceramics/heiyouhan.jpg',
+      },
+      '梅纹盏': {
+        description: '梅纹盏是一种具有独特装饰纹样的瓷器,主要流行于宋代。这种瓷器的装饰纹样以梅花为主,梅花在宋代文人的心目中具有高洁、傲骨的象征意义,因此在瓷器装饰中广泛应用。梅纹盏的制作工艺多样,包括黑釉彩绘、剪纸贴花、剔花等多种技法,其中以吉州窑的梅纹盏最为著名。这些梅纹盏不仅具有观赏价值,还反映了宋代的文化品位和审美体验。',
+        imageUrl: 'asset/images/Ceramics/meiwenzhan.jpg',
+      },
+      '鹧鸪斑盏': {
+        description: '鹧鸪斑盏是一种宋代烧制的黑釉茶盏,其釉面呈现出鹧鸪鸟胸部羽毛般的白点正圆如珠的斑纹,因此得名。鹧鸪斑盏的烧制工艺复杂,成品极为难得,因其烧制条件要求非常高,所以成品凤毛麟角,佳品独特难得。鹧鸪斑盏在宋代时期并非主流社会推崇的产品,当时更受欢迎的是兔毫盏,但它却反映了当时茶文化的繁荣和审美观念的多样性,为研究宋代茶文化提供了重要的实物资料。',
+        imageUrl: 'assets/images/Ceramics/zhegubanzhan.jpg',
+      },
+      '木叶天目盏': {
+        description: '木叶天目盏是一种起源于南宋吉州窑的独特瓷器,其制作工艺是将木叶置于施完天目釉的坯体之上,经过高温烧制,木叶高温氧化自然落灰,木叶灰与底层釉面高温融合,浑然天成形成木叶纹理。这种茶盏的树叶专门选用桑叶,有禅宗文化的背景,桑叶与禅在当时存在特殊的关联。木叶天目盏的胎质紧致,盏内木叶茎脉清晰、栩栩如生,釉面光滑平整,树叶与釉面融合在一个平面上,用手触摸无突兀感。注水后,木叶盏中的叶片纹路似雨后新叶悠然飘至盏底。由于木叶在高温下的变化难以预测,加之手工操作的不可复制性,使得每一件木叶盏都是独一无二的艺术品。',
+        imageUrl: 'assets/images/Ceramics/muyetianmuzhan.jpg',
       },
       },
-      // 添加其他陶瓷信息...
     };
     };
     const ceramicDetails = ceramicInfo[ceramicName] || {
     const ceramicDetails = ceramicInfo[ceramicName] || {
       description: '暂无详细信息。',
       description: '暂无详细信息。',
@@ -180,9 +228,9 @@ export class Tab3Page implements AfterViewInit{
     await modal.present();
     await modal.present();
   }
   }
   // 查看详情事件
   // 查看详情事件
-  viewDetails(item: { result: string; confidence: string; details: string }) {
+  async viewDetails(item: { result: string; confidence: string }) {
     console.log('查看详情:', item);
     console.log('查看详情:', item);
-    // 在此实现查看详情的逻辑
-    alert(`结果: ${item.result}\n置信度: ${item.confidence}\n详情: ${item.details}`);
+    // 跳转到陶瓷详情模态框
+    await this.openCeramicDetails(item.result, item.confidence);
   }
   }
 }
 }

二進制
src/assets/images/Ceramics/daimaoyouzhan.jpg


二進制
src/assets/images/Ceramics/fengwenzhan.jpg


二進制
src/assets/images/Ceramics/heiyouhan.jpg


二進制
src/assets/images/Ceramics/jianzhitiehuazhan.jpg


二進制
src/assets/images/Ceramics/meiping.jpg


二進制
src/assets/images/Ceramics/meiwenzhan.jpg


二進制
src/assets/images/Ceramics/muyetianmuzhan.jpg


二進制
src/assets/images/Ceramics/tuhaozhan.jpg


二進制
src/assets/images/Ceramics/zhegubanzhan.jpg


二進制
src/assets/images/KG-background.png


二進制
src/assets/images/ceramics-background.png


二進制
src/assets/images/details-background.png


+ 0 - 0
src/assets/images/recognition-background.png → src/assets/images/recognition-background1.png


二進制
src/assets/images/recognition-background2.png


二進制
src/assets/images/slide1.jpg


二進制
src/assets/images/slide2.jpg


二進制
src/assets/images/slide3.jpg


二進制
src/assets/images/slide4.jpg


+ 31 - 0
src/assets/json/graph.json

@@ -0,0 +1,31 @@
+{
+  "nodes": [
+    { "id": 1, "label": "吉州窑", "color": "#a67b5b", "details": "吉州窑是中国传统制瓷工艺的代表之一,拥有超过1200年的历史。它不仅是江西吉安地区的历史瑰宝,也代表了中国古代陶瓷技术的巅峰。作为江南地区最重要的陶瓷生产基地之一,吉州窑以其精美的黑釉瓷和天目釉瓷著称,展现了中原文化与地方工艺的融合。其器物造型和纹样多样,充分体现了汉族艺术的精细与创新。" },
+    { "id": 2, "label": "地理位置", "color": "#d4a373", "details": "吉州窑位于江西省吉安市永和镇,距离吉安市约8公里,地理位置优越,位于赣江流域的关键位置。该地交通便利,土壤和气候条件适合陶瓷生产,丰富的陶土资源为吉州窑的陶瓷制造提供了充足的原材料。永和镇周围的自然环境也为吉州窑的艺术创作提供了灵感,形成了独特的地方风格。" },
+    { "id": 3, "label": "历史沿革", "color": "#e0c097", "details": "吉州窑的历史可以追溯到晚唐时期,它在五代、北宋时期逐渐兴起,并在南宋达到了鼎盛。尽管到了元代末期逐渐衰落,但它在中国陶瓷史上仍占有极为重要的地位。吉州窑的崛起和发展不仅得益于当地的资源条件,还与当时的社会经济发展和文化繁荣息息相关。宋代吉州窑的陶瓷生产技艺,特别是黑釉瓷和天目釉瓷,成为中国古代陶瓷艺术的重要代表。" },
+    { "id": 4, "label": "工艺与产品", "color": "#c7a18b", "details": "吉州窑以其独特的黑釉瓷和天目釉瓷闻名,特别是木叶天目、玳瑁天目和剪纸贴花天目等独创性技艺,令其陶瓷作品别具一格。此外,吉州窑的生产种类丰富,包括乳白釉、青釉、绿釉等类型,器物形制涵盖碗、盏、瓶、罐、枕、盆等各种实用和装饰性陶瓷。其黑釉瓷以其釉面变化和独特的窑变色斑,如油滴斑、兔毫斑、洒釉等著称,体现了宋代瓷器的精湛工艺与艺术魅力。" },
+    { "id": 5, "label": "文化与影响", "color": "#f4b183", "details": "吉州窑不仅仅是一种陶瓷生产技术的体现,它更是中华文化艺术的一部分。吉州窑将中原的制瓷工艺与吉州本地的文化特色相结合,创造出符合当时审美的器物,且多采用了极具地方特色的装饰技法,如木叶、玳瑁、剪纸贴花等。吉州窑的陶瓷产品具有浓厚的民间文化色彩,曾在中国和世界范围内的文化交流中扮演重要角色,尤其在宋元时期,成为东西方贸易的重要商品。" },
+    { "id": 6, "label": "国际影响", "color": "#f7c59f", "details": "吉州窑的陶瓷作品在国际间享有极高声誉,尤其在古代中东和欧洲的王室贵族中备受推崇。吉州瓷器的高质量和独特美感使其成为文化交流的载体。许多吉州窑的传世珍品,如兔毫斑、鹧鸪斑和玳瑁斑,现存于世界各大博物馆。吉州窑的影响不仅限于中国,其在日本、韩国、英国等国家的陶瓷收藏中也占有一席之地。" },
+    { "id": 7, "label": "历史与成就", "color": "#d4a276", "details": "吉州窑在中国陶瓷史上具有举足轻重的地位,它不仅为宋代瓷业的发展做出了重要贡献,还对后世的瓷器生产产生了深远影响。吉州窑烧制的120多种器型,如碗、盏、碟、瓶、罐、枕等,展示了极高的工艺水平和丰富的艺术风格。吉州窑是中国古代黑釉瓷的代表性产地之一,它独特的釉面和烧制技术,成为了中国瓷器的重要代表。" },
+    { "id": 8, "label": "国际贸易与珍藏", "color": "#e4c290", "details": "吉州窑陶瓷在宋元时期成为中国陶瓷贸易的重心之一,广泛出口到日本、韩国、中东、欧洲等地,成为世界各地文化交流的重要组成部分。许多吉州窑的名贵瓷器在日本博物馆、韩国博物馆和英国博物馆中珍藏,并被视为国宝。例如,日本的剪纸贴花盏被誉为国宝,而韩国和英国的吉州窑作品也被视为陶瓷艺术的瑰宝。" },
+    { "id": 9, "label": "现代复兴", "color": "#f9d8a8", "details": "自1982年吉州窑古陶瓷研究所成立以来,吉州窑的陶瓷技术和文化逐步得到复兴和保护。通过仿古瓷、陈设瓷等的生产,吉州窑重新进入国际市场。如今,吉州窑的现代陶瓷产品已经进入美国、英国、法国、日本等国家的市场,成为世界陶瓷文化的重要组成部分。" },
+    { "id": 10, "label": "吉州窑的保护", "color": "#bfa580", "details": "吉州窑遗址是中国现存最为完好的古代名窑遗址之一,2001年被列为全国重点文物保护单位。为了保护这一历史遗产,吉安市制定了科学的保护计划,每年投入专款用于遗址的修复和保护。与此同时,当地政府积极推动吉州窑的开发与文化旅游,努力将其打造为历史文化名镇。" },
+    { "id": 11, "label": "类别与纹样", "color": "#dacaa2", "details": "吉州窑的陶瓷种类繁多,涵盖了青釉、黑釉、乳白釉、白釉彩绘、绿釉等多种釉色。吉州窑的装饰技法极为丰富,包括木叶、玳瑁、洒釉、剪纸贴花、剔花、印花、彩绘等,表现出极高的艺术水准。纹样装饰既有传统的自然主题,如梅花、竹枝、飞蝶等,也有吉祥寓意的图案,如双鱼戏水、跃鹿、鹊喜等,体现了宋代民间文化的深厚底蕴。" },
+    { "id": 12, "label": "瓷器种类", "color": "#e6c690", "details": "吉州窑的瓷器种类丰富,主要包括碗、盏、瓶、罐、枕、盆等,既有实用器具,也有精美的装饰品。每件器物的造型都经过精心设计,不仅功能性强,而且艺术感十足。特别是在北宋至南宋时期,吉州窑的瓷器常常以其独特的造型和釉色成为收藏家和艺术爱好者的珍品。" },
+    { "id": 13, "label": "遗址现状", "color": "#f2e0b0", "details": "吉州窑遗址位于江西吉安市永和镇西侧,现存24处古窑遗址,是世界上已知最大的古窑遗址群。遗址周围的古街道和窑址展示了古代瓷器生产的繁荣景象。为保护这一文化遗产,永和镇已建立了完善的保护体系,并不断推进遗址的研究与开发,使吉州窑的历史和文化得以传承。" }
+  ],
+  "edges": [
+    { "from": 1, "to": 2, "label": "地理关联" },
+    { "from": 1, "to": 3, "label": "历史传承" },
+    { "from": 1, "to": 4, "label": "产品与工艺" },
+    { "from": 1, "to": 5, "label": "文化贡献" },
+    { "from": 1, "to": 6, "label": "国际影响" },
+    { "from": 1, "to": 7, "label": "历史与成就" },
+    { "from": 7, "to": 8, "label": "贸易与珍藏" },
+    { "from": 8, "to": 9, "label": "现代延续" },
+    { "from": 1, "to": 10, "label": "保护措施" },
+    { "from": 1, "to": 11, "label": "装饰艺术" },
+    { "from": 11, "to": 12, "label": "瓷器种类" },
+    { "from": 1, "to": 13, "label": "遗址现状" }
+  ]
+}

+ 1 - 23
src/global.scss

@@ -35,27 +35,5 @@
 /* @import "@ionic/angular/css/palettes/dark.always.css"; */
 /* @import "@ionic/angular/css/palettes/dark.always.css"; */
 /* @import "@ionic/angular/css/palettes/dark.class.css"; */
 /* @import "@ionic/angular/css/palettes/dark.class.css"; */
 @import "@ionic/angular/css/palettes/dark.system.css";
 @import "@ionic/angular/css/palettes/dark.system.css";
+@import 'swiper/swiper-bundle.min.css';
 
 
-.custom-modal {
-    --width: 100%; /* 宽度占满屏幕 */
-    --height: 50%; /* 高度占据屏幕下半部分 */
-    --border-radius: 20px 20px 0 0; /* 顶部圆角 */
-    --margin-top: auto; /* 将模态框置于底部 */
-    --box-shadow: 0px -4px 10px rgba(0, 0, 0, 0.2); /* 添加顶部阴影 */
-    --background: white; /* 背景色 */
-  
-    position: fixed; /* 使用固定定位 */
-    bottom: 0; /* 固定在屏幕底部 */
-    left: 0; /* 水平居中 */
-    animation: slide-up 0.8s ease-in-out; /* 滑动动画 */
-  }
-  
-  /* 动画:模态框从底部滑入 */
-  @keyframes slide-up {
-    from {
-      transform: translateY(100%); /* 初始位置在屏幕下方 */
-    }
-    to {
-      transform: translateY(0); /* 滑动到原始位置 */
-    }
-  }