Browse Source

feat: knowlege

chenlei 4 weeks ago
parent
commit
34175166aa
91 changed files with 2486 additions and 14 deletions
  1. 2 0
      .vscode/settings.json
  2. 5 2
      package.json
  3. 45 0
      public/echarts-v5.4.3.js
  4. 7 3
      public/index.html
  5. BIN
      public/myData/knowlegeImg/bcfjzxdzgh--bwwq-hngxskdyk.jpg
  6. BIN
      public/myData/knowlegeImg/bcfjzxdzgh--bwzwq-bwygskd6kzxtzxsps.jpg
  7. BIN
      public/myData/knowlegeImg/bcfjzxdzgh--dwbq-bqbxtskd4kpsx.jpg
  8. BIN
      public/myData/knowlegeImg/bcfjzxdzgh--dwbq-bqbxtsskdskyb.jpg
  9. BIN
      public/myData/knowlegeImg/bcfjzxdzgh--dwbq-dwtlsskd2kbbk.jpg
  10. BIN
      public/myData/knowlegeImg/bcfjzxdzgh-bwzwq-bwygskd6kdbncfk.jpg
  11. BIN
      public/myData/knowlegeImg/bcfjzxdzgh-bwzwq-lmskbyzd.jpg
  12. BIN
      public/myData/knowlegeImg/bcfjzxdzgh-bwzzq-bwygskd19kybxsps.jpg
  13. BIN
      public/myData/knowlegeImg/bcfjzxdzgh-bwzzq-gy420nbls169k.jpg
  14. BIN
      public/myData/knowlegeImg/bcfjzxdzgh-bwzzq-ygskd20kfx.jpg
  15. BIN
      public/myData/knowlegeImg/bcfjzxdzgh-dwbq-bqbxtskzxfzzdkpsx.jpg
  16. BIN
      public/myData/knowlegeImg/bcfjzxdzgh-dwbq-bqnxtskd1kzxzzbk.jpg
  17. BIN
      public/myData/knowlegeImg/bcfjzxdzgh-xwbz-xwmjsskd135kzb.jpg
  18. BIN
      public/myData/knowlegeImg/bcfjzxdzgh-xwbz-xwmjsskd44k.jpg
  19. BIN
      public/myData/knowlegeImg/bcfjzxdzgh-xwbzbzxxmd51khbsdk.jpg
  20. BIN
      public/myData/knowlegeImg/bjzcyczb-bc-ezxmz-1.png
  21. BIN
      public/myData/knowlegeImg/bjzcyczb-bc-ezxmz-2.png
  22. BIN
      public/myData/knowlegeImg/bjzcyczb-bc-hgmz.png
  23. BIN
      public/myData/knowlegeImg/bjzcyczb-bc-lxmz-1.png
  24. BIN
      public/myData/knowlegeImg/bjzcyczb-bc-lxmz-2.png
  25. BIN
      public/myData/knowlegeImg/bjzcyczb-bc-lxmz-3.png
  26. BIN
      public/myData/knowlegeImg/bjzcyczb-bc-lxmz-4.png
  27. BIN
      public/myData/knowlegeImg/bjzcyczb-bc-rhmz.jpg
  28. BIN
      public/myData/knowlegeImg/bjzcyczb-bc-shzmzm-1.jpg
  29. BIN
      public/myData/knowlegeImg/bjzcyczb-bc-shzmzm-2.jpg
  30. BIN
      public/myData/knowlegeImg/bjzcyczb-bc-smjlmb-1.png
  31. BIN
      public/myData/knowlegeImg/bjzcyczb-bc-smjlmb-2.png
  32. BIN
      public/myData/knowlegeImg/bjzcyczb-bc-yhmz-1.png
  33. BIN
      public/myData/knowlegeImg/bjzcyczb-bc-yhmz-2.png
  34. BIN
      public/myData/knowlegeImg/bjzcyczb-bc-ymmz.jpg
  35. BIN
      public/myData/knowlegeImg/bjzcyczb-bc-ytmmz-1.jpg
  36. BIN
      public/myData/knowlegeImg/bjzcyczb-bc-ytmmz-2.png
  37. BIN
      public/myData/knowlegeImg/bjzcyczb-bc-yymz.png
  38. BIN
      public/myData/knowlegeImg/bjzcyczb-djsq-wxzffmz-1.png
  39. BIN
      public/myData/knowlegeImg/bjzcyczb-djsq-wxzffmz-2.jpg
  40. BIN
      public/myData/knowlegeImg/bjzcyczb-djsq-xkmz-1.png
  41. BIN
      public/myData/knowlegeImg/bjzcyczb-djsq-xkmz-2.jpg
  42. BIN
      public/myData/knowlegeImg/bjzcyczb-lhzj-jjb-1.png
  43. BIN
      public/myData/knowlegeImg/bjzcyczb-lhzj-jjb-2.jpg
  44. BIN
      public/myData/knowlegeImg/bjzcyczb-lhzj-jjb-3.jpg
  45. BIN
      public/myData/knowlegeImg/bjzcyczb-lhzj-yab-1.png
  46. BIN
      public/myData/knowlegeImg/bjzcyczb-lhzj-yab-2.png
  47. BIN
      public/myData/knowlegeImg/bjzcyczb-nc-xdb.jpg
  48. BIN
      public/myData/knowlegeImg/bjzcyczb-xjsq-chmz.jpg
  49. BIN
      public/myData/knowlegeImg/bjzcyczb-xjsq-xyzm-1.png
  50. BIN
      public/myData/knowlegeImg/bjzcyczb-xjsq-xyzm-2.png
  51. BIN
      public/myData/knowlegeImg/ckb-1.png
  52. BIN
      public/myData/knowlegeImg/ckb-2.png
  53. BIN
      public/myData/knowlegeImg/czbszys-fyw-bqtbsnfyw.png
  54. BIN
      public/myData/knowlegeImg/czbszys-fyw-ypsnfyw.png
  55. BIN
      public/myData/knowlegeImg/czbszys-mzw-gfmz.png
  56. BIN
      public/myData/knowlegeImg/czbszys-mzw-lzhmz.png
  57. BIN
      public/myData/knowlegeImg/czbzxys-cthhyxk-1.jpg
  58. BIN
      public/myData/knowlegeImg/czbzxys-cthhyxk-2.jpg
  59. BIN
      public/myData/knowlegeImg/czbzxys-dfsgyr.jpg
  60. BIN
      public/myData/knowlegeImg/czbzxys-fdfggfd.jpg
  61. BIN
      public/myData/knowlegeImg/czbzxys-zxrh-ft.png
  62. BIN
      public/myData/knowlegeImg/dyb-1.png
  63. BIN
      public/myData/knowlegeImg/dyb-2.png
  64. BIN
      public/myData/knowlegeImg/gssdb.png
  65. BIN
      public/myData/knowlegeImg/hyb.png
  66. BIN
      public/myData/knowlegeImg/tp-bw.png
  67. BIN
      public/myData/knowlegeImg/tp-tx.png
  68. BIN
      public/myData/knowlegeImg/xt-bw.png
  69. BIN
      public/myData/knowlegeImg/xt-tx.png
  70. 1379 0
      public/myData/myData.js
  71. 2 0
      src/App.tsx
  72. 169 0
      src/pages/A9knowlege/components/Chart/index.module.scss
  73. 209 0
      src/pages/A9knowlege/components/Chart/index.tsx
  74. 26 0
      src/pages/A9knowlege/components/ModelPanel/index.module.scss
  75. 29 0
      src/pages/A9knowlege/components/ModelPanel/index.tsx
  76. 54 0
      src/pages/A9knowlege/components/Panel/index.module.scss
  77. 42 0
      src/pages/A9knowlege/components/Panel/index.tsx
  78. 50 0
      src/pages/A9knowlege/components/Panel2/index.module.scss
  79. 48 0
      src/pages/A9knowlege/components/Panel2/index.tsx
  80. BIN
      src/pages/A9knowlege/images/bg_jiaohu-min.jpg
  81. BIN
      src/pages/A9knowlege/images/btn_close_red.png
  82. BIN
      src/pages/A9knowlege/images/frame_01_01.png
  83. BIN
      src/pages/A9knowlege/images/frame_01_03.png
  84. BIN
      src/pages/A9knowlege/images/icon_flower_red.png
  85. BIN
      src/pages/A9knowlege/images/img_pop_02-min.png
  86. BIN
      src/pages/A9knowlege/images/img_pop_03-min.png
  87. BIN
      src/pages/A9knowlege/images/line_04-min.png
  88. 41 0
      src/pages/A9knowlege/index.module.scss
  89. 141 0
      src/pages/A9knowlege/index.tsx
  90. 109 0
      src/utils/encrypt.ts
  91. 128 9
      yarn.lock

