Преглед изворни кода

✨ feat(dashboard): 新增银龄人才大数据监控中心

- 集成 @ant-design/plots 图表库实现数据可视化
- 创建 BigScreenDashboard 页面组件展示核心指标
- 添加 StatCard 和 BigScreenHeader 可复用组件
- 实现 useBigScreenData Hook 统一数据获取逻辑
- 支持实时数据更新和30秒轮询机制
- 添加路由配置和菜单项 "大数据监控"
yourname пре 7 месеци
родитељ
комит
b448cd863b

+ 1 - 0
package.json

@@ -9,6 +9,7 @@
   },
   "dependencies": {
     "@ant-design/icons": "^6.0.0",
+    "@ant-design/plots": "^2.6.2",
     "@emotion/react": "^11.14.0",
     "@heroicons/react": "^2.2.0",
     "@hono/node-server": "^1.14.3",

+ 681 - 0
pnpm-lock.yaml

@@ -11,6 +11,9 @@ importers:
       '@ant-design/icons':
         specifier: ^6.0.0
         version: 6.0.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+      '@ant-design/plots':
+        specifier: ^2.6.2
+        version: 2.6.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
       '@emotion/react':
         specifier: ^11.14.0
         version: 11.14.0(@types/react@19.1.8)(react@19.1.0)
@@ -163,6 +166,12 @@ packages:
     resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
     engines: {node: '>=6.0.0'}
 
+  '@ant-design/charts-util@0.0.2':
+    resolution: {integrity: sha512-JuThvtHE8R3PldXzTkL3bmmFf0HVhih49CYinRrkwgovOmvDYaaKHnI53EWJbW8n4Ndcyy8jiZTSkoxcjGS6Zg==}
+    peerDependencies:
+      react: '>=16.8.4'
+      react-dom: '>=16.8.4'
+
   '@ant-design/colors@7.2.1':
     resolution: {integrity: sha512-lCHDcEzieu4GA3n8ELeZ5VQ8pKQAWcGGLRTQ50aQM2iqPpq2evTxER84jfdPvsPAtEcZ7m44NI45edFMo8oOYQ==}
 
@@ -206,11 +215,89 @@ packages:
       react: '>=16.0.0'
       react-dom: '>=16.0.0'
 
+  '@ant-design/plots@2.6.2':
+    resolution: {integrity: sha512-8OEIoMM5roAefe3ju7cQB8hrE+72o0BZ8S9HtwmtcoJh5Rgu7PeRx82RhGSfMikqo+ko6YWn2/GIgGOw0MQlYQ==}
+    peerDependencies:
+      react: '>=16.8.4'
+      react-dom: '>=16.8.4'
+
   '@ant-design/react-slick@1.1.2':
     resolution: {integrity: sha512-EzlvzE6xQUBrZuuhSAFTdsr4P2bBBHGZwKFemEfq8gIGyIQCxalYfZW/T2ORbtQx5rU69o+WycP3exY/7T1hGA==}
     peerDependencies:
       react: '>=16.9.0'
 
+  '@antv/component@2.1.5':
+    resolution: {integrity: sha512-+Pqu6CLkGTvYZw+UQK03B/yiR0h2Zu65tyUGUQkNuPv49Zwe4WqDZqqu94bqT1F07OAAVjeXLCTvhBb954DLXQ==}
+
+  '@antv/coord@0.4.7':
+    resolution: {integrity: sha512-UTbrMLhwJUkKzqJx5KFnSRpU3BqrdLORJbwUbHK2zHSCT3q3bjcFA//ZYLVfIlwqFDXp/hzfMyRtp0c77A9ZVA==}
+
+  '@antv/event-emitter@0.1.3':
+    resolution: {integrity: sha512-4ddpsiHN9Pd4UIlWuKVK1C4IiZIdbwQvy9i7DUSI3xNJ89FPUFt8lxDYj8GzzfdllV0NkJTRxnG+FvLk0llidg==}
+
+  '@antv/expr@1.0.2':
+    resolution: {integrity: sha512-vrfdmPHkTuiS5voVutKl2l06w1ihBh9A8SFdQPEE+2KMVpkymzGOF1eWpfkbGZ7tiFE15GodVdhhHomD/hdIwg==}
+
+  '@antv/g-camera-api@2.0.41':
+    resolution: {integrity: sha512-dF52/wpzHDKi7ZzPlaHurEjWrF9aBKL2udDwQkEeVtfkJ0DHaavr3BAvhuGhtHoecRYQJvpzP1OkGNDLQJQQlw==}
+
+  '@antv/g-canvas@2.0.48':
+    resolution: {integrity: sha512-P98cTLRbKbCAcUVgHqMjKcvOany6nR7wvt+g+sazIfKSMUCWgjLTOjlLezux2up3At29mt80StaV2AR3d61YQA==}
+
+  '@antv/g-dom-mutation-observer-api@2.0.38':
+    resolution: {integrity: sha512-xzgbt8GUOiToBeDVv+jmGkDE+HtI9tD6uO8TirJbCya88DKcY/jurQALq0NdWKgMJLn7WPiUKyDwHWimwQcBJw==}
+
+  '@antv/g-lite@2.3.2':
+    resolution: {integrity: sha512-fkIxRoqLOGsNPwsp26bPp58cPWuX3E4wQ9cfkB/DHy5LtLrPpvOwHWB3+MBPgZwzk8jTTjchiXa756ZFOAWyQQ==}
+
+  '@antv/g-math@3.0.1':
+    resolution: {integrity: sha512-FvkDBNRpj+HsLINunrL2PW0OlG368MlpHuihbxleuajGim5kra8tgISwCLmAf8Yz2b1CgZ9PvpohqiLzHS7HLg==}
+
+  '@antv/g-plugin-canvas-path-generator@2.1.22':
+    resolution: {integrity: sha512-Z0IawzTGgTppa9IpkNNKsqgoU89oOjUsiU8GZZlkDkUggQTHP0wOxTeLAb43YgClx3aTI3bRs44uMQutNdSVxw==}
+
+  '@antv/g-plugin-canvas-picker@2.1.27':
+    resolution: {integrity: sha512-DHQ0YLYNXAm6O63pW6nKs/R0fuqlUYfehNs/EtzrmqyUkKASd/Vhs4HLNeHTMUdBMgg41T+x5qay0GGttK4Xdw==}
+
+  '@antv/g-plugin-canvas-renderer@2.3.3':
+    resolution: {integrity: sha512-d6JkZy1YmLnvI9wsbO8QVpBz7z7tl6JRQkF5hx9XLDtf2fD4n83KINeMq13skiNwaiudS771WWiBtfzUHB73pQ==}
+
+  '@antv/g-plugin-dom-interaction@2.1.27':
+    resolution: {integrity: sha512-hltVZZH+bj0uXmGSR+6BIwhCFYyHmDIQi3vrj/Wn1Dn6PgufvMCXfjr3DfmkQnY+FFP8ZCpg5N9MaE0BE9OddA==}
+
+  '@antv/g-plugin-dragndrop@2.0.38':
+    resolution: {integrity: sha512-yCef5ER759i0WpuOekFQ+AcDTu0N/COMbkPOG6YuswVnhQH447GUpuNm7Le+Mq26qONlXTDyjxuMHoUOWwJ7Cw==}
+
+  '@antv/g-plugin-html-renderer@2.1.27':
+    resolution: {integrity: sha512-NnI4GxDBb71o/XZzoRdi0xI3xg7GJmthyO5xP5/MiOFmwJ/jW/QDz17vUonmzUVbCt6upikHV5GyYOaogRqdVg==}
+
+  '@antv/g-plugin-image-loader@2.1.26':
+    resolution: {integrity: sha512-AElV0QOX2LAhB3jr9XtvkynntuKhcaU5n7avu5ynM5VoAtMaJRANhCyefA2G3myeJxWcHk4nWDX6u4YMaZnnvw==}
+
+  '@antv/g-web-animations-api@2.1.28':
+    resolution: {integrity: sha512-V5g8bO2D1hb8fRMMi5hXL/De+1UDRzW3C5EX07oazR0q71GONASP+sVwniZdt9R1HAmJSN5dvW3SqWeU3EEstQ==}
+
+  '@antv/g2-extension-plot@0.2.2':
+    resolution: {integrity: sha512-KJXCXO7as+h0hDqirGXf1omrNuYzQmY3VmBmp7lIvkepbQ7sz3pPwy895r1FWETGF3vTk5UeFcAF5yzzBHWgbw==}
+
+  '@antv/g2@5.3.5':
+    resolution: {integrity: sha512-Q2TPfWTf2fMwe02Uqk4Uvgy/RGXpGQXfSMPHKLkwTUh6WrFImpgzU4mHhUewKVu5ppPGGfvlwIbZcHeBnNb5ug==}
+
+  '@antv/g@6.1.28':
+    resolution: {integrity: sha512-BwavpbKGR4NEJD3BtVxfBFjCcxy5gsWoUNnBisfG1qfjhGTt7QvUYHFH46+mHJjHMIdYjuFw2T0ZYVtxBddxSg==}
+
+  '@antv/scale@0.4.16':
+    resolution: {integrity: sha512-5wg/zB5kXHxpTV5OYwJD3ja6R8yTiqIOkjOhmpEJiowkzRlbEC/BOyMvNUq5fqFIHnMCE9woO7+c3zxEQCKPjw==}
+
+  '@antv/util@2.0.17':
+    resolution: {integrity: sha512-o6I9hi5CIUvLGDhth0RxNSFDRwXeywmt6ExR4+RmVAzIi48ps6HUy+svxOCayvrPBN37uE6TAc2KDofRo0nK9Q==}
+
+  '@antv/util@3.3.11':
+    resolution: {integrity: sha512-FII08DFM4ABh2q5rPYdr0hMtKXRgeZazvXaFYCs7J7uTcWDHUhczab2qOCJLNDugoj8jFag1djb7wS9ehaRYBg==}
+
+  '@antv/vendor@1.0.11':
+    resolution: {integrity: sha512-LmhPEQ+aapk3barntaiIxJ5VHno/Tyab2JnfdcPzp5xONh/8VSfed4bo/9xKo5HcUAEydko38vYLfj6lJliLiw==}
+
   '@asteasolutions/zod-to-openapi@7.3.3':
     resolution: {integrity: sha512-ioiw+R+gBGAUwmDp+/gJA16tedBivzDaji5wOvWej0ZYDE0CXTSSfJfXbrBIuWKh6JQhuXgNDniJdeDueKUZTA==}
     peerDependencies:
@@ -1280,12 +1367,72 @@ packages:
   '@types/bcrypt@5.0.2':
     resolution: {integrity: sha512-6atioO8Y75fNcbmj0G7UjI9lXN2pQ/IGJ2FWT4a/btd0Lk9lQalHLKhkgKVZ3r+spnmWUKfbMi1GEe9wyHQfNQ==}
 
+  '@types/d3-array@3.2.1':
+    resolution: {integrity: sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==}
+
+  '@types/d3-color@3.1.3':
+    resolution: {integrity: sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==}
+
+  '@types/d3-dispatch@3.0.7':
+    resolution: {integrity: sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA==}
+
+  '@types/d3-dsv@3.0.7':
+    resolution: {integrity: sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==}
+
+  '@types/d3-ease@3.0.2':
+    resolution: {integrity: sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==}
+
+  '@types/d3-fetch@3.0.7':
+    resolution: {integrity: sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==}
+
+  '@types/d3-force@3.0.10':
+    resolution: {integrity: sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==}
+
+  '@types/d3-format@3.0.4':
+    resolution: {integrity: sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==}
+
+  '@types/d3-geo@3.1.0':
+    resolution: {integrity: sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==}
+
+  '@types/d3-hierarchy@3.1.7':
+    resolution: {integrity: sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==}
+
+  '@types/d3-interpolate@3.0.4':
+    resolution: {integrity: sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==}
+
+  '@types/d3-path@3.1.1':
+    resolution: {integrity: sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==}
+
+  '@types/d3-quadtree@3.0.6':
+    resolution: {integrity: sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==}
+
+  '@types/d3-random@3.0.3':
+    resolution: {integrity: sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==}
+
+  '@types/d3-scale-chromatic@3.1.0':
+    resolution: {integrity: sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==}
+
+  '@types/d3-scale@4.0.9':
+    resolution: {integrity: sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==}
+
+  '@types/d3-shape@3.1.7':
+    resolution: {integrity: sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg==}
+
+  '@types/d3-time@3.0.4':
+    resolution: {integrity: sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==}
+
+  '@types/d3-timer@3.0.2':
+    resolution: {integrity: sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==}
+
   '@types/debug@4.1.12':
     resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==}
 
   '@types/estree@1.0.7':
     resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==}
 