+ 2 - 0
.vscode/settings.json

@@ -1,2 +1,4 @@
 {
+  "editor.defaultFormatter": "esbenp.prettier-vscode",
+  "editor.formatOnSave": true
 }

+ 5 - 2
package.json

@@ -15,7 +15,9 @@
     "@types/react-dom": "^18.0.8",
     "antd": "^5.8.3",
     "antd-mobile": "^5.30.0",
-    "axios": "^1.7.9",
+    "axios": "^1.13.2",
+    "classnames": "^2.5.1",
+    "crypto-js": "^4.2.0",
     "i18next": "^25.6.3",
     "i18next-browser-languagedetector": "^8.2.0",
     "react": "^18.2.0",
@@ -59,10 +61,11 @@
     ]
   },
   "devDependencies": {
+    "@types/crypto-js": "^4.2.2",
     "@types/history": "^5.0.0",
     "@types/react-router-dom": "^5.3.3",
     "customize-cra": "^1.0.0",
     "react-app-rewired": "^2.2.1"
   },
   "homepage": "."
-}
+}

File diff suppressed because it is too large
+ 45 - 0
public/echarts-v5.4.3.js


+ 7 - 3
public/index.html

@@ -2,7 +2,10 @@
 <html lang="zh">
   <head>
     <meta charset="utf-8" />
-    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
+    <meta
+      name="viewport"
+      content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
+    />
     <meta name="theme-color" content="#000000" />
     <meta name="description" content="Web site created using create-react-app" />
     <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
@@ -17,7 +20,7 @@
         font-family: 'song';
         src: url('./myData/song.TTF');
       }