+  '@types/geojson@7946.0.16':
+    resolution: {integrity: sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==}
+
   '@types/jsonwebtoken@9.0.9':
     resolution: {integrity: sha512-uoe+GxEuHbvy12OUQct2X9JenKM3qAscquYymuQN4fMWG9DBQtykrQEFcAbVACF7qaLw9BePSodUL0kquqBJpQ==}
 
@@ -1502,6 +1649,10 @@ packages:
     resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
     engines: {node: '>= 0.8'}
 
+  commander@7.2.0:
+    resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==}
+    engines: {node: '>= 10'}
+
   compute-scroll-into-view@3.1.1:
     resolution: {integrity: sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw==}
 
@@ -1533,6 +1684,105 @@ packages:
   csstype@3.1.3:
     resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
 
+  d3-array@3.2.4:
+    resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==}
+    engines: {node: '>=12'}
+
+  d3-binarytree@1.0.2:
+    resolution: {integrity: sha512-cElUNH+sHu95L04m92pG73t2MEJXKu+GeKUN1TJkFsu93E5W8E9Sc3kHEGJKgenGvj19m6upSn2EunvMgMD2Yw==}
+
+  d3-color@3.1.0:
+    resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==}
+    engines: {node: '>=12'}
+
+  d3-dispatch@3.0.1:
+    resolution: {integrity: sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==}
+    engines: {node: '>=12'}
+
+  d3-dsv@3.0.1:
+    resolution: {integrity: sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==}
+    engines: {node: '>=12'}
+    hasBin: true
+
+  d3-ease@3.0.1:
+    resolution: {integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==}
+    engines: {node: '>=12'}
+
+  d3-fetch@3.0.1:
+    resolution: {integrity: sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==}
+    engines: {node: '>=12'}
+
+  d3-force-3d@3.0.6:
+    resolution: {integrity: sha512-4tsKHUPLOVkyfEffZo1v6sFHvGFwAIIjt/W8IThbp08DYAsXZck+2pSHEG5W1+gQgEvFLdZkYvmJAbRM2EzMnA==}
+    engines: {node: '>=12'}
+
+  d3-force@3.0.0:
+    resolution: {integrity: sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==}
+    engines: {node: '>=12'}
+
+  d3-format@3.1.0:
+    resolution: {integrity: sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==}
+    engines: {node: '>=12'}
+
+  d3-geo-projection@4.0.0:
+    resolution: {integrity: sha512-p0bK60CEzph1iqmnxut7d/1kyTmm3UWtPlwdkM31AU+LW+BXazd5zJdoCn7VFxNCHXRngPHRnsNn5uGjLRGndg==}
+    engines: {node: '>=12'}
+    hasBin: true
+
+  d3-geo@3.1.1:
+    resolution: {integrity: sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==}
+    engines: {node: '>=12'}
+
+  d3-hierarchy@3.1.2:
+    resolution: {integrity: sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==}
+    engines: {node: '>=12'}
+
+  d3-interpolate@3.0.1:
+    resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==}
+    engines: {node: '>=12'}
+
+  d3-octree@1.1.0:
+    resolution: {integrity: sha512-F8gPlqpP+HwRPMO/8uOu5wjH110+6q4cgJvgJT6vlpy3BEaDIKlTZrgHKZSp/i1InRpVfh4puY/kvL6MxK930A==}
+
+  d3-path@3.1.0:
+    resolution: {integrity: sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==}
+    engines: {node: '>=12'}
+
+  d3-quadtree@3.0.1:
+    resolution: {integrity: sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==}
+    engines: {node: '>=12'}
+
+  d3-random@3.0.1:
+    resolution: {integrity: sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==}
+    engines: {node: '>=12'}
+
+  d3-regression@1.3.10:
+    resolution: {integrity: sha512-PF8GWEL70cHHWpx2jUQXc68r1pyPHIA+St16muk/XRokETzlegj5LriNKg7o4LR0TySug4nHYPJNNRz/W+/Niw==}
+
+  d3-scale-chromatic@3.1.0:
+    resolution: {integrity: sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==}
+    engines: {node: '>=12'}
+
+  d3-scale@4.0.2:
+    resolution: {integrity: sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==}
+    engines: {node: '>=12'}
+
+  d3-shape@3.2.0:
+    resolution: {integrity: sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==}
+    engines: {node: '>=12'}
+
+  d3-time-format@4.1.0:
+    resolution: {integrity: sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==}
+    engines: {node: '>=12'}
+
+  d3-time@3.1.0:
+    resolution: {integrity: sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==}
+    engines: {node: '>=12'}
+
+  d3-timer@3.0.1:
+    resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==}
+    engines: {node: '>=12'}
+
   d8d-iframe-communicator@0.0.10:
     resolution: {integrity: sha512-VuBVcXE2ZdW6eSvJ13TBM1nkau6I8RzIcPpHF9XopLiLvx6AylIujVHEFQ4Fl6kGuABnh6VdulMCkC4zr7R0zA==}
 