-      .fontLoding{
+      .fontLoding {
         position: absolute;
         top: 0;
         left: 0;
@@ -35,7 +38,7 @@
     <div id="panoramic-root"></div>
 
     <!-- 一进页面就加载字体 -->
-     <i class="fontLoding">123</i>
+    <i class="fontLoding">123</i>
   </body>
 
   <script>
@@ -52,6 +55,7 @@
     }
   </script>
 
+  <script src="./echarts-v5.4.3.js"></script>
   <!-- <script>
     window.onload = function () {
       var script = document.createElement('script')

BIN
public/myData/knowlegeImg/bcfjzxdzgh--bwwq-hngxskdyk.jpg


BIN
public/myData/knowlegeImg/bcfjzxdzgh--bwzwq-bwygskd6kzxtzxsps.jpg


BIN
public/myData/knowlegeImg/bcfjzxdzgh--dwbq-bqbxtskd4kpsx.jpg


BIN
public/myData/knowlegeImg/bcfjzxdzgh--dwbq-bqbxtsskdskyb.jpg


BIN
public/myData/knowlegeImg/bcfjzxdzgh--dwbq-dwtlsskd2kbbk.jpg


BIN
public/myData/knowlegeImg/bcfjzxdzgh-bwzwq-bwygskd6kdbncfk.jpg


BIN
public/myData/knowlegeImg/bcfjzxdzgh-bwzwq-lmskbyzd.jpg


BIN
public/myData/knowlegeImg/bcfjzxdzgh-bwzzq-bwygskd19kybxsps.jpg


BIN
public/myData/knowlegeImg/bcfjzxdzgh-bwzzq-gy420nbls169k.jpg


BIN
public/myData/knowlegeImg/bcfjzxdzgh-bwzzq-ygskd20kfx.jpg


BIN
public/myData/knowlegeImg/bcfjzxdzgh-dwbq-bqbxtskzxfzzdkpsx.jpg


BIN
public/myData/knowlegeImg/bcfjzxdzgh-dwbq-bqnxtskd1kzxzzbk.jpg


BIN
public/myData/knowlegeImg/bcfjzxdzgh-xwbz-xwmjsskd135kzb.jpg


BIN
public/myData/knowlegeImg/bcfjzxdzgh-xwbz-xwmjsskd44k.jpg


BIN
public/myData/knowlegeImg/bcfjzxdzgh-xwbzbzxxmd51khbsdk.jpg


BIN
public/myData/knowlegeImg/bjzcyczb-bc-ezxmz-1.png


BIN
public/myData/knowlegeImg/bjzcyczb-bc-ezxmz-2.png


BIN
public/myData/knowlegeImg/bjzcyczb-bc-hgmz.png


BIN
public/myData/knowlegeImg/bjzcyczb-bc-lxmz-1.png


BIN
public/myData/knowlegeImg/bjzcyczb-bc-lxmz-2.png


BIN
public/myData/knowlegeImg/bjzcyczb-bc-lxmz-3.png


BIN
public/myData/knowlegeImg/bjzcyczb-bc-lxmz-4.png


BIN
public/myData/knowlegeImg/bjzcyczb-bc-rhmz.jpg


BIN
public/myData/knowlegeImg/bjzcyczb-bc-shzmzm-1.jpg


BIN
public/myData/knowlegeImg/bjzcyczb-bc-shzmzm-2.jpg


BIN
public/myData/knowlegeImg/bjzcyczb-bc-smjlmb-1.png


BIN
public/myData/knowlegeImg/bjzcyczb-bc-smjlmb-2.png


BIN
public/myData/knowlegeImg/bjzcyczb-bc-yhmz-1.png


BIN
public/myData/knowlegeImg/bjzcyczb-bc-yhmz-2.png


BIN
public/myData/knowlegeImg/bjzcyczb-bc-ymmz.jpg


BIN
public/myData/knowlegeImg/bjzcyczb-bc-ytmmz-1.jpg


BIN
public/myData/knowlegeImg/bjzcyczb-bc-ytmmz-2.png


BIN
public/myData/knowlegeImg/bjzcyczb-bc-yymz.png


BIN
public/myData/knowlegeImg/bjzcyczb-djsq-wxzffmz-1.png


BIN
public/myData/knowlegeImg/bjzcyczb-djsq-wxzffmz-2.jpg


BIN
public/myData/knowlegeImg/bjzcyczb-djsq-xkmz-1.png


BIN
public/myData/knowlegeImg/bjzcyczb-djsq-xkmz-2.jpg


BIN
public/myData/knowlegeImg/bjzcyczb-lhzj-jjb-1.png


BIN
public/myData/knowlegeImg/bjzcyczb-lhzj-jjb-2.jpg


BIN
public/myData/knowlegeImg/bjzcyczb-lhzj-jjb-3.jpg


BIN
public/myData/knowlegeImg/bjzcyczb-lhzj-yab-1.png


BIN
public/myData/knowlegeImg/bjzcyczb-lhzj-yab-2.png


BIN
public/myData/knowlegeImg/bjzcyczb-nc-xdb.jpg


BIN
public/myData/knowlegeImg/bjzcyczb-xjsq-chmz.jpg


BIN
public/myData/knowlegeImg/bjzcyczb-xjsq-xyzm-1.png


BIN
public/myData/knowlegeImg/bjzcyczb-xjsq-xyzm-2.png


BIN
public/myData/knowlegeImg/ckb-1.png


BIN
public/myData/knowlegeImg/ckb-2.png


BIN
public/myData/knowlegeImg/czbszys-fyw-bqtbsnfyw.png


BIN
public/myData/knowlegeImg/czbszys-fyw-ypsnfyw.png


BIN
public/myData/knowlegeImg/czbszys-mzw-gfmz.png


BIN
public/myData/knowlegeImg/czbszys-mzw-lzhmz.png


BIN
public/myData/knowlegeImg/czbzxys-cthhyxk-1.jpg


BIN
public/myData/knowlegeImg/czbzxys-cthhyxk-2.jpg


BIN
public/myData/knowlegeImg/czbzxys-dfsgyr.jpg


BIN
public/myData/knowlegeImg/czbzxys-fdfggfd.jpg


BIN
public/myData/knowlegeImg/czbzxys-zxrh-ft.png


BIN
public/myData/knowlegeImg/dyb-1.png


BIN
public/myData/knowlegeImg/dyb-2.png


BIN
public/myData/knowlegeImg/gssdb.png


BIN
public/myData/knowlegeImg/hyb.png


BIN
public/myData/knowlegeImg/tp-bw.png


BIN
public/myData/knowlegeImg/tp-tx.png


BIN
public/myData/knowlegeImg/xt-bw.png


BIN
public/myData/knowlegeImg/xt-tx.png


File diff suppressed because it is too large
+ 1379 - 0
public/myData/myData.js


+ 2 - 0
src/App.tsx

@@ -29,6 +29,7 @@ const A6_1_zxys = React.lazy(() => import('./pages/A6ybwx/A6_1_zxys'))
 const A6_2_zxzgh = React.lazy(() => import('./pages/A6ybwx/A6_2_zxzgh'))
 // 墓影智慧
 const A8byzh = React.lazy(() => import('./pages/A8byzh'))
+const A9knowlege = React.lazy(() => import('./pages/A9knowlege'))
 
 declare global {
   //设置全局属性
@@ -581,6 +582,7 @@ export default function App() {
             <Route path='/zxys' component={A6_1_zxys} exact />
             <Route path='/sinicize' component={A6_2_zxzgh} exact />
             <Route path='/byzh' component={A8byzh} exact />
+            <Route path='/knowlege' component={A9knowlege} exact />
             <Route path='*' component={NotFound} />
           </Switch>
         </React.Suspense>

+ 169 - 0
src/pages/A9knowlege/components/Chart/index.module.scss

@@ -0,0 +1,169 @@
+.chart {
+  display: flex;
+  flex-direction: column;
+  gap: 10px;
+  position: absolute;
+  inset: 0;
+  padding: 28px 20px 20px 32px;
+}
+
+.chartWrap {
+  flex: 1;
+  margin: -5px -2px;
+  overflow-y: auto;
+  overflow-x: hidden;
+}
+
+.quickQuestions {
+  display: flex;
+  flex-wrap: wrap;
+}
+
+.messagesContainer {
+  display: flex;
+  flex-direction: column;
+  gap: 12px;
+  padding: 10px 0;
+}
+
+.message {
+  display: flex;
+  flex-direction: column;
+  max-width: 85%;
+  word-wrap: break-word;
+  word-break: break-word;
+
+  &_user {
+    align-self: flex-end;
+    align-items: flex-end;
+  }
+
+  &_assistant {
+    align-self: flex-start;
+    align-items: flex-start;
+  }
+}
+
+.messageContent {
+  padding: 8px 12px;
+  border-radius: 8px;
+  font-size: 12px;
+  line-height: 1.5;
+  color: #7c4b36;
+  background-color: rgba(255, 255, 255, 0.6);
+  border: 1px solid rgba(156, 120, 104, 0.3);
+  white-space: pre-wrap;
+}
+
+.message_user .messageContent {
+  background-color: rgba(124, 75, 54, 0.1);
+}
+
+.loadingText {
+  display: inline-block;
+  animation: pulse 1.5s ease-in-out infinite;
+}
+
+@keyframes pulse {
+  0%, 100% {
+    opacity: 1;
+  }
+  50% {
+    opacity: 0.5;
+  }
+}
+
+.chartFooter {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  gap: 8px;
+
+  &::before {
+    content: '';
+    display: block;
+    width: 217px;
+    height: 10px;
+    background: url('../../images/line_04-min.png') no-repeat center / contain;
+  }
+}
+
+.chartInput {
+  position: relative;
+  padding: 0 49px 0 13px;
+  width: 100%;
+  height: 36px;
+  border-radius: 50px;
+  border: 1px solid #7c4b36;
+
+  &::after {
+    content: '';
+    position: absolute;
+    top: 50%;
+    right: 10px;
+    width: 29px;
+    height: 22px;
+    background: url('../../images/icon_flower_red.png') no-repeat center / contain;
+    transform: translateY(-50%);
+  }
+  input {
+    width: 100%;
+    height: 100%;
+    border: none;
+    outline: none;
+    background: transparent;
+    color: #7c4b36;
+
+    &::placeholder {
+      opacity: 0.5;
+      color: #7c4b36;
+    }
+  }
+}
+
+.chartLog {
+  position: relative;
+  display: inline-block;
+  margin: 5px 10px;
+  color: #7c4b36;
+  max-width: 230px;
+  height: 21px;
+  line-height: 21px;
+  font-size: 12px;
+  cursor: pointer;
+  transition: opacity 0.2s;
+
+  &:hover {
+    opacity: 0.8;
+  }
+
+  span {
+    display: inline-block;
+    padding: 0 5px;
+    width: 100%;
+    overflow: hidden;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+    border-top: 1px solid #9c7868;
+    border-bottom: 1px solid #9c7868;
+  }
+  &::before {
+    content: '';
+    position: absolute;
+    top: 0;
+    left: -9px;
+    bottom: 0;
+    width: 9px;
+    background: url('../../images/frame_01_01.png') no-repeat center / contain;
+  }
+  &::after {
+    content: '';
+    position: absolute;
+    top: 0;
+    right: -9px;
+    bottom: 0;
+    width: 9px;
+    background: url('../../images/frame_01_03.png') no-repeat center / contain;
+  }
+}

+ 209 - 0
src/pages/A9knowlege/components/Chart/index.tsx

@@ -0,0 +1,209 @@
+import React, { useState, useRef, useEffect } from 'react'
+import axios from 'axios'
+import styles from './index.module.scss'
+import { decrypt } from '@/utils/encrypt'
+
+const questions = [
+  '程哲碑最值得看的亮点是什么?',
+  '程哲是谁?',
+  '为什么说既是造像碑又是墓碑?',
+  '最初在哪里被发现的?',
+  '想了解北朝历史,这个展览能提供什么信息?'
+]
+
+const FASTGPT_API_URL = 'https://cloud.fastgpt.cn/api'
+const FASTGPT_API_KEY =
+  'U2FsdGVkX19SxkwdbXrR9VmIDZK2+1AdXIWWOLWD5yV5PfNiTfhywkHntyyo7NcV92+wK/TZlUC3zuWHG7EhLYAY+hCmiuZRK8Lr2+h+nwck+ECyzyM9leVPHEVTbMtD'
+
+interface Message {
+  role: 'user' | 'assistant'
+  content: string
+}
+
+function Chart() {
+  const [messages, setMessages] = useState<Message[]>([])
+  const [inputValue, setInputValue] = useState('')
+  const [isLoading, setIsLoading] = useState(false)
+  const [showQuickQuestions, setShowQuickQuestions] = useState(true)
+  const messagesEndRef = useRef<HTMLDivElement>(null)
+  const inputRef = useRef<HTMLInputElement>(null)
+
+  useEffect(() => {
+    messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' })
+  }, [messages])
+
+  const sendMessageToFastGPT = async (userMessage: string) => {
+    try {
+      setIsLoading(true)
+
+      const chatMessages = [
+        ...messages.map(msg => ({
+          role: msg.role,
+          content: msg.content
+        })),
+        {
+          role: 'user' as const,
+          content: userMessage
+        }
+      ]
+
+      let response
+      try {
+        response = await axios.post(
+          `${FASTGPT_API_URL}/v1/chat/completions`,
+          {
+            messages: chatMessages,
+            stream: false,
+            model: 'gpt-3.5-turbo'
+          },
+          {
+            headers: {
+              Authorization: `Bearer ${decrypt(FASTGPT_API_KEY)}`,
+              'Content-Type': 'application/json'
+            },
+            timeout: 30000
+          }
+        )
+
+        let assistantMessage = ''
+        if (response.data?.choices?.[0]?.message?.content) {
+          assistantMessage = response.data.choices[0].message.content
+        } else if (response.data?.data?.text?.[0]) {
+          assistantMessage = response.data.data.text[0]
+        } else if (response.data?.answer) {
+          assistantMessage = response.data.answer
+        } else if (response.data?.text) {
+          assistantMessage = response.data.text
+        } else if (typeof response.data === 'string') {
+          assistantMessage = response.data
+        } else if (response.data?.data) {
+          assistantMessage = JSON.stringify(response.data.data)
+        } else {
+          assistantMessage = JSON.stringify(response.data)
+        }
+
+        return assistantMessage.trim() || '抱歉,没有收到有效回复'
+      } catch (apiError: any) {
+        throw apiError
+      }
+    } catch (error: any) {
+      console.error('FastGPT API 调用失败:', error)
+      let errorMessage = '请求失败,请稍后重试'
+
+      if (error.response?.status === 401) {
+        errorMessage = 'API Key 无效,请检查配置'
+      } else if (error.response?.status === 403) {
+        errorMessage = 'API Key 权限不足'
+      } else if (error.response?.data?.message) {
+        errorMessage = error.response.data.message
+      } else if (error.response?.data?.error?.message) {
+        errorMessage = error.response.data.error.message
+      } else if (error.message) {
+        errorMessage = error.message
+      }
+
+      throw new Error(errorMessage)
+    } finally {
+      setIsLoading(false)
+    }
+  }
+
+  const handleSendMessage = async (messageText?: string) => {
+    const text = messageText || inputValue.trim()
+    if (!text || isLoading) return
+
+    if (showQuickQuestions) {
+      setShowQuickQuestions(false)
+    }
+
+    const userMessage: Message = {
+      role: 'user',
+      content: text
+    }
+    setMessages(prev => [...prev, userMessage])
+    setInputValue('')
+
+    try {
+      const assistantResponse = await sendMessageToFastGPT(text)
+      const assistantMessage: Message = {
+        role: 'assistant',
+        content: assistantResponse
+      }
+      setMessages(prev => [...prev, assistantMessage])
+    } catch (error: any) {
+      const errorMessage: Message = {
+        role: 'assistant',
+        content: `抱歉,发生了错误:${error.message}`
+      }
+      setMessages(prev => [...prev, errorMessage])
+    }
+  }
+
+  const handleQuickQuestionClick = (question: string) => {
+    handleSendMessage(question)
+  }
+
+  const handleInputKeyPress = (e: React.KeyboardEvent<HTMLInputElement>) => {
+    if (e.key === 'Enter' && !e.shiftKey) {
+      e.preventDefault()
+      handleSendMessage()
+    }
+  }
+
+  return (
+    <div className={styles.chart}>
+      <div className={styles.chartWrap}>
+        {showQuickQuestions && (
+          <div className={styles.quickQuestions}>
+            {questions.map(text => (
+              <div
+                key={text}
+                className={styles.chartLog}
+                onClick={() => handleQuickQuestionClick(text)}
+              >
+                <span>{text}</span>
+              </div>
+            ))}
+          </div>
+        )}
+
+        {/* 聊天消息列表 */}
+        {messages.length > 0 && (
+          <div className={styles.messagesContainer}>
+            {messages.map((msg, index) => (
+              <div key={index} className={`${styles.message} ${styles[`message_${msg.role}`]}`}>
+                <div className={styles.messageContent}>{msg.content}</div>
+              </div>
+            ))}
+            {isLoading && (
+              <div className={`${styles.message} ${styles.message_assistant}`}>
+                <div className={styles.messageContent}>
+                  <span className={styles.loadingText}>正在思考...</span>
+                </div>
+              </div>
+            )}
+            <div ref={messagesEndRef} />
+          </div>
+        )}
+      </div>
+
+      <div className={styles.chartFooter}>
+        <div className={styles.chartInput}>
+          <input
+            ref={inputRef}
+            type='text'
+            placeholder='请输入您想了解的内容...'
+            value={inputValue}
+            onChange={e => setInputValue(e.target.value)}
+            onKeyPress={handleInputKeyPress}
+            disabled={isLoading}
+          />
+        </div>
+      </div>
+    </div>
+  )
+}
+
+const MemoChart = React.memo(Chart)
+
+export default MemoChart

+ 26 - 0
src/pages/A9knowlege/components/ModelPanel/index.module.scss

@@ -0,0 +1,26 @@
+.panel {
+  position: absolute;
+  inset: 0;
+  display: flex;
+  flex-direction: column;
+  color: #5b472e;
+  padding: 34px 20px 70px 30px;
+}
+
+.panelWrap {
+  flex: 1;
+
+  iframe {
+    width: 100%;
+    height: 100%;
+    border: none;
+  }
+}
+
+.panelClose {
+  position: absolute;
+  right: 27px;
+  bottom: 28px;
+  width: 61px;
+  height: 25px;
+}

+ 29 - 0
src/pages/A9knowlege/components/ModelPanel/index.tsx

@@ -0,0 +1,29 @@
+import React from 'react'
+import styles from './index.module.scss'
+
+type Props = {
+  detail?: any
+  onClose?: () => void
+}
+
+function Panel({ detail, onClose }: Props) {
+  return (
+    <div className={styles.panel}>
+      <div className={styles.panelWrap}>
+        <iframe title='model' src={detail.link} />
+      </div>
+
+      <img
+        draggable={false}
+        className={styles.panelClose}
+        src={require('../../images/btn_close_red.png')}
+        alt=''
+        onClick={() => onClose && onClose()}
+      />
+    </div>
+  )
+}
+
+const MemoPanel = React.memo(Panel)
+
+export default MemoPanel

+ 54 - 0
src/pages/A9knowlege/components/Panel/index.module.scss

@@ -0,0 +1,54 @@
+.panel {
+  position: absolute;
+  inset: 0;
+  display: flex;
+  flex-direction: column;
+  color: #5b472e;
+  padding: 34px 0 70px 40px;
+}
+
+.panelLabel {
+  margin-bottom: 15px;
+  font-size: 20px;
+}
+
+.panelContent {
+  flex: 1;
+  padding-right: 20px;
+  overflow-y: auto;
+}
+
+.panelLine {
+  display: flex;
+  align-items: flex-start;
+  gap: 16px;
+  margin-bottom: 10px;
+
+  p:first-child {
+    position: relative;
+    white-space: nowrap;
+    font-weight: bold;
+
+    span {
+      position: relative;
+      z-index: 1;
+    }
+    &::after {
+      content: '';
+      position: absolute;
+      left: 2px;
+      right: 2px;
+      bottom: 0;
+      height: 8px;
+      background: #af8764;
+    }
+  }
+}
+
+.panelClose {
+  position: absolute;
+  right: 27px;
+  bottom: 28px;
+  width: 61px;
+  height: 25px;
+}

+ 42 - 0
src/pages/A9knowlege/components/Panel/index.tsx

@@ -0,0 +1,42 @@
+import React from 'react'
+import styles from './index.module.scss'
+
+type Props = {
+  detail?: any
+  onClose?: () => void
+}
+
+function Panel({ detail, onClose }: Props) {
+  const title = detail?.label || '文物简介'
+
+  return (
+    <div className={styles.panel}>
+      <p className={styles.panelLabel}>{title}</p>
+
+      <div className={styles.panelContent}>
+        {detail.content.map((block: any, idx: number) => (
+          <div className={styles.panelLine} key={idx}>
+            {block.label ? (
+              <p>
+                <span>{block.label}</span>
+              </p>
+            ) : null}
+            <p>{block.value}</p>
+          </div>
+        ))}
+      </div>
+
+      <img
+        draggable={false}
+        className={styles.panelClose}
+        src={require('../../images/btn_close_red.png')}
+        alt=''
+        onClick={() => onClose && onClose()}
+      />
+    </div>
+  )
+}
+
+const MemoPanel = React.memo(Panel)
+
+export default MemoPanel

+ 50 - 0
src/pages/A9knowlege/components/Panel2/index.module.scss

@@ -0,0 +1,50 @@
+.panel {
+  position: absolute;
+  inset: 0;
+  display: flex;
+  flex-direction: column;
+  color: #5b472e;
+  padding: 34px 0 70px 40px;
+
+  :global {
+    .indent {
+      text-indent: 2em;
+    }
+  }
+}
+
+.panelLabel {
+  margin-bottom: 15px;
+  font-size: 20px;
+}
+
+.panelWrap {
+  flex: 1;
+  padding-right: 20px;
+  overflow-y: auto;
+}
+
+.panelContent {
+  font-size: 14px;
+  margin-bottom: 15px;
+  // white-space: pre-line;
+}
+
+.panelImg {
+  margin-bottom: 15px;
+  display: flex;
+  flex-direction: column;
+  gap: 4px;
+
+  span {
+    font-size: 10px;
+  }
+}
+
+.panelClose {
+  position: absolute;
+  right: 27px;
+  bottom: 28px;
+  width: 61px;
+  height: 25px;
+}

+ 48 - 0
src/pages/A9knowlege/components/Panel2/index.tsx

@@ -0,0 +1,48 @@
+import React from 'react'
+import classNames from 'classnames'
+import styles from './index.module.scss'
+
+type Props = {
+  detail?: any
+  onClose?: () => void
+}
+
+function Panel({ detail, onClose }: Props) {
+  const title = detail?.label || ''
+  const content = detail?.content || ''
+  const imgs = detail?.imgs || []
+
+  return (
+    <div className={styles.panel}>
+      <p className={styles.panelLabel}>{title}</p>
+
+      <div className={styles.panelWrap}>
+        {content && (
+          <div
+            className={classNames([styles.panelContent, { indent: detail?.needIndent }])}
+            dangerouslySetInnerHTML={{ __html: content }}
+          />
+        )}
+
+        {imgs.map((img: any, idx: number) => (
+          <div key={idx} className={styles.panelImg}>
+            <img alt={img.desc} src={img.path} />
+            <span>{img.desc}</span>
+          </div>
+        ))}
+      </div>
+
+      <img
+        draggable={false}
+        className={styles.panelClose}
+        src={require('../../images/btn_close_red.png')}
+        alt=''
+        onClick={() => onClose && onClose()}
+      />
+    </div>
+  )
+}
+
+const MemoPanel = React.memo(Panel)
+
+export default MemoPanel

BIN
src/pages/A9knowlege/images/bg_jiaohu-min.jpg


BIN
src/pages/A9knowlege/images/btn_close_red.png


BIN
src/pages/A9knowlege/images/frame_01_01.png


BIN
src/pages/A9knowlege/images/frame_01_03.png


BIN
src/pages/A9knowlege/images/icon_flower_red.png


BIN
src/pages/A9knowlege/images/img_pop_02-min.png


BIN
src/pages/A9knowlege/images/img_pop_03-min.png


BIN
src/pages/A9knowlege/images/line_04-min.png


+ 41 - 0
src/pages/A9knowlege/index.module.scss

@@ -0,0 +1,41 @@
+.A9knowlege {
+  display: flex;
+  width: 100%;
+  height: 100%;
+  overflow: hidden;
+  background: url('./images/bg_jiaohu-min.jpg') no-repeat center / cover;
+
+  :global {
+    .back {
+      width: 60px;
+      height: 30px;
+      position: absolute;
+      z-index: 3;
+      top: 3%;
+      left: 4%;
+      cursor: pointer;
+
+      & > img {
+        height: 100%;
+        object-fit: contain;
+      }
+    }
+  }
+}
+
+.main {
+  flex: 1;
+
+  > * {
+    width: 100%;
+    height: 100%;
+    border: none;
+  }
+}
+
+.sidebar {
+  position: relative;
+  width: 298px;
+  height: 100%;
+  background: url('./images/img_pop_02-min.png') no-repeat center / cover;
+}

+ 141 - 0
src/pages/A9knowlege/index.tsx

@@ -0,0 +1,141 @@
+import React, { useEffect, useRef, useCallback, useState } from 'react'
+import styles from './index.module.scss'
+import Chart from './components/Chart'
+import Panel from './components/Panel'
+import Panel2 from './components/Panel2'
+import ModelPanel from './components/ModelPanel'
+
+function A9knowlege() {
+  const echartRef = useRef<HTMLDivElement | null>(null)
+  const chartInstance = useRef<any>(null)
+  const [detail, setDetail] = useState<any>(null)
+
+  const buildGraphFromKnowlege = (data: any[]) => {
+    const nodes: any[] = []
+    const links: any[] = []
+    let idCounter = 0
+    const genId = (label: string) =>
+      `${idCounter++}-${String(label || 'node').replace(/\s+/g, '_')}`
+
+    const traverse = (item: any, parentId: string | null, depth: number) => {
+      const id = genId(item.label)
+      const category = `level${depth}`
+      const symbolSize = depth === 0 ? 60 : depth === 1 ? 40 : 20
+      nodes.push({ id, name: item.label, category, symbolSize, raw: item })
+      if (parentId) links.push({ source: parentId, target: id })
+      if (Array.isArray(item.children))
+        item.children.forEach((child: any) => traverse(child, id, depth + 1))
+    }
+
+    data.forEach((root: any) => traverse(root, null, 0))
+    const maxDepth = nodes.reduce((m, n) => {
+      const match = (n.category || '').match(/level(\d+)/)
+      const d = match ? Number(match[1]) : 0
+      return Math.max(m, d)
+    }, 0)
+    const categories: any[] = []
+    for (let i = 0; i <= maxDepth; i++) categories.push({ name: `level${i}` })
+    return { nodes, links, categories }
+  }
+
+  const initChart = useCallback(() => {
+    // @ts-ignore
+    const echarts = (window as any).echarts
+    // @ts-ignore
+    const data = knowlegeData || []
+    if (!echarts || !echartRef.current) return
+
+    if (chartInstance.current) {
+      try {
+        chartInstance.current.dispose()
+      } catch (e) {}
+      chartInstance.current = null
+    }
+
+    const myChart = echarts.init(echartRef.current, null, {
+      renderer: 'canvas',
+      useDirtyRect: false
+    })
+    chartInstance.current = myChart
+
+    const graph = buildGraphFromKnowlege(data)
+
+    const option = {
+      tooltip: { show: false },
+      series: [
+        {
+          name: 'KnowledgeGraph',
+          type: 'graph',
+          layout: 'force',
+          data: graph.nodes.map((n: any) => ({
+            ...n,
+            label: { show: true, formatter: n.name, fontSize: 12 }
+          })),
+          links: graph.links,
+          categories: graph.categories,
+          roam: true,
+          label: { position: 'right' },
+          emphasis: { focus: 'adjacency' },
+          force: { repulsion: 200, edgeLength: [50, 120] },
+          lineStyle: { color: 'source', curveness: 0.2 }
+        }
+      ]
+    }
+
+    myChart.setOption(option, true)
+    myChart.off('click')
+    myChart.on('click', function (params: any) {
+      if (!params || !params.data) return
+      const node = params.data
+      if (node && node.raw && node.raw.type) {
+        setDetail(node.raw)
+      }
+    })
+    const resizeHandler = () => myChart.resize()
+    window.addEventListener('resize', resizeHandler)
+    ;(chartInstance.current as any)._resizeHandler = resizeHandler
+  }, [])
+
+  useEffect(() => {
+    initChart()
+    return () => {
+      if (chartInstance.current) {
+        try {
+          const h = (chartInstance.current as any)._resizeHandler
+          if (h) window.removeEventListener('resize', h)
+          chartInstance.current.dispose()
+        } catch (e) {}
+        chartInstance.current = null
+      }
+    }
+    // eslint-disable-next-line react-hooks/exhaustive-deps
+  }, [])
+
+  return (
+    <div className={styles.A9knowlege}>
+      <div className='back' onClick={() => window.location.replace('#/base')}>
+        <img src={require('@/assets/img/btn_back.png')} alt='' />
+      </div>
+
+      <div className={styles.main}>
+        <div id='echart-container' ref={echartRef} />
+      </div>
+
+      <div className={styles.sidebar}>
+        {!detail ? (
+          <Chart />
+        ) : detail.type === 1 ? (
+          <Panel detail={detail} onClose={() => setDetail(null)} />
+        ) : detail.type === 5 ? (
+          <ModelPanel detail={detail} onClose={() => setDetail(null)} />
+        ) : (
+          <Panel2 detail={detail} onClose={() => setDetail(null)} />
+        )}
+      </div>
+    </div>
+  )
+}
+
+const MemoA9knowlege = React.memo(A9knowlege)
+
+export default MemoA9knowlege

+ 109 - 0
src/utils/encrypt.ts

@@ -0,0 +1,109 @@
+// utils/encrypt.ts
+
+/**
+ * 加解密工具类(依赖crypto-js)
+ */
+import CryptoJS from 'crypto-js'
+
+// 默认密钥,建议在生产环境中使用环境变量
+const DEFAULT_SECRET_KEY = 'chengzhebei-2025-key'
+
+/**
+ * AES加密
+ * @param text 明文
+ * @param secretKey 密钥(可选,默认使用DEFAULT_SECRET_KEY)
+ * @returns 加密后的字符串
+ */
+export function encrypt(text: string, secretKey?: string): string {
+  try {
+    const key = secretKey || DEFAULT_SECRET_KEY
+    return CryptoJS.AES.encrypt(text, key).toString()
+  } catch (error) {
+    console.error('加密失败:', error)
+    throw new Error('加密失败')
+  }
+}
+
+/**
+ * AES解密
+ * @param ciphertext 密文
+ * @param secretKey 密钥(可选,默认使用DEFAULT_SECRET_KEY)
+ * @returns 解密后的明文
+ */
+export function decrypt(ciphertext: string, secretKey?: string): string {
+  try {
+    const key = secretKey || DEFAULT_SECRET_KEY
+    const bytes = CryptoJS.AES.decrypt(ciphertext, key)
+    const decryptedText = bytes.toString(CryptoJS.enc.Utf8)
+
+    if (!decryptedText) {
+      throw new Error('解密失败,可能是密钥错误')
+    }
+
+    return decryptedText
+  } catch (error) {
+    console.error('解密失败:', error)
+    throw new Error('解密失败')
+  }
+}
+
+/**
+ * Base64编码
+ * @param text 原始文本
+ * @returns Base64编码后的字符串
+ */
+export function base64Encode(text: string): string {
+  try {
+    return CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(text))
+  } catch (error) {
+    console.error('Base64编码失败:', error)
+    throw new Error('Base64编码失败')
+  }
+}
+
+/**
+ * Base64解码
+ * @param base64Text Base64编码的文本
+ * @returns 解码后的原始文本
+ */
+export function base64Decode(base64Text: string): string {
+  try {
+    const words = CryptoJS.enc.Base64.parse(base64Text)
+    return CryptoJS.enc.Utf8.stringify(words)
+  } catch (error) {
+    console.error('Base64解码失败:', error)
+    throw new Error('Base64解码失败')
+  }
+}
+
+/**
+ * MD5哈希(不可逆,常用于数据校验)
+ * @param text 原始文本
+ * @returns MD5哈希值
+ */
+export function md5(text: string): string {
+  return CryptoJS.MD5(text).toString()
+}
+
+/**
+ * SHA256哈希(不可逆,常用于数据校验)
+ * @param text 原始文本
+ * @returns SHA256哈希值
+ */
+export function sha256(text: string): string {
+  return CryptoJS.SHA256(text).toString()
+}
+
+/**
+ * 生成随机密钥
+ * @param length 密钥长度(默认32)
+ * @returns 随机密钥字符串
+ */
+export function generateSecretKey(length: number = 32): string {
+  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
+  let result = ''
+  for (let i = 0; i < length; i++) {
+    result += chars.charAt(Math.floor(Math.random() * chars.length))
+  }
+  return result
+}

+ 128 - 9
yarn.lock

@@ -2154,6 +2154,11 @@
   dependencies:
     "@types/node" "*"
 
+"@types/crypto-js@^4.2.2":
+  version "4.2.2"
+  resolved "https://registry.npmmirror.com/@types/crypto-js/-/crypto-js-4.2.2.tgz#771c4a768d94eb5922cc202a3009558204df0cea"
+  integrity sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ==
+
 "@types/eslint-scope@^3.7.3":
   version "3.7.4"
   resolved "https://registry.npmmirror.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz"
@@ -3283,13 +3288,13 @@ axe-core@^4.4.3:
   resolved "https://registry.npmmirror.com/axe-core/-/axe-core-4.5.0.tgz"
   integrity sha512-4+rr8eQ7+XXS5nZrKcMO/AikHL0hVqy+lHWAnE3xdHl+aguag8SOQ6eEqLexwLNWgXIMfunGuD3ON1/6Kyet0A==
 
-axios@^1.7.9:
-  version "1.7.9"
-  resolved "https://registry.npmmirror.com/axios/-/axios-1.7.9.tgz#d7d071380c132a24accda1b2cfc1535b79ec650a"
-  integrity sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==
+axios@^1.13.2:
+  version "1.13.2"
+  resolved "https://registry.npmmirror.com/axios/-/axios-1.13.2.tgz#9ada120b7b5ab24509553ec3e40123521117f687"
+  integrity sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==
   dependencies:
     follow-redirects "^1.15.6"
-    form-data "^4.0.0"
+    form-data "^4.0.4"
     proxy-from-env "^1.1.0"
 
 axobject-query@^2.2.0:
@@ -3620,6 +3625,14 @@ bytes@3.1.2:
   resolved "https://registry.npmmirror.com/bytes/-/bytes-3.1.2.tgz"
   integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==
 
+call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6"
+  integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==
+  dependencies:
+    es-errors "^1.3.0"
+    function-bind "^1.1.2"
+
 call-bind@^1.0.0, call-bind@^1.0.2:
   version "1.0.2"
   resolved "https://registry.npmmirror.com/call-bind/-/call-bind-1.0.2.tgz"
@@ -3768,6 +3781,11 @@ classnames@2.x, classnames@^2.2.1, classnames@^2.2.3, classnames@^2.2.5, classna
   resolved "https://registry.npmmirror.com/classnames/-/classnames-2.3.2.tgz"
   integrity sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==
 
+classnames@^2.5.1:
+  version "2.5.1"
+  resolved "https://registry.npmmirror.com/classnames/-/classnames-2.5.1.tgz#ba774c614be0f016da105c858e7159eae8e7687b"
+  integrity sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==
+
 clean-css@^5.2.2:
   version "5.3.1"
   resolved "https://registry.npmmirror.com/clean-css/-/clean-css-5.3.1.tgz"
@@ -4039,6 +4057,11 @@ cross-spawn@^7.0.2, cross-spawn@^7.0.3:
     shebang-command "^2.0.0"
     which "^2.0.1"
 
+crypto-js@^4.2.0:
+  version "4.2.0"
+  resolved "https://registry.npmmirror.com/crypto-js/-/crypto-js-4.2.0.tgz#4d931639ecdfd12ff80e8186dba6af2c2e856631"
+  integrity sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==
+
 crypto-random-string@^2.0.0:
   version "2.0.0"
   resolved "https://registry.npmmirror.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz"
@@ -4589,6 +4612,15 @@ dotenv@^10.0.0:
   resolved "https://registry.npmmirror.com/dotenv/-/dotenv-10.0.0.tgz"
   integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==
 
+dunder-proto@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a"
+  integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==
+  dependencies:
+    call-bind-apply-helpers "^1.0.1"
+    es-errors "^1.3.0"
+    gopd "^1.2.0"
+
 duplexer2@~0.1.4:
   version "0.1.4"
   resolved "https://registry.npmmirror.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1"
@@ -4717,6 +4749,16 @@ es-array-method-boxes-properly@^1.0.0:
   resolved "https://registry.npmmirror.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz"
   integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==
 
+es-define-property@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa"
+  integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==
+
+es-errors@^1.3.0:
+  version "1.3.0"
+  resolved "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f"
+  integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==
+
 es-get-iterator@^1.1.1:
   version "1.1.2"
   resolved "https://registry.npmmirror.com/es-get-iterator/-/es-get-iterator-1.1.2.tgz"
@@ -4736,6 +4778,23 @@ es-module-lexer@^0.9.0:
   resolved "https://registry.npmmirror.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz"
   integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==
 
+es-object-atoms@^1.0.0, es-object-atoms@^1.1.1:
+  version "1.1.1"
+  resolved "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1"
+  integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==
+  dependencies:
+    es-errors "^1.3.0"
+
+es-set-tostringtag@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.npmmirror.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz#f31dbbe0c183b00a6d26eb6325c810c0fd18bd4d"
+  integrity sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==
+  dependencies:
+    es-errors "^1.3.0"
+    get-intrinsic "^1.2.6"
+    has-tostringtag "^1.0.2"
+    hasown "^2.0.2"
+
 es-shim-unscopables@^1.0.0:
   version "1.0.0"
   resolved "https://registry.npmmirror.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz"
@@ -5392,13 +5451,15 @@ form-data@^3.0.0:
     combined-stream "^1.0.8"
     mime-types "^2.1.12"
 
-form-data@^4.0.0:
-  version "4.0.1"
-  resolved "https://registry.npmmirror.com/form-data/-/form-data-4.0.1.tgz#ba1076daaaa5bfd7e99c1a6cb02aa0a5cff90d48"
-  integrity sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==
+form-data@^4.0.4:
+  version "4.0.5"
+  resolved "https://registry.npmmirror.com/form-data/-/form-data-4.0.5.tgz#b49e48858045ff4cbf6b03e1805cebcad3679053"
+  integrity sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==
   dependencies:
     asynckit "^0.4.0"
     combined-stream "^1.0.8"
+    es-set-tostringtag "^2.1.0"
+    hasown "^2.0.2"
     mime-types "^2.1.12"
 
 forwarded@0.2.0:
@@ -5470,6 +5531,11 @@ function-bind@^1.1.1:
   resolved "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.1.tgz"
   integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
 
+function-bind@^1.1.2:
+  version "1.1.2"
+  resolved "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c"
+  integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==
+
 function.prototype.name@^1.1.5:
   version "1.1.5"
   resolved "https://registry.npmmirror.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz"
@@ -5504,6 +5570,22 @@ get-intrinsic@^1.0.1, get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@
     has "^1.0.3"
     has-symbols "^1.0.3"
 
+get-intrinsic@^1.2.6:
+  version "1.3.0"
+  resolved "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01"
+  integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==
+  dependencies:
+    call-bind-apply-helpers "^1.0.2"
+    es-define-property "^1.0.1"
+    es-errors "^1.3.0"
+    es-object-atoms "^1.1.1"
+    function-bind "^1.1.2"
+    get-proto "^1.0.1"
+    gopd "^1.2.0"
+    has-symbols "^1.1.0"
+    hasown "^2.0.2"
+    math-intrinsics "^1.1.0"
+
 get-own-enumerable-property-symbols@^3.0.0:
   version "3.0.2"
   resolved "https://registry.npmmirror.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz"
@@ -5514,6 +5596,14 @@ get-package-type@^0.1.0:
   resolved "https://registry.npmmirror.com/get-package-type/-/get-package-type-0.1.0.tgz"
   integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==
 
+get-proto@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.npmmirror.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1"
+  integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==
+  dependencies:
+    dunder-proto "^1.0.1"
+    es-object-atoms "^1.0.0"
+
 get-stream@^6.0.0:
   version "6.0.1"
   resolved "https://registry.npmmirror.com/get-stream/-/get-stream-6.0.1.tgz"
@@ -5598,6 +5688,11 @@ globby@^11.0.4, globby@^11.1.0:
     merge2 "^1.4.1"
     slash "^3.0.0"
 
+gopd@^1.2.0:
+  version "1.2.0"
+  resolved "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1"
+  integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==
+
 graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9:
   version "4.2.10"
   resolved "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.10.tgz"
@@ -5657,6 +5752,11 @@ has-symbols@^1.0.1, has-symbols@^1.0.2, has-symbols@^1.0.3:
   resolved "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.0.3.tgz"
   integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==
 
+has-symbols@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338"
+  integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==
+
 has-tostringtag@^1.0.0:
   version "1.0.0"
   resolved "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz"
@@ -5664,6 +5764,13 @@ has-tostringtag@^1.0.0:
   dependencies:
     has-symbols "^1.0.2"
 
+has-tostringtag@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc"
+  integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==
+  dependencies:
+    has-symbols "^1.0.3"
+
 has@^1.0.3:
   version "1.0.3"
   resolved "https://registry.npmmirror.com/has/-/has-1.0.3.tgz"
@@ -5671,6 +5778,13 @@ has@^1.0.3:
   dependencies:
     function-bind "^1.1.1"
 
+hasown@^2.0.2:
+  version "2.0.2"
+  resolved "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003"
+  integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==
+  dependencies:
+    function-bind "^1.1.2"
+
 he@^1.2.0:
   version "1.2.0"
   resolved "https://registry.npmmirror.com/he/-/he-1.2.0.tgz"
@@ -7229,6 +7343,11 @@ makeerror@1.0.12:
   dependencies:
     tmpl "1.0.5"
 
+math-intrinsics@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9"
+  integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==
+
 mdn-data@2.0.14:
   version "2.0.14"
   resolved "https://registry.npmmirror.com/mdn-data/-/mdn-data-2.0.14.tgz"