@@ -1663,6 +1913,9 @@ packages:
   fast-decode-uri-component@1.0.1:
     resolution: {integrity: sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==}
 
+  fast-deep-equal@3.1.3:
+    resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
+
   fast-querystring@1.1.2:
     resolution: {integrity: sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==}
 
@@ -1678,6 +1931,9 @@ packages:
       picomatch:
         optional: true
 
+  fecha@4.2.3:
+    resolution: {integrity: sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==}
+
   fetch-blob@3.2.0:
     resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==}
     engines: {node: ^12.20 || >= 14.13}
@@ -1692,6 +1948,10 @@ packages:
   find-root@1.1.0:
     resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==}
 
+  flru@1.0.2:
+    resolution: {integrity: sha512-kWyh8ADvHBFz6ua5xYOPnUroZTT/bwWfrCeL0Wj1dzG4/YOmOcfJ99W8dOVyyynJN35rZ9aCOtHChqQovV7yog==}
+    engines: {node: '>=6'}
+
   follow-redirects@1.15.9:
     resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==}
     engines: {node: '>=4.0'}
@@ -1755,6 +2015,9 @@ packages:
   get-source@2.0.12:
     resolution: {integrity: sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w==}
 
+  gl-matrix@3.4.3:
+    resolution: {integrity: sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA==}
+
   glob-to-regexp@0.4.1:
     resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==}
 
@@ -1824,6 +2087,10 @@ packages:
   inherits@2.0.4:
     resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
 
+  internmap@2.0.3:
+    resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==}
+    engines: {node: '>=12'}
+
   ioredis@5.6.1:
     resolution: {integrity: sha512-UxC0Yv1Y4WRJiGQxQkP0hfdL0/5/6YvdfOOClRgJ0qppSarkhneSa6UvkMkms0AkdGimSH3Ikqm+6mkMmX7vGA==}
     engines: {node: '>=12.22.0'}
@@ -2168,6 +2435,9 @@ packages:
   pathe@2.0.3:
     resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
 
+  pdfast@0.2.0:
+    resolution: {integrity: sha512-cq6TTu6qKSFUHwEahi68k/kqN2mfepjkGrG9Un70cgdRRKLKY6Rf8P8uvP2NvZktaQZNF3YE7agEkLj0vGK9bA==}
+
   picocolors@1.1.1:
     resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
 
@@ -2193,6 +2463,12 @@ packages:
     resolution: {integrity: sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==}
     engines: {node: '>=6'}
 
+  quickselect@2.0.0:
+    resolution: {integrity: sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==}
+
+  rbush@3.0.1:
+    resolution: {integrity: sha512-XRaVO0YecOpEuIvbhbpTrZgoiI6xBlz6hnlr6EHhd+0x9ase6EmeN+hdwwUaJvLcsFFQ8iWVF1GAK1yB0BWi0w==}
+
   rc-cascader@3.34.0:
     resolution: {integrity: sha512-KpXypcvju9ptjW9FaN2NFcA2QH9E9LHKq169Y0eWtH4e/wHQ5Wh5qZakAgvb8EKZ736WZ3B0zLLOBsrsja5Dag==}
     peerDependencies:
@@ -2521,6 +2797,9 @@ packages:
     engines: {node: '>=18.0.0', npm: '>=8.0.0'}
     hasBin: true
 
+  rw@1.3.3:
+    resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==}
+
   safe-buffer@5.2.1:
     resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
 
@@ -2665,6 +2944,9 @@ packages:
     resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
     engines: {node: '>= 0.4'}
 
+  svg-path-parser@1.1.0:
+    resolution: {integrity: sha512-jGCUqcQyXpfe38R7RFfhrMyfXcBmpMNJI/B+4CE9/Unkh98UporAc461GTthv+TVDuZXsBx7/WiwJb1Oh4tt4A==}
+
   tailwindcss@4.1.10:
     resolution: {integrity: sha512-P3nr6WkvKV/ONsTzj6Gb57sWPMX29EPNPopo7+FcpkQaNsrNpZ1pv8QmrYI2RqEKD7mlGqLnGovlcYnBK0IqUA==}
 
@@ -2958,6 +3240,12 @@ snapshots:
       '@jridgewell/gen-mapping': 0.3.8
       '@jridgewell/trace-mapping': 0.3.25
 
+  '@ant-design/charts-util@0.0.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
+    dependencies:
+      lodash: 4.17.21
+      react: 19.1.0
+      react-dom: 19.1.0(react@19.1.0)
+
   '@ant-design/colors@7.2.1':
     dependencies:
       '@ant-design/fast-color': 2.0.6
@@ -3013,6 +3301,17 @@ snapshots:
       react: 19.1.0
       react-dom: 19.1.0(react@19.1.0)
 
+  '@ant-design/plots@2.6.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
+    dependencies:
+      '@ant-design/charts-util': 0.0.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+      '@antv/event-emitter': 0.1.3
+      '@antv/g': 6.1.28
+      '@antv/g2': 5.3.5
+      '@antv/g2-extension-plot': 0.2.2
+      lodash: 4.17.21
+      react: 19.1.0
+      react-dom: 19.1.0(react@19.1.0)
+
   '@ant-design/react-slick@1.1.2(react@19.1.0)':
     dependencies:
       '@babel/runtime': 7.27.6
@@ -3022,6 +3321,223 @@ snapshots:
       resize-observer-polyfill: 1.5.1
       throttle-debounce: 5.0.2
 
+  '@antv/component@2.1.5':
+    dependencies:
+      '@antv/g': 6.1.28
+      '@antv/scale': 0.4.16
+      '@antv/util': 3.3.11
+      svg-path-parser: 1.1.0
+
+  '@antv/coord@0.4.7':
+    dependencies:
+      '@antv/scale': 0.4.16
+      '@antv/util': 2.0.17
+      gl-matrix: 3.4.3
+
+  '@antv/event-emitter@0.1.3': {}
+
+  '@antv/expr@1.0.2': {}
+
+  '@antv/g-camera-api@2.0.41':
+    dependencies:
+      '@antv/g-lite': 2.3.2
+      '@antv/util': 3.3.11
+      '@babel/runtime': 7.27.6
+      gl-matrix: 3.4.3
+      tslib: 2.8.1
+
+  '@antv/g-canvas@2.0.48':
+    dependencies:
+      '@antv/g-lite': 2.3.2
+      '@antv/g-plugin-canvas-path-generator': 2.1.22
+      '@antv/g-plugin-canvas-picker': 2.1.27
+      '@antv/g-plugin-canvas-renderer': 2.3.3
+      '@antv/g-plugin-dom-interaction': 2.1.27
+      '@antv/g-plugin-html-renderer': 2.1.27
+      '@antv/g-plugin-image-loader': 2.1.26
+      '@antv/util': 3.3.11
+      '@babel/runtime': 7.27.6
+      tslib: 2.8.1
+
+  '@antv/g-dom-mutation-observer-api@2.0.38':
+    dependencies:
+      '@antv/g-lite': 2.3.2
+      '@babel/runtime': 7.27.6
+
+  '@antv/g-lite@2.3.2':
+    dependencies:
+      '@antv/g-math': 3.0.1
+      '@antv/util': 3.3.11
+      '@antv/vendor': 1.0.11
+      '@babel/runtime': 7.27.6
+      eventemitter3: 5.0.1
+      gl-matrix: 3.4.3
+      rbush: 3.0.1
+      tslib: 2.8.1
+
+  '@antv/g-math@3.0.1':
+    dependencies:
+      '@antv/util': 3.3.11
+      '@babel/runtime': 7.27.6
+      gl-matrix: 3.4.3
+      tslib: 2.8.1
+
+  '@antv/g-plugin-canvas-path-generator@2.1.22':
+    dependencies:
+      '@antv/g-lite': 2.3.2
+      '@antv/g-math': 3.0.1
+      '@antv/util': 3.3.11
+      '@babel/runtime': 7.27.6
+      tslib: 2.8.1
+
+  '@antv/g-plugin-canvas-picker@2.1.27':
+    dependencies:
+      '@antv/g-lite': 2.3.2
+      '@antv/g-math': 3.0.1
+      '@antv/g-plugin-canvas-path-generator': 2.1.22
+      '@antv/g-plugin-canvas-renderer': 2.3.3
+      '@antv/util': 3.3.11
+      '@babel/runtime': 7.27.6
+      gl-matrix: 3.4.3
+      tslib: 2.8.1
+
+  '@antv/g-plugin-canvas-renderer@2.3.3':
+    dependencies:
+      '@antv/g-lite': 2.3.2
+      '@antv/g-math': 3.0.1
+      '@antv/g-plugin-canvas-path-generator': 2.1.22
+      '@antv/g-plugin-image-loader': 2.1.26
+      '@antv/util': 3.3.11
+      '@babel/runtime': 7.27.6
+      gl-matrix: 3.4.3
+      tslib: 2.8.1
+
+  '@antv/g-plugin-dom-interaction@2.1.27':
+    dependencies:
+      '@antv/g-lite': 2.3.2
+      '@babel/runtime': 7.27.6
+      tslib: 2.8.1
+
+  '@antv/g-plugin-dragndrop@2.0.38':
+    dependencies:
+      '@antv/g-lite': 2.3.2
+      '@antv/util': 3.3.11
+      '@babel/runtime': 7.27.6
+      tslib: 2.8.1
+
+  '@antv/g-plugin-html-renderer@2.1.27':
+    dependencies:
+      '@antv/g-lite': 2.3.2
+      '@antv/util': 3.3.11
+      '@babel/runtime': 7.27.6
+      gl-matrix: 3.4.3
+      tslib: 2.8.1
+
+  '@antv/g-plugin-image-loader@2.1.26':
+    dependencies:
+      '@antv/g-lite': 2.3.2
+      '@antv/util': 3.3.11
+      '@babel/runtime': 7.27.6
+      gl-matrix: 3.4.3
+      tslib: 2.8.1
+
+  '@antv/g-web-animations-api@2.1.28':
+    dependencies:
+      '@antv/g-lite': 2.3.2
+      '@antv/util': 3.3.11
+      '@babel/runtime': 7.27.6
+      tslib: 2.8.1
+
+  '@antv/g2-extension-plot@0.2.2':
+    dependencies:
+      '@antv/g2': 5.3.5
+      '@antv/util': 3.3.11
+      '@antv/vendor': 1.0.11
+
+  '@antv/g2@5.3.5':
+    dependencies:
+      '@antv/component': 2.1.5
+      '@antv/coord': 0.4.7
+      '@antv/event-emitter': 0.1.3
+      '@antv/expr': 1.0.2
+      '@antv/g': 6.1.28
+      '@antv/g-canvas': 2.0.48
+      '@antv/g-plugin-dragndrop': 2.0.38
+      '@antv/scale': 0.4.16
+      '@antv/util': 3.3.11
+      '@antv/vendor': 1.0.11
+      flru: 1.0.2
+      pdfast: 0.2.0
+
+  '@antv/g@6.1.28':
+    dependencies:
+      '@antv/g-camera-api': 2.0.41
+      '@antv/g-dom-mutation-observer-api': 2.0.38
+      '@antv/g-lite': 2.3.2
+      '@antv/g-web-animations-api': 2.1.28
+      '@babel/runtime': 7.27.6
+
+  '@antv/scale@0.4.16':
+    dependencies:
+      '@antv/util': 3.3.11
+      color-string: 1.9.1
+      fecha: 4.2.3
+
+  '@antv/util@2.0.17':
+    dependencies:
+      csstype: 3.1.3
+      tslib: 2.8.1
+
+  '@antv/util@3.3.11':
+    dependencies:
+      fast-deep-equal: 3.1.3
+      gl-matrix: 3.4.3
+      tslib: 2.8.1
+
+  '@antv/vendor@1.0.11':
+    dependencies:
+      '@types/d3-array': 3.2.1
+      '@types/d3-color': 3.1.3
+      '@types/d3-dispatch': 3.0.7
+      '@types/d3-dsv': 3.0.7
+      '@types/d3-ease': 3.0.2
+      '@types/d3-fetch': 3.0.7
+      '@types/d3-force': 3.0.10
+      '@types/d3-format': 3.0.4
+      '@types/d3-geo': 3.1.0
+      '@types/d3-hierarchy': 3.1.7
+      '@types/d3-interpolate': 3.0.4
+      '@types/d3-path': 3.1.1
+      '@types/d3-quadtree': 3.0.6
+      '@types/d3-random': 3.0.3
+      '@types/d3-scale': 4.0.9
+      '@types/d3-scale-chromatic': 3.1.0
+      '@types/d3-shape': 3.1.7
+      '@types/d3-time': 3.0.4
+      '@types/d3-timer': 3.0.2
+      d3-array: 3.2.4
+      d3-color: 3.1.0
+      d3-dispatch: 3.0.1
+      d3-dsv: 3.0.1
+      d3-ease: 3.0.1
+      d3-fetch: 3.0.1
+      d3-force: 3.0.0
+      d3-force-3d: 3.0.6
+      d3-format: 3.1.0
+      d3-geo: 3.1.1
+      d3-geo-projection: 4.0.0
+      d3-hierarchy: 3.1.2
+      d3-interpolate: 3.0.1
+      d3-path: 3.1.0
+      d3-quadtree: 3.0.1
+      d3-random: 3.0.1
+      d3-regression: 1.3.10
+      d3-scale: 4.0.2
+      d3-scale-chromatic: 3.1.0
+      d3-shape: 3.2.0
+      d3-time: 3.1.0
+      d3-timer: 3.0.1
+
   '@asteasolutions/zod-to-openapi@7.3.3(zod@3.24.2)':
     dependencies:
       openapi3-ts: 4.4.0
@@ -3866,12 +4382,62 @@ snapshots:
     dependencies:
       '@types/node': 22.15.31
 
+  '@types/d3-array@3.2.1': {}
+
+  '@types/d3-color@3.1.3': {}
+
+  '@types/d3-dispatch@3.0.7': {}
+
+  '@types/d3-dsv@3.0.7': {}
+
+  '@types/d3-ease@3.0.2': {}
+
+  '@types/d3-fetch@3.0.7':
+    dependencies:
+      '@types/d3-dsv': 3.0.7
+
+  '@types/d3-force@3.0.10': {}
+
+  '@types/d3-format@3.0.4': {}
+
+  '@types/d3-geo@3.1.0':
+    dependencies:
+      '@types/geojson': 7946.0.16
+
+  '@types/d3-hierarchy@3.1.7': {}
+
+  '@types/d3-interpolate@3.0.4':
+    dependencies:
+      '@types/d3-color': 3.1.3
+
+  '@types/d3-path@3.1.1': {}
+
+  '@types/d3-quadtree@3.0.6': {}
+
+  '@types/d3-random@3.0.3': {}
+
+  '@types/d3-scale-chromatic@3.1.0': {}
+
+  '@types/d3-scale@4.0.9':
+    dependencies:
+      '@types/d3-time': 3.0.4
+
+  '@types/d3-shape@3.1.7':
+    dependencies:
+      '@types/d3-path': 3.1.1
+
+  '@types/d3-time@3.0.4': {}
+
+  '@types/d3-timer@3.0.2': {}
+
   '@types/debug@4.1.12':
     dependencies:
       '@types/ms': 2.1.0
 
   '@types/estree@1.0.7': {}
 
+  '@types/geojson@7946.0.16': {}
+
   '@types/jsonwebtoken@9.0.9':
     dependencies:
       '@types/ms': 2.1.0
@@ -4140,6 +4706,8 @@ snapshots:
     dependencies:
       delayed-stream: 1.0.0
 
+  commander@7.2.0: {}
+
   compute-scroll-into-view@3.1.1: {}
 
   convert-source-map@1.9.0: {}
@@ -4170,6 +4738,97 @@ snapshots:
 
   csstype@3.1.3: {}
 
+  d3-array@3.2.4:
+    dependencies:
+      internmap: 2.0.3
+
+  d3-binarytree@1.0.2: {}
+
+  d3-color@3.1.0: {}
+
+  d3-dispatch@3.0.1: {}
+
+  d3-dsv@3.0.1:
+    dependencies:
+      commander: 7.2.0
+      iconv-lite: 0.6.3
+      rw: 1.3.3
+
+  d3-ease@3.0.1: {}
+
+  d3-fetch@3.0.1:
+    dependencies:
+      d3-dsv: 3.0.1
+
+  d3-force-3d@3.0.6:
+    dependencies:
+      d3-binarytree: 1.0.2
+      d3-dispatch: 3.0.1
+      d3-octree: 1.1.0
+      d3-quadtree: 3.0.1
+      d3-timer: 3.0.1
+
+  d3-force@3.0.0:
+    dependencies:
+      d3-dispatch: 3.0.1
+      d3-quadtree: 3.0.1
+      d3-timer: 3.0.1
+
+  d3-format@3.1.0: {}
+
+  d3-geo-projection@4.0.0:
+    dependencies:
+      commander: 7.2.0
+      d3-array: 3.2.4
+      d3-geo: 3.1.1
+
+  d3-geo@3.1.1:
+    dependencies:
+      d3-array: 3.2.4
+
+  d3-hierarchy@3.1.2: {}
+
+  d3-interpolate@3.0.1:
+    dependencies:
+      d3-color: 3.1.0
+
+  d3-octree@1.1.0: {}
+
+  d3-path@3.1.0: {}
+
+  d3-quadtree@3.0.1: {}
+
+  d3-random@3.0.1: {}
+
+  d3-regression@1.3.10: {}
+
+  d3-scale-chromatic@3.1.0:
+    dependencies:
+      d3-color: 3.1.0
+      d3-interpolate: 3.0.1
+
+  d3-scale@4.0.2:
+    dependencies:
+      d3-array: 3.2.4
+      d3-format: 3.1.0
+      d3-interpolate: 3.0.1
+      d3-time: 3.1.0
+      d3-time-format: 4.1.0
+
+  d3-shape@3.2.0:
+    dependencies:
+      d3-path: 3.1.0
+
+  d3-time-format@4.1.0:
+    dependencies:
+      d3-time: 3.1.0
+
+  d3-time@3.1.0:
+    dependencies:
+      d3-array: 3.2.4
+
+  d3-timer@3.0.1: {}
+
   d8d-iframe-communicator@0.0.10: {}
 
   data-uri-to-buffer@2.0.2: {}
@@ -4314,6 +4973,8 @@ snapshots:
 
   fast-decode-uri-component@1.0.1: {}
 
+  fast-deep-equal@3.1.3: {}
+
   fast-querystring@1.1.2:
     dependencies:
       fast-decode-uri-component: 1.0.1
@@ -4326,6 +4987,8 @@ snapshots:
     optionalDependencies:
       picomatch: 4.0.2
 
+  fecha@4.2.3: {}
+
   fetch-blob@3.2.0:
     dependencies:
       node-domexception: 1.0.0
@@ -4337,6 +5000,8 @@ snapshots:
 
   find-root@1.1.0: {}
 
+  flru@1.0.2: {}
+
   follow-redirects@1.15.9(debug@4.4.1):
     optionalDependencies:
       debug: 4.4.1
@@ -4402,6 +5067,8 @@ snapshots:
       data-uri-to-buffer: 2.0.2
       source-map: 0.6.1
 
+  gl-matrix@3.4.3: {}
+
   glob-to-regexp@0.4.1: {}
 
   glob@10.4.5:
@@ -4480,6 +5147,8 @@ snapshots:
 
   inherits@2.0.4: {}
 
+  internmap@2.0.3: {}
+
   ioredis@5.6.1:
     dependencies:
       '@ioredis/commands': 1.2.0
@@ -4815,6 +5484,8 @@ snapshots:
 
   pathe@2.0.3: {}
 
+  pdfast@0.2.0: {}
+
   picocolors@1.1.1: {}
 
   picomatch@4.0.2: {}
@@ -4838,6 +5509,12 @@ snapshots:
       split-on-first: 1.1.0
       strict-uri-encode: 2.0.0
 
+  quickselect@2.0.0: {}
+
+  rbush@3.0.1:
+    dependencies:
+      quickselect: 2.0.0
+
   rc-cascader@3.34.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
     dependencies:
       '@babel/runtime': 7.27.6
@@ -5257,6 +5934,8 @@ snapshots:
       '@rollup/rollup-win32-x64-msvc': 4.43.0
       fsevents: 2.3.3
 
+  rw@1.3.3: {}
+
   safe-buffer@5.2.1: {}
 
   safe-regex-test@1.1.0:
@@ -5400,6 +6079,8 @@ snapshots:
 
   supports-preserve-symlinks-flag@1.0.0: {}
 
+  svg-path-parser@1.1.0: {}
+
   tailwindcss@4.1.10: {}
 
   tapable@2.2.2: {}

+ 67 - 0
src/client/admin/components/BigScreenHeader.tsx

@@ -0,0 +1,67 @@
+import React, { useState, useEffect } from 'react';
+import { Space, Typography, Tag, Avatar } from 'antd';
+import {
+  ThunderboltOutlined,
+  ClockCircleOutlined,
+  WifiOutlined,
+  SoundOutlined,
+  BellOutlined,
+  SettingOutlined,
+} from '@ant-design/icons';
+import dayjs from 'dayjs';
+
+const { Title, Text } = Typography;
+
+const BigScreenHeader: React.FC = () => {
+  const [currentTime, setCurrentTime] = useState(dayjs());
+
+  useEffect(() => {
+    const timer = setInterval(() => {
+      setCurrentTime(dayjs());
+    }, 1000);
+    return () => clearInterval(timer);
+  }, []);
+
+  return (
+    <div className="flex items-center justify-between p-4 bg-gradient-to-r from-gray-800 to-gray-900 rounded-lg mb-6">
+      <div className="flex items-center space-x-4">
+        <ThunderboltOutlined className="text-3xl text-yellow-400" />
+        <div>
+          <Title level={2} className="text-white !mb-1">
+            银龄人才大数据监控中心
+          </Title>
+          <Text className="text-gray-300">
+            Real-time Data Monitoring & Intelligent Analysis
+          </Text>
+        </div>
+      </div>
+      
+      <div className="flex items-center space-x-6">
+        <Space>
+          <Tag icon={<WifiOutlined />} color="success">
+            系统在线
+          </Tag>
+          <Tag icon={<SoundOutlined />} color="processing">
+            数据同步
+          </Tag>
+          <Tag icon={<BellOutlined />} color="warning">
+            3条通知
+          </Tag>
+        </Space>
+        
+        <div className="text-right">
+          <div className="text-2xl font-bold text-white">
+            {currentTime.format('HH:mm:ss')}
+          </div>
+          <div className="text-sm text-gray-300">
+            {currentTime.format('YYYY-MM-DD')} {currentTime.format('dddd')}
+          </div>
+        </div>
+        
+        <Avatar size="large" icon={<SettingOutlined />} className="bg-blue-500" />
+      </div>
+    </div>
+  );
+};
+
+export default BigScreenHeader;

+ 71 - 0
src/client/admin/components/StatCard.tsx

@@ -0,0 +1,71 @@
+import React from 'react';
+import { Card, Statistic, Tag } from 'antd';
+import { ArrowUpOutlined, ArrowDownOutlined } from '@ant-design/icons';
+
+interface StatCardProps {
+  title: string;
+  value: number;
+  prefix?: React.ReactNode;
+  suffix?: string;
+  trend?: 'up' | 'down';
+  trendValue?: string;
+  color: string;
+  icon: React.ReactNode;
+}
+
+const StatCard: React.FC<StatCardProps> = ({
+  title,
+  value,
+  prefix,
+  suffix = '',
+  trend,
+  trendValue,
+  color,
+  icon,
+}) => {
+  const gradientColors = {
+    blue: 'from-blue-500 to-blue-600',
+    green: 'from-green-500 to-green-600',
+    orange: 'from-orange-500 to-orange-600',
+    purple: 'from-purple-500 to-purple-600',
+    red: 'from-red-500 to-red-600',
+    pink: 'from-pink-500 to-pink-600',
+  };
+
+  return (
+    <Card
+      className={`bg-gradient-to-r ${gradientColors[color as keyof typeof gradientColors]} border-0 shadow-2xl transform transition-all duration-300 hover:scale-105 hover:shadow-3xl`}
+      bodyStyle={{ padding: '24px' }}
+    >
+      <div className="flex items-center justify-between">
+        <div>
+          <div className="text-white text-lg mb-2">{title}</div>
+          <div className="text-white text-4xl font-bold">
+            {value.toLocaleString()}
+          </div>
+          {trend && trendValue && (
+            <div className="text-white opacity-80 mt-2 flex items-center">
+              {trend === 'up' ? (
+                <ArrowUpOutlined className="mr-1" />
+              ) : (
+                <ArrowDownOutlined className="mr-1" />
+              )}
+              {trendValue}
+            </div>
+          )}
+        </div>
+        <div className="text-white opacity-80">
+          {React.cloneElement(icon as React.ReactElement, { className: 'text-5xl' })}
+        </div>
+      </div>
+      
+      <div className="mt-4">
+        <Tag color="white" className="bg-white bg-opacity-20 border-0 text-white">
+          {suffix}
+        </Tag>
+      </div>
+    </Card>
+  );
+};
+
+export default StatCard;

+ 204 - 0
src/client/admin/hooks/useBigScreenData.ts

@@ -0,0 +1,204 @@
+import { useRequest } from 'ahooks';
+import { 
+  usersClient, 
+  silverTalentsClient, 
+  silverJobsClient, 
+  silverKnowledgesClient,
+  filesClient,
+  homeIconsClient,
+  companyCertificationClient,
+  silverUsersClient
+} from '@/client/api';
+
+// 大屏幕数据Hook
+export const useBigScreenData = () => {
+  // 获取用户统计数据
+  const { data: userStats, loading: userLoading } = useRequest(async () => {
+    try {
+      const response = await usersClient.$get({
+        query: { page: 1, pageSize: 1 }
+      });
+      const result = await response.json();
+      return { 
+        total: result.pagination?.total || 0,
+        today: Math.floor(Math.random() * 50) + 10, // 模拟今日新增
+        active: Math.floor((result.pagination?.total || 0) * 0.78)
+      };
+    } catch (error) {
+      console.error('获取用户统计失败:', error);
+      return { total: 0, today: 0, active: 0 };
+    }
+  }, {
+    refreshDeps: [],
+    pollingInterval: 30000,
+  });
+
+  // 获取银龄人才数据
+  const { data: talentStats, loading: talentLoading } = useRequest(async () => {
+    try {
+      const response = await silverTalentsClient.$get({
+        query: { page: 1, pageSize: 1 }
+      });
+      const result = await response.json();
+      return { 
+        total: result.pagination?.total || 0,
+        verified: Math.floor((result.pagination?.total || 0) * 0.85),
+        active: Math.floor((result.pagination?.total || 0) * 0.78)
+      };
+    } catch (error) {
+      console.error('获取银龄人才统计失败:', error);
+      return { total: 0, verified: 0, active: 0 };
+    }
+  }, {
+    refreshDeps: [],
+    pollingInterval: 30000,
+  });
+
+  // 获取岗位数据
+  const { data: jobStats, loading: jobLoading } = useRequest(async () => {
+    try {
+      const response = await silverJobsClient.$get({
+        query: { page: 1, pageSize: 1 }
+      });
+      const result = await response.json();
+      return { 
+        total: result.pagination?.total || 0,
+        open: Math.floor((result.pagination?.total || 0) * 0.65),
+        matched: Math.floor((result.pagination?.total || 0) * 0.85)
+      };
+    } catch (error) {
+      console.error('获取岗位统计失败:', error);
+      return { total: 0, open: 0, matched: 0 };
+    }
+  }, {
+    refreshDeps: [],
+    pollingInterval: 30000,
+  });
+
+  // 获取知识库数据
+  const { data: knowledgeStats, loading: knowledgeLoading } = useRequest(async () => {
+    try {
+      const response = await silverKnowledgesClient.$get({
+        query: { page: 1, pageSize: 1 }
+      });
+      const result = await response.json();
+      
+      // 获取知识分类统计
+      const categoryResponse = await silverUsersClient['knowledge-categories'].$get({
+        query: { page: 1, pageSize: 100 }
+      });
+      const categoryResult = await categoryResponse.json();
+      
+      return { 
+        total: result.pagination?.total || 0,
+        categories: categoryResult.pagination?.total || 0,
+        thisMonth: Math.floor(Math.random() * 200) + 100
+      };
+    } catch (error) {
+      console.error('获取知识库统计失败:', error);
+      return { total: 0, categories: 0, thisMonth: 0 };
+    }
+  }, {
+    refreshDeps: [],
+    pollingInterval: 30000,
+  });
+
+  // 获取文件数据
+  const { data: fileStats, loading: fileLoading } = useRequest(async () => {
+    try {
+      const response = await filesClient.$get({
+        query: { page: 1, pageSize: 1 }
+      });
+      const result = await response.json();
+      return { 
+        total: result.pagination?.total || 0,
+        images: Math.floor((result.pagination?.total || 0) * 0.6),
+        documents: Math.floor((result.pagination?.total || 0) * 0.3),
+        videos: Math.floor((result.pagination?.total || 0) * 0.1)
+      };
+    } catch (error) {
+      console.error('获取文件统计失败:', error);
+      return { total: 0, images: 0, documents: 0, videos: 0 };
+    }
+  }, {
+    refreshDeps: [],
+    pollingInterval: 30000,
+  });
+
+  // 获取公司认证数据
+  const { data: companyStats, loading: companyLoading } = useRequest(async () => {
+    try {
+      const response = await companyCertificationClient.$get({
+        query: { page: 1, pageSize: 1 }
+      });
+      const result = await response.json();
+      return { 
+        total: result.pagination?.total || 0,
+        certified: Math.floor((result.pagination?.total || 0) * 0.75),
+        pending: Math.floor((result.pagination?.total || 0) * 0.15)
+      };
+    } catch (error) {
+      console.error('获取公司认证统计失败:', error);
+      return { total: 0, certified: 0, pending: 0 };
+    }
+  }, {
+    refreshDeps: [],
+    pollingInterval: 30000,
+  });
+
+  // 生成图表数据
+  const generateChartData = () => {
+    const hours = Array.from({ length: 24 }, (_, i) => `${i}:00`);
+    return hours.map(hour => ({
+      time: hour,
+      users: Math.floor(Math.random() * 100) + 50,
+      talents: Math.floor(Math.random() * 80) + 30,
+      jobs: Math.floor(Math.random() * 60) + 20,
+      knowledge: Math.floor(Math.random() * 40) + 10,
+    }));
+  };
+
+  const generateWeeklyData = () => {
+    const days = ['周一', '周二', '周三', '周四', '周五', '周六', '周日'];
+    return days.map(day => ({
+      day,
+      users: Math.floor(Math.random() * 200) + 100,
+      talents: Math.floor(Math.random() * 150) + 80,
+      jobs: Math.floor(Math.random() * 100) + 50,
+      knowledge: Math.floor(Math.random() * 80) + 40,
+    }));
+  };
+
+  const generateCategoryData = () => [
+    { category: '技能分享', value: 35, color: '#1890ff' },
+    { category: '政策咨询', value: 25, color: '#52c41a' },
+    { category: '岗位匹配', value: 20, color: '#faad14' },
+    { category: '学习培训', value: 15, color: '#722ed1' },
+    { category: '其他', value: 5, color: '#13c2c2' },
+  ];
+
+  return {
+    // 统计数据
+    userStats,
+    talentStats,
+    jobStats,
+    knowledgeStats,
+    fileStats,
+    companyStats,
+    
+    // 图表数据
+    realtimeData: generateChartData(),
+    weeklyData: generateWeeklyData(),
+    categoryData: generateCategoryData(),
+    
+    // 加载状态
+    loading: {
+      user: userLoading,
+      talent: talentLoading,
+      job: jobLoading,
+      knowledge: knowledgeLoading,
+      file: fileLoading,
+      company: companyLoading,
+    },
+  };
+};

+ 8 - 0
src/client/admin/menu.tsx

@@ -14,6 +14,7 @@ import {
   PictureOutlined,
   BookOutlined,
   FolderOutlined,
+  FundViewOutlined,
 } from '@ant-design/icons';
 
 export interface MenuItem {
@@ -141,6 +142,13 @@ export const useMenu = () => {
       path: '/admin/knowledge-categories',
       permission: 'silver-knowledge:manage'
     },
+    {
+      key: 'big-screen',
+      label: '大数据监控',
+      icon: <FundViewOutlined />,
+      path: '/admin/big-screen',
+      permission: 'dashboard:view'
+    },
   ];
 
   // 用户菜单项

+ 358 - 0
src/client/admin/pages/BigScreenDashboard.tsx

@@ -0,0 +1,358 @@
+import React, { useState, useEffect } from 'react';
+import { Card, Row, Col, Statistic, Typography, Space, Timeline, List, Avatar, Progress, Tag } from 'antd';
+import {
+  UserOutlined,
+  TeamOutlined,
+  BookOutlined,
+  FileTextOutlined,
+  TrendingUpOutlined,
+  ClockCircleOutlined,
+  BarChartOutlined,
+  PieChartOutlined,
+  EyeOutlined,
+  HeartOutlined,
+  StarOutlined,
+  DownloadOutlined,
+  UploadOutlined,
+  DatabaseOutlined,
+  CloudOutlined,
+  ThunderboltOutlined,
+  FireOutlined,
+  RocketOutlined
+} from '@ant-design/icons';
+import { Line, Pie, Column } from '@ant-design/plots';
+import { useRequest } from 'ahooks';
+import dayjs from 'dayjs';
+import { 
+  usersClient, 
+  silverTalentsClient, 
+  silverJobsClient, 
+  silverKnowledgesClient,
+  filesClient,
+  homeIconsClient,
+  companyCertificationClient
+} from '@/client/api';
+
+const { Title, Text } = Typography;
+
+// 大屏幕仪表板组件
+const BigScreenDashboard: React.FC = () => {
+  const [currentTime, setCurrentTime] = useState(dayjs());
+  const [realtimeData, setRealtimeData] = useState<any[]>([]);
+
+  // 实时时钟
+  useEffect(() => {
+    const timer = setInterval(() => {
+      setCurrentTime(dayjs());
+    }, 1000);
+    return () => clearInterval(timer);
+  }, []);
+
+  // 获取用户统计数据
+  const { data: userStats } = useRequest(async () => {
+    const response = await usersClient.$get({
+      query: { page: 1, pageSize: 1 }
+    });
+    const result = await response.json();
+    return { total: result.pagination?.total || 0 };
+  }, {
+    refreshDeps: [],
+    pollingInterval: 30000,
+  });
+
+  // 获取银龄人才数据
+  const { data: talentStats } = useRequest(async () => {
+    const response = await silverTalentsClient.$get({
+      query: { page: 1, pageSize: 1 }
+    });
+    const result = await response.json();
+    return { total: result.pagination?.total || 0 };
+  }, {
+    refreshDeps: [],
+    pollingInterval: 30000,
+  });
+
+  // 获取岗位数据
+  const { data: jobStats } = useRequest(async () => {
+    const response = await silverJobsClient.$get({
+      query: { page: 1, pageSize: 1 }
+    });
+    const result = await response.json();
+    return { total: result.pagination?.total || 0 };
+  }, {
+    refreshDeps: [],
+    pollingInterval: 30000,
+  });
+
+  // 获取知识库数据
+  const { data: knowledgeStats } = useRequest(async () => {
+    const response = await silverKnowledgesClient.$get({
+      query: { page: 1, pageSize: 1 }
+    });
+    const result = await response.json();
+    return { total: result.pagination?.total || 0 };
+  }, {
+    refreshDeps: [],
+    pollingInterval: 30000,
+  });
+
+  // 获取文件数据
+  const { data: fileStats } = useRequest(async () => {
+    const response = await filesClient.$get({
+      query: { page: 1, pageSize: 1 }
+    });
+    const result = await response.json();
+    return { total: result.pagination?.total || 0 };
+  }, {
+    refreshDeps: [],
+    pollingInterval: 30000,
+  });
+
+  // 模拟实时活动数据
+  useEffect(() => {
+    const activities = [
+      { user: '张大爷', action: '发布了新技能', time: '刚刚', icon: <RocketOutlined className="text-blue-500" /> },
+      { user: '李奶奶', action: '收藏了政策资讯', time: '1分钟前', icon: <HeartOutlined className="text-red-500" /> },
+      { user: '王教授', action: '上传了教学视频', time: '3分钟前', icon: <UploadOutlined className="text-green-500" /> },
+      { user: '刘阿姨', action: '申请了银龄岗位', time: '5分钟前', icon: <FileTextOutlined className="text-purple-500" /> },
+      { user: '陈师傅', action: '完成了时间银行任务', time: '8分钟前', icon: <ClockCircleOutlined className="text-orange-500" /> },
+    ];
+    
+    const interval = setInterval(() => {
+      const randomActivity = activities[Math.floor(Math.random() * activities.length)];
+      setRealtimeData(prev => [randomActivity, ...prev].slice(0, 5));
+    }, 10000);
+    
+    return () => clearInterval(interval);
+  }, []);
+
+  // 模拟图表数据
+  const lineData = [
+    { date: '00:00', users: 120, talents: 80, jobs: 45 },
+    { date: '04:00', users: 132, talents: 100, jobs: 50 },
+    { date: '08:00', users: 201, talents: 160, jobs: 85 },
+    { date: '12:00', users: 334, talents: 280, jobs: 120 },
+    { date: '16:00', users: 290, talents: 250, jobs: 110 },
+    { date: '20:00', users: 330, talents: 320, jobs: 145 },
+    { date: '24:00', users: 340, talents: 350, jobs: 150 },
+  ];
+
+  const pieData = [
+    { type: '技能分享', value: 35, color: '#1890ff' },
+    { type: '政策咨询', value: 25, color: '#52c41a' },
+    { type: '岗位匹配', value: 20, color: '#faad14' },
+    { type: '学习培训', value: 15, color: '#722ed1' },
+    { type: '其他', value: 5, color: '#13c2c2' },
+  ];
+
+  const columnData = [
+    { category: '周一', users: 120, talents: 80, jobs: 40 },
+    { category: '周二', users: 132, talents: 100, jobs: 55 },
+    { category: '周三', users: 201, talents: 160, jobs: 70 },
+    { category: '周四', users: 234, talents: 200, jobs: 85 },
+    { category: '周五', users: 290, talents: 250, jobs: 100 },
+    { category: '周六', users: 330, talents: 320, jobs: 120 },
+    { category: '周日', users: 340, talents: 350, jobs: 140 },
+  ];
+
+  const lineConfig = {
+    data: lineData,
+    xField: 'date',
+    yField: 'value',
+    seriesField: 'category',
+    color: ['#1890ff', '#52c41a', '#faad14'],
+    smooth: true,
+    animation: { appear: { animation: 'wave-in', duration: 2000 } },
+  };
+
+  const pieConfig = {
+    data: pieData,
+    angleField: 'value',
+    colorField: 'type',
+    color: pieData.map(item => item.color),
+    radius: 0.8,
+    innerRadius: 0.6,
+    label: {
+      type: 'inner',
+      offset: '-50%',
+      content: '{value}%',
+      style: { textAlign: 'center', fontSize: 14 },
+    },
+    interactions: [{ type: 'element-selected' }, { type: 'element-active' }],
+  };
+
+  const columnConfig = {
+    data: columnData,
+    xField: 'category',
+    yField: 'users',
+    color: '#1890ff',
+    columnStyle: { radius: [4, 4, 0, 0] },
+    animation: { appear: { animation: 'scale-in-y', duration: 2000 } },
+  };
+
+  return (
+    <div className="min-h-screen bg-gradient-to-br from-gray-900 via-blue-900 to-purple-900 p-6">
+      {/* 顶部标题栏 */}
+      <div className="mb-6 flex items-center justify-between">
+        <div>
+          <Title level={1} className="text-white !mb-2">
+            <ThunderboltOutlined className="mr-3 text-yellow-400" />
+            银龄人才大数据监控中心
+          </Title>
+          <Text className="text-gray-300 text-lg">
+            实时数据监控 · 智能分析决策 · 精准服务匹配
+          </Text>
+        </div>
+        <div className="text-right">
+          <div className="text-3xl font-bold text-white">
+            {currentTime.format('HH:mm:ss')}
+          </div>
+          <div className="text-gray-300">
+            {currentTime.format('YYYY年MM月DD日')} {currentTime.format('dddd')}
+          </div>
+        </div>
+      </div>
+
+      {/* 核心数据卡片 */}
+      <Row gutter={[24, 24]} className="mb-6">
+        <Col span={6}>
+          <Card className="bg-gradient-to-r from-blue-500 to-blue-600 border-0 shadow-2xl">
+            <Statistic
+              title={<span className="text-white text-lg">总用户数</span>}
+              value={userStats?.total || 0}
+              valueStyle={{ color: 'white', fontSize: 36, fontWeight: 'bold' }}
+              prefix={<UserOutlined className="text-white text-2xl" />}
+              suffix={<Tag color="blue" className="ml-2">人</Tag>}
+            />
+            <div className="mt-2 text-white opacity-80">
+              <TrendingUpOutlined /> 今日新增: +12人
+            </div>
+          </Card>
+        </Col>
+        <Col span={6}>
+          <Card className="bg-gradient-to-r from-green-500 to-green-600 border-0 shadow-2xl">
+            <Statistic
+              title={<span className="text-white text-lg">银龄人才</span>}
+              value={talentStats?.total || 0}
+              valueStyle={{ color: 'white', fontSize: 36, fontWeight: 'bold' }}
+              prefix={<TeamOutlined className="text-white text-2xl" />}
+              suffix={<Tag color="green" className="ml-2">人</Tag>}
+            />
+            <div className="mt-2 text-white opacity-80">
+              <TrendingUpOutlined /> 活跃占比: 78%
+            </div>
+          </Card>
+        </Col>
+        <Col span={6}>
+          <Card className="bg-gradient-to-r from-orange-500 to-orange-600 border-0 shadow-2xl">
+            <Statistic
+              title={<span className="text-white text-lg">岗位机会</span>}
+              value={jobStats?.total || 0}
+              valueStyle={{ color: 'white', fontSize: 36, fontWeight: 'bold' }}
+              prefix={<FileTextOutlined className="text-white text-2xl" />}
+              suffix={<Tag color="orange" className="ml-2">个</Tag>}
+            />
+            <div className="mt-2 text-white opacity-80">
+              <TrendingUpOutlined /> 匹配成功率: 85%
+            </div>
+          </Card>
+        </Col>
+        <Col span={6}>
+          <Card className="bg-gradient-to-r from-purple-500 to-purple-600 border-0 shadow-2xl">
+            <Statistic
+              title={<span className="text-white text-lg">知识库</span>}
+              value={knowledgeStats?.total || 0}
+              valueStyle={{ color: 'white', fontSize: 36, fontWeight: 'bold' }}
+              prefix={<BookOutlined className="text-white text-2xl" />}
+              suffix={<Tag color="purple" className="ml-2">篇</Tag>}
+            />
+            <div className="mt-2 text-white opacity-80">
+              <TrendingUpOutlined /> 本月新增: 156篇
+            </div>
+          </Card>
+        </Col>
+      </Row>
+
+      {/* 图表区域 */}
+      <Row gutter={[24, 24]} className="mb-6">
+        <Col span={12}>
+          <Card title="24小时活跃度趋势" className="bg-white bg-opacity-10 border-0 backdrop-blur-sm">
+            <Line {...lineConfig} />
+          </Card>
+        </Col>
+        <Col span={12}>
+          <Card title="内容类型分布" className="bg-white bg-opacity-10 border-0 backdrop-blur-sm">
+            <Pie {...pieConfig} />
+          </Card>
+        </Col>
+      </Row>
+
+      <Row gutter={[24, 24]} className="mb-6">
+        <Col span={16}>
+          <Card title="周活跃度统计" className="bg-white bg-opacity-10 border-0 backdrop-blur-sm">
+            <Column {...columnConfig} />
+          </Card>
+        </Col>
+        <Col span={8}>
+          <Card title="实时活动" className="bg-white bg-opacity-10 border-0 backdrop-blur-sm">
+            <Timeline
+              items={realtimeData.map((item, index) => ({
+                color: index === 0 ? 'green' : 'gray',
+                dot: item.icon,
+                children: (
+                  <div className="text-white">
+                    <div className="font-semibold">{item.user}</div>
+                    <div className="text-sm opacity-80">{item.action}</div>
+                    <div className="text-xs opacity-60">{item.time}</div>
+                  </div>
+                ),
+              }))}
+            />
+          </Card>
+        </Col>
+      </Row>
+
+      {/* 底部状态栏 */}
+      <Row gutter={[24, 24]}>
+        <Col span={8}>
+          <Card className="bg-white bg-opacity-10 border-0 backdrop-blur-sm">
+            <div className="flex items-center justify-between">
+              <div>
+                <Text className="text-white">文件总数</Text>
+                <div className="text-2xl font-bold text-white">{fileStats?.total || 0}</div>
+              </div>
+              <DatabaseOutlined className="text-4xl text-blue-400" />
+            </div>
+            <Progress percent={75} strokeColor="#1890ff" showInfo={false} />
+          </Card>
+        </Col>
+        <Col span={8}>
+          <Card className="bg-white bg-opacity-10 border-0 backdrop-blur-sm">
+            <div className="flex items-center justify-between">
+              <div>
+                <Text className="text-white">系统健康度</Text>
+                <div className="text-2xl font-bold text-white">99.8%</div>
+              </div>
+              <CloudOutlined className="text-4xl text-green-400" />
+            </div>
+            <Progress percent={99.8} strokeColor="#52c41a" showInfo={false} />
+          </Card>
+        </Col>
+        <Col span={8}>
+          <Card className="bg-white bg-opacity-10 border-0 backdrop-blur-sm">
+            <div className="flex items-center justify-between">
+              <div>
+                <Text className="text-white">今日访问</Text>
+                <div className="text-2xl font-bold text-white">1,234</div>
+              </div>
+              <EyeOutlined className="text-4xl text-orange-400" />
+            </div>
+            <Progress percent={85} strokeColor="#faad14" showInfo={false} />
+          </Card>
+        </Col>
+      </Row>
+    </div>
+  );
+};
+
+export default BigScreenDashboard;

+ 6 - 0
src/client/admin/routes.tsx

@@ -15,6 +15,7 @@ import HomeIconsPage from './pages/HomeIcons';
 import SilverKnowledgesPage from './pages/SilverKnowledges';
 import SilverKnowledgeDetailPage from './pages/SilverKnowledgeDetailPage';
 import KnowledgeCategories from './pages/KnowledgeCategories';
+import BigScreenDashboard from './pages/BigScreenDashboard';
 
 export const router = createBrowserRouter([
   {
@@ -87,6 +88,11 @@ export const router = createBrowserRouter([
         element: <KnowledgeCategories />,
         errorElement: <ErrorPage />
       },
+      {
+        path: 'big-screen',
+        element: <BigScreenDashboard />,
+        errorElement: <ErrorPage />
+      },
       {
         path: '*',
         element: <NotFoundPage />,