From a69190cbdc19ea9f0d4b65d420ed38d266946ad2 Mon Sep 17 00:00:00 2001 From: mmc <1556375442@qq.com> Date: Mon, 10 Aug 2026 15:25:56 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A7=86=E9=A2=91=E6=8E=A5=E5=85=A5=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build_log2.txt | 217 +++++++++++++ package-lock.json | 23 ++ package.json | 1 + .../SystemSetting/VideoManagement.tsx | 297 +++++++++++++----- 4 files changed, 464 insertions(+), 74 deletions(-) create mode 100644 build_log2.txt diff --git a/build_log2.txt b/build_log2.txt new file mode 100644 index 0000000..9c7a88a --- /dev/null +++ b/build_log2.txt @@ -0,0 +1,217 @@ + +> react-example@0.0.0 build +> vite build + +vite v6.4.2 building for production... +transforming... +鉁?[39m 9321 modules transformed. +rendering chunks... +npm : [plugin vite:reporter] +所在位置 行:1 字符: 25 ++ cd "D:\code\机器人智慧服务系统"; npm run build 2>&1 | Out-String -Width 300 | ... ++ ~~~~~~~~~~~~~~~~~~ + + CategoryInfo : NotSpecified: ([plugin vite:reporter] :String) [], RemoteException + + FullyQualifiedErrorId : NativeCommandError + +(!) D:/code/鏈哄櫒浜烘櫤鎱ф湇鍔$郴缁?src/store/userSlice.ts is dynamically imported by D:/code/鏈哄櫒浜烘櫤鎱ф湇鍔$郴缁?src/api/request.ts but also statically imported by D:/code/鏈哄櫒浜烘櫤鎱ф湇鍔$郴缁?src/components/Layout.tsx, D:/code/鏈哄櫒浜烘櫤鎱ф湇鍔$郴缁?src/pages/Login.tsx, D:/code/鏈哄櫒浜烘櫤鎱ф湇鍔$郴缁?src/pages/Profile.tsx, D:/code/鏈哄櫒浜烘櫤 +鎱ф湇鍔$郴缁?src/store/index.ts, dynamic import will not move module into another chunk. + +[plugin vite:reporter] +(!) D:/code/鏈哄櫒浜烘櫤鎱ф湇鍔$郴缁?src/store/index.ts is dynamically imported by D:/code/鏈哄櫒浜烘櫤鎱ф湇鍔$郴缁?src/api/request.ts but also statically imported by D:/code/鏈哄櫒浜烘櫤鎱ф湇鍔$郴缁?src/components/Layout.tsx, D:/code/鏈哄櫒浜烘櫤鎱ф湇鍔$郴缁?src/main.tsx, D:/code/鏈哄櫒浜烘櫤鎱ф湇鍔$郴缁?src/pages/Login.tsx, D:/code/鏈哄櫒浜烘櫤鎱ф湇鍔$郴缁?src/p +ages/Profile.tsx, dynamic import will not move module into another chunk. + +computing gzip size... +dist/index.html  2.52 kB 鈹?gzip: 1.13 kB +dist/assets/gecaocar-DMp9NnzT.png  16.23 kB +dist/assets/bgmain-DtapCCMy.jpg  71.91 kB +dist/assets/xunjiancar-CAfmDzzl.png  213.39 kB +dist/assets/carplane-f-ISorrw.png  259.24 kB +dist/assets/logincard-B8hQtFRG.png  355.36 kB +dist/assets/logo-BZW_A_MC.png  1,814.58 kB +dist/assets/bgc2-CfINnBvq.png  3,954.80 kB +dist/assets/inspectCar-C-BgLHu6.png 14,801.70 kB +dist/assets/Home-C67sUCdb.css  1.21 kB 鈹?gzip: 0.55 kB +dist/assets/index-bPDl6cOh.css  70.30 kB 鈹?gzip: 12.91 kB +dist/assets/useForceUpdate-CZFCNyeq.js  0.11 kB 鈹?gzip: 0.13 kB +dist/assets/EyeOutlined-BFyfoix3.js  0.20 kB 鈹?gzip: 0.18 kB +dist/assets/index-Bjna-cdU.js  0.29 kB 鈹?gzip: 0.17 kB +dist/assets/constants-DwgWOJkA.js  0.31 kB 鈹?gzip: 0.28 kB +dist/assets/chevron-right-vVBQ_U9m.js  0.31 kB 鈹?gzip: 0.25 kB +dist/assets/SwapRightOutlined-CaVf5wQU.js  0.32 kB 鈹?gzip: 0.26 kB +dist/assets/index-Be-tFikO.js  0.35 kB 鈹?gzip: 0.19 kB +dist/assets/useBreakpoint-DAxx-Njc.js  0.37 kB 鈹?gzip: 0.27 kB +dist/assets/Empty-xLCAL5dw.js  0.40 kB 鈹?gzip: 0.32 kB +dist/assets/CloseOutlined-JMAuRABM.js  0.41 kB 鈹?gzip: 0.31 kB +dist/assets/wind-1zUaWqEo.js  0.43 kB 鈹?gzip: 0.31 kB +dist/assets/CheckOutlined-D2FgLXFS.js  0.44 kB 鈹?gzip: 0.32 kB +dist/assets/PlusOutlined-D6I49DVX.js  0.44 kB 鈹?gzip: 0.32 kB +dist/assets/EditOutlined-BR5vRp4u.js  0.44 kB 鈹?gzip: 0.32 kB +dist/assets/SearchOutlined-DSqH5eOx.js  0.44 kB 鈹?gzip: 0.32 kB +dist/assets/index-B8qYoa6A.js  0.44 kB 鈹?gzip: 0.22 kB +dist/assets/zap-BbovkZw3.js  0.45 kB 鈹?gzip: 0.32 kB +dist/assets/collapse-BbEVqHco.js  0.45 kB 鈹?gzip: 0.20 kB +dist/assets/EyeOutlined-BRmjDxUJ.js  0.45 kB 鈹?gzip: 0.32 kB +dist/assets/DeleteOutlined-DcPIqNbE.js  0.45 kB 鈹?gzip: 0.32 kB +dist/assets/CalendarOutlined-DmuAJ4dw.js  0.45 kB 鈹?gzip: 0.33 kB +dist/assets/DownloadOutlined-Dk0o-amg.js  0.45 kB 鈹?gzip: 0.33 kB +dist/assets/ClockCircleOutlined-BdM1xofC.js  0.46 kB 鈹?gzip: 0.33 kB +dist/assets/DownloadOutlined-DTidZHln.js  0.46 kB 鈹?gzip: 0.30 kB +dist/assets/SwapOutlined-MHggqN5a.js  0.47 kB 鈹?gzip: 0.34 kB +dist/assets/DeleteOutlined-DFutYCzo.js  0.50 kB 鈹?gzip: 0.34 kB +dist/assets/shield-check-sfL9HgxB.js  0.50 kB 鈹?gzip: 0.36 kB +dist/assets/CalendarOutlined-DKq2sctu.js  0.51 kB 鈹?gzip: 0.31 kB +dist/assets/ClockCircleOutlined-CELcQ7Uv.js  0.53 kB 鈹?gzip: 0.34 kB +dist/assets/EyeOutlined-Bmd706kk.js  0.63 kB 鈹?gzip: 0.39 kB +dist/assets/PauseOutlined-BLt2csZU.js  0.65 kB 鈹?gzip: 0.47 kB +dist/assets/play-1ljA3jPR.js  0.66 kB 鈹?gzip: 0.36 kB +dist/assets/MoreOutlined-B1PG76QS.js  0.67 kB 鈹?gzip: 0.43 kB +dist/assets/SystemSetting-tRZ3rI5Y.js  0.67 kB 鈹?gzip: 0.42 kB +dist/assets/index-QGIuQAVc.js  0.75 kB 鈹?gzip: 0.30 kB +dist/assets/ProtectedRoute-DBQ_RFvv.js  0.77 kB 鈹?gzip: 0.47 kB +dist/assets/ThunderboltOutlined-CM9FK6lI.js  0.81 kB 鈹?gzip: 0.57 kB +dist/assets/RiseOutlined-CG9xbajJ.js  0.83 kB 鈹?gzip: 0.57 kB +dist/assets/cpu-COM_qCei.js  0.83 kB 鈹?gzip: 0.41 kB +dist/assets/trending-up-C335pZ95.js  0.83 kB 鈹?gzip: 0.39 kB +dist/assets/WarningOutlined-Btx5sX6A.js  0.84 kB 鈹?gzip: 0.59 kB +dist/assets/DatabaseOutlined-C5nPN0EL.js  0.84 kB 鈹?gzip: 0.53 kB +dist/assets/InfoCircleOutlined-BRsgui7Y.js  0.88 kB 鈹?gzip: 0.56 kB +dist/assets/MailOutlined-CrBBI-jk.js  0.88 kB 鈹?gzip: 0.59 kB +dist/assets/LockOutlined-CpZjW16Y.js  0.88 kB 鈹?gzip: 0.60 kB +dist/assets/ExclamationCircleOutlined-BTwY9HjG.js  0.88 kB 鈹?gzip: 0.57 kB +dist/assets/index-BZNW0Ac-.js  0.89 kB 鈹?gzip: 0.28 kB +dist/assets/VideoCameraOutlined-BpSekwuQ.js  0.89 kB 鈹?gzip: 0.62 kB +dist/assets/PlayCircleOutlined-C8_VtFd1.js  0.90 kB 鈹?gzip: 0.58 kB +dist/assets/LeftOutlined-mtwdKv5a.js  0.90 kB 鈹?gzip: 0.49 kB +dist/assets/index-B5BnD-LK.js  0.93 kB 鈹?gzip: 0.56 kB +dist/assets/CheckCircleOutlined-CiWPVIDh.js  0.94 kB 鈹?gzip: 0.61 kB +dist/assets/droplets-J52jZ87L.js  0.94 kB 鈹?gzip: 0.50 kB +dist/assets/FileTextOutlined-8_Os79cm.js  0.96 kB 鈹?gzip: 0.62 kB +dist/assets/RobotOutlined-D9B_FJ7c.js  0.97 kB 鈹?gzip: 0.63 kB +dist/assets/BellOutlined-DEw0MDNM.js  0.97 kB 鈹?gzip: 0.65 kB +dist/assets/FormOutlined-B5idtZPb.js  1.00 kB 鈹?gzip: 0.66 kB +dist/assets/BarChartOutlined-D19D9dh2.js  1.01 kB 鈹?gzip: 0.53 kB +dist/assets/BgColorsOutlined-D4zNRQ_S.js  1.01 kB 鈹?gzip: 0.66 kB +dist/assets/AppstoreOutlined-vwQa2ti0.js  1.06 kB 鈹?gzip: 0.52 kB +dist/assets/ExperimentOutlined-C4X5fx5X.js  1.06 kB 鈹?gzip: 0.72 kB +dist/assets/BranchesOutlined-BsXN7E28.js  1.07 kB 鈹?gzip: 0.65 kB +dist/assets/index-B7QMvlEx.js  1.10 kB 鈹?gzip: 0.59 kB +dist/assets/ExpandOutlined-Wqi8y5jM.js  1.12 kB 鈹?gzip: 0.59 kB +dist/assets/CloudOutlined-bffXYW10.js  1.13 kB 鈹?gzip: 0.74 kB +dist/assets/UserOutlined-C7S2oBX2.js  1.22 kB 鈹?gzip: 0.76 kB +dist/assets/ZoomOutOutlined-CdPjzMfa.js  1.22 kB 鈹?gzip: 0.42 kB +dist/assets/ReloadOutlined-Xhzi5rUd.js  1.23 kB 鈹?gzip: 0.77 kB +dist/assets/AlertOutlined-BSdXkZNw.js  1.24 kB 鈹?gzip: 0.73 kB +dist/assets/AimOutlined-BQ_60xaP.js  1.25 kB 鈹?gzip: 0.71 kB +dist/assets/alarmApi-D98kS4sF.js  1.25 kB 鈹?gzip: 0.35 kB +dist/assets/SyncOutlined-D5St2s8G.js  1.27 kB 鈹?gzip: 0.81 kB +dist/assets/MoneyCollectOutlined-BEnuS9NY.js  1.30 kB 鈹?gzip: 0.79 kB +dist/assets/FullscreenOutlined-Bd0pqIlF.js  1.34 kB 鈹?gzip: 0.77 kB +dist/assets/SafetyCertificateOutlined-DnZNNQOF.js  1.41 kB 鈹?gzip: 0.76 kB +dist/assets/SwapOutlined-Dmzzor8a.js  1.42 kB 鈹?gzip: 0.65 kB +dist/assets/ZoomOutOutlined-DAOfVl6t.js  1.47 kB 鈹?gzip: 0.67 kB +dist/assets/satellite-D5SYgbBW.js  1.47 kB 鈹?gzip: 0.54 kB +dist/assets/RocketOutlined-DvS5QcPf.js  1.49 kB 鈹?gzip: 0.93 kB +dist/assets/EnvironmentOutlined-DmDILpSG.js  1.49 kB 鈹?gzip: 0.91 kB +dist/assets/useBubbleLock-BcDDtpST.js  1.54 kB 鈹?gzip: 0.75 kB +dist/assets/index-CALtcbsS.js  1.61 kB 鈹?gzip: 0.85 kB +dist/assets/ApiOutlined-CzQyCItv.js  1.61 kB 鈹?gzip: 0.87 kB +dist/assets/SunOutlined-4fVeMoLM.js  1.75 kB 鈹?gzip: 0.90 kB +dist/assets/DashboardOutlined-By3UzQBB.js  1.83 kB 鈹?gzip: 0.93 kB +dist/assets/createLucideIcon-I8N4V_Qv.js  1.86 kB 鈹?gzip: 0.80 kB +dist/assets/CarOutlined-Dl55nQ-v.js  2.00 kB 鈹?gzip: 0.98 kB +dist/assets/index-Bki12rLk.js  2.04 kB 鈹?gzip: 1.00 kB +dist/assets/systemSetting-BrHh5w13.js  2.11 kB 鈹?gzip: 0.45 kB +dist/assets/PlayCircleFilled-BBXiNPP8.js  2.14 kB 鈹?gzip: 1.04 kB +dist/assets/LinkOutlined-DvFl02q6.js  2.19 kB 鈹?gzip: 0.82 kB +dist/assets/index-CFB0_Wn2.js  2.19 kB 鈹?gzip: 1.14 kB +dist/assets/SettingOutlined-DeJS8h5d.js  2.35 kB 鈹?gzip: 1.21 kB +dist/assets/VideoPlayer-CBopx0N2.js  2.39 kB 鈹?gzip: 1.33 kB +dist/assets/PictureTwoTone-BaO8R2Hf.js  2.42 kB 鈹?gzip: 1.04 kB +dist/assets/index-Dzwhnzv1.js  2.42 kB 鈹?gzip: 1.16 kB +dist/assets/SaveOutlined-CPLKsg-u.js  3.28 kB 鈹?gzip: 1.40 kB +dist/assets/device-psUGD0yB.js  3.38 kB 鈹?gzip: 0.76 kB +dist/assets/index-C8BzGSw1.js  3.61 kB 鈹?gzip: 1.27 kB +dist/assets/row-CWgAqdVq.js  3.74 kB 鈹?gzip: 1.64 kB +dist/assets/MonitorOutlined-BblwvURO.js  3.85 kB 鈹?gzip: 1.28 kB +dist/assets/OnlineUser-DP0qCIhg.js  3.87 kB 鈹?gzip: 1.82 kB +dist/assets/index-BU7NlCGd.js  4.14 kB 鈹?gzip: 1.74 kB +dist/assets/MenuUnfoldOutlined-D7wIQeV0.js  4.16 kB 鈹?gzip: 1.30 kB +dist/assets/ScanOutlined-BErT-8VV.js  4.19 kB 鈹?gzip: 1.38 kB +dist/assets/index-D-WWTY9M.js  4.21 kB 鈹?gzip: 1.58 kB +dist/assets/LoadingOutlined-CSGMXG1Q.js  4.25 kB 鈹?gzip: 1.83 kB +dist/assets/index-CwWg_1c5.js  4.38 kB 鈹?gzip: 1.76 kB +dist/assets/Organization-DaUilJNB.js  4.43 kB 鈹?gzip: 1.95 kB +dist/assets/index-DLB_37uE.js  4.58 kB 鈹?gzip: 1.91 kB +dist/assets/VideoCameraAddOutlined-DfZ_JO9-.js  4.79 kB 鈹?gzip: 1.68 kB +dist/assets/WomanOutlined-DfQHI4i_.js  4.82 kB 鈹?gzip: 1.76 kB +dist/assets/LineChartOutlined-DoICXm12.js  5.07 kB 鈹?gzip: 1.82 kB +dist/assets/Roles-BcoDNXzy.js  5.16 kB 鈹?gzip: 2.28 kB +dist/assets/index-DlknX2AJ.js  5.44 kB 鈹?gzip: 2.24 kB +dist/assets/Users-Cc87fC1a.js  5.46 kB 鈹?gzip: 2.17 kB +dist/assets/index-DBrV9klW.js  5.57 kB 鈹?gzip: 2.20 kB +dist/assets/index-BIHkEVGV.js  5.83 kB 鈹?gzip: 2.63 kB +dist/assets/Sider-S9XGzyBR.js  6.64 kB 鈹?gzip: 2.85 kB +dist/assets/Input-C5V4O2--.js  6.73 kB 鈹?gzip: 2.71 kB +dist/assets/LogManagement-DMoKnN3a.js  6.80 kB 鈹?gzip: 3.23 kB +dist/assets/dayjs.min-BQmzeOJK.js  7.15 kB 鈹?gzip: 3.11 kB +dist/assets/Timeline-DTl788NK.js  7.47 kB 鈹?gzip: 2.32 kB +dist/assets/Profile-D6l6crbd.js  7.59 kB 鈹?gzip: 2.67 kB +dist/assets/index-Bxnk55C6.js  7.98 kB 鈹?gzip: 2.71 kB +dist/assets/GlobalOutlined-BBf_4gfp.js  8.13 kB 鈹?gzip: 2.73 kB +dist/assets/StationManage-DqEWUwhR.js  9.55 kB 鈹?gzip: 3.29 kB +dist/assets/CaretUpOutlined-CeF_o8iU.js  9.72 kB 鈹?gzip: 3.73 kB +dist/assets/index-7OmqMvBS.js  9.85 kB 鈹?gzip: 4.12 kB +dist/assets/index-CoZjM-Ur.js  10.86 kB 鈹?gzip: 3.67 kB +dist/assets/index-BcHyRtCu.js  13.09 kB 鈹?gzip: 4.32 kB +dist/assets/RealTimeMonitor-D3QaTkAC.js  13.35 kB 鈹?gzip: 3.86 kB +dist/assets/Downloads-DcgcCi6l.js  14.39 kB 鈹?gzip: 5.34 kB +dist/assets/Layout-Bd_POYYm.js  14.43 kB 鈹?gzip: 5.93 kB +dist/assets/UserPage-32JpRX2A.js  14.58 kB 鈹?gzip: 5.10 kB +dist/assets/mowerAllView-I1S0UCff.js  15.31 kB 鈹?gzip: 5.14 kB +dist/assets/progress-BRDZKBDI.js  16.32 kB 鈹?gzip: 5.97 kB +dist/assets/Video-DCzOHWv-.js  17.54 kB 鈹?gzip: 6.37 kB +dist/assets/VideoMonitorPage-BhzNbDao.js  19.23 kB 鈹?gzip: 5.70 kB +dist/assets/Home-Bn7xrUeS.js  19.49 kB 鈹?gzip: 5.82 kB +dist/assets/ReportCenter-BBu6qFzX.js  19.98 kB 鈹?gzip: 5.52 kB +dist/assets/AIAnalysis-6Etwoj3Z.js  20.65 kB 鈹?gzip: 5.97 kB +dist/assets/SystemMaintain-Cd07s562.js  21.22 kB 鈹?gzip: 6.42 kB +dist/assets/Agri-CAyj5gpp.js  23.35 kB 鈹?gzip: 6.70 kB +dist/assets/CleanOptimization-m28ON6IA.js  23.72 kB 鈹?gzip: 6.78 kB +dist/assets/BasicSettings-mBDMHnai.js  24.03 kB 鈹?gzip: 6.94 kB +dist/assets/Pagination-E56Qk7uV.js  24.07 kB 鈹?gzip: 7.27 kB +dist/assets/index-D2zgn0VX.js  24.29 kB 鈹?gzip: 6.84 kB +dist/assets/index-CIQZPZYn.js  24.61 kB 鈹?gzip: 8.41 kB +dist/assets/DeviceAccessPage-DkChs1SW.js  27.31 kB 鈹?gzip: 7.77 kB +dist/assets/DeviceStatusPage-DeTc4zz3.js  27.77 kB 鈹?gzip: 8.81 kB +dist/assets/AntdIcon-0lBFMey5.js  28.67 kB 鈹?gzip: 10.61 kB +dist/assets/index-3QLgGeSa.js  30.34 kB 鈹?gzip: 10.81 kB +dist/assets/index-4Tny0eKH.js  31.74 kB 鈹?gzip: 11.04 kB +dist/assets/DeviceOverviewPage-OFF9ez_H.js  34.95 kB 鈹?gzip: 9.58 kB +dist/assets/Map-B9M4yO_P.js  35.52 kB 鈹?gzip: 16.50 kB +dist/assets/DeviceParamModal-aOMZwSFn.js  36.02 kB 鈹?gzip: 12.66 kB +dist/assets/Alerts-DSpopPLD.js  43.22 kB 鈹?gzip: 13.57 kB +dist/assets/WayLinePage-Cu3Rj_Of.js  47.81 kB 鈹?gzip: 12.76 kB +dist/assets/RobotTaskPage-W5Q2YiXq.js  50.58 kB 鈹?gzip: 15.72 kB +dist/assets/index-DtVs1TSu.js  53.48 kB 鈹?gzip: 17.46 kB +dist/assets/index-DOfHuV9M.js  55.58 kB 鈹?gzip: 16.79 kB +dist/assets/index-DdSZJIQg.js  85.35 kB 鈹?gzip: 28.38 kB +dist/assets/index-8P5uuj0T.js  104.37 kB 鈹?gzip: 33.62 kB +dist/assets/Table-DEFhGiKk.js  105.22 kB 鈹?gzip: 35.08 kB +dist/assets/index-C4N9F59W.js  119.58 kB 鈹?gzip: 40.54 kB +dist/assets/Login-B_ks4Hrx.js  127.74 kB 鈹?gzip: 42.25 kB +dist/assets/VideoManagement-DTii0Wl_.js  162.67 kB 鈹?gzip: 41.60 kB +dist/assets/useMqtt-CalKBDup.js  372.77 kB 鈹?gzip: 112.37 kB +dist/assets/recharts-oahKx968.js  376.93 kB 鈹?gzip: 108.14 kB +dist/assets/index-_6GufRdM.js  651.35 kB 鈹?gzip: 215.64 kB +dist/assets/DeviceManagement-CdpxXm_d.js  722.93 kB 鈹?gzip: 158.92 kB +dist/assets/MenuList-tLwkyiAS.js  857.15 kB 鈹?gzip: 165.02 kB +dist/assets/WorkOrder-DfwdBKQc.js  1,507.81 kB 鈹?gzip: 445.47 kB +dist/assets/DroneVideoPlayer-BnJcr8Dl.js  2,529.14 kB 鈹?gzip: 708.00 kB + +(!) Some chunks are larger than 1000 kB after minification. Consider: +- Using dynamic import() to code-split the application +- Use build.rollupOptions.output.manualChunks to improve chunking: https://rollupjs.org/configuration-options/#output-manualchunks +- Adjust chunk size limit for this warning via build.chunkSizeWarningLimit. +[vite-plugin-static-copy] Copied 1 items. +鉁?built in 1m 39s + diff --git a/package-lock.json b/package-lock.json index 13e9603..e1ed8b8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,6 +24,7 @@ "dotenv": "^17.2.3", "echarts": "^6.0.0", "express": "^4.21.2", + "flv.js": "^1.6.2", "js-cookie": "^3.0.5", "lodash": "^4.18.1", "lucide-react": "^0.546.0", @@ -4083,6 +4084,12 @@ "benchmarks" ] }, + "node_modules/es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", + "license": "MIT" + }, "node_modules/esbuild": { "version": "0.27.7", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz", @@ -4372,6 +4379,16 @@ "node": ">=6" } }, + "node_modules/flv.js": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/flv.js/-/flv.js-1.6.2.tgz", + "integrity": "sha512-xre4gUbX1MPtgQRKj2pxJENp/RnaHaxYvy3YToVVCrSmAWUu85b9mug6pTXF6zakUjNP2lFWZ1rkSX7gxhB/2A==", + "license": "Apache-2.0", + "dependencies": { + "es6-promise": "^4.2.8", + "webworkify-webpack": "^2.1.5" + } + }, "node_modules/follow-redirects": { "version": "1.16.0", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", @@ -8165,6 +8182,12 @@ "npm": ">=3.10.0" } }, + "node_modules/webworkify-webpack": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/webworkify-webpack/-/webworkify-webpack-2.1.5.tgz", + "integrity": "sha512-2akF8FIyUvbiBBdD+RoHpoTbHMQF2HwjcxfDvgztAX5YwbZNyrtfUMgvfgFVsgDhDPVTlkbb5vyasqDHfIDPQw==", + "license": "MIT" + }, "node_modules/which-module": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", diff --git a/package.json b/package.json index f38d33f..125986a 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "dotenv": "^17.2.3", "echarts": "^6.0.0", "express": "^4.21.2", + "flv.js": "^1.6.2", "js-cookie": "^3.0.5", "lodash": "^4.18.1", "lucide-react": "^0.546.0", diff --git a/src/components/SystemSetting/VideoManagement.tsx b/src/components/SystemSetting/VideoManagement.tsx index eee1167..28dc3ae 100644 --- a/src/components/SystemSetting/VideoManagement.tsx +++ b/src/components/SystemSetting/VideoManagement.tsx @@ -1,104 +1,253 @@ -import React, { useState } from 'react'; +import React, { useState, useEffect, useRef } from 'react'; import { useNavigate } from 'react-router-dom'; import { - Card as AntdCard, Tag, Button, Space, Typography, Row, Col, message + Card, Tag, Button, Space, Typography, Row, Col, Select, Table, Modal, message, Empty, Spin } from 'antd'; import { - VideoCameraOutlined, PlayCircleOutlined, HistoryOutlined, SettingOutlined, - CameraOutlined, EyeOutlined + VideoCameraOutlined, DownloadOutlined, PlayCircleOutlined, + FolderOutlined, ReloadOutlined, EyeOutlined, DatabaseOutlined } from '@ant-design/icons'; +import axios from 'axios'; +import flvjs from 'flv.js'; const { Title, Text } = Typography; // ====================== // 视频管理(仅 admin 可见) -// 说明:当前为前端展示页,数据使用本地 mock 视频通道。 -// 接入真实视频时,「实时预览」可跳转至监控页 /monitor(VideoMonitorPage), -// 或对接 WebRTC / 流媒体服务获取实时画面与回放地址。 +// 真实数据对接 nodevideo(端口 9528,SRS 录制文件服务): +// POST /list body: { deviceId?, year?, month?, day? } +// 不传参 → 所有通道(deviceId);传 deviceId → 年份目录;逐级下钻 → 当天视频文件 +// 返回 { code, path, directories:[], files:[{ fileName, size, sizeFormatted }] } +// GET /video/download?deviceId=&year=&month=&day=&fileName= +// 流式返回录制视频(SRS 多为 .flv,用 flv.js 播放) +// 说明:本机开发直连 http://localhost:9528;若部署到其它主机,请改为反向代理/相对路径。 // ====================== -const MOCK_CHANNELS = [ - { id: 'CAM-01', name: '1区组件巡检摄像头', device: '巡检机器人-01', status: 'online', location: 'A排 1-12 组件', lastUpdate: '2026-08-10 12:58' }, - { id: 'CAM-02', name: '升压站全景摄像头', device: '固定球机', status: 'online', location: '升压站', lastUpdate: '2026-08-10 12:59' }, - { id: 'CAM-03', name: '无人机航拍通道', device: '无人机-01', status: 'offline', location: '全场', lastUpdate: '2026-08-09 18:20' }, - { id: 'CAM-04', name: '汇流箱热成像', device: '巡检机器人-02', status: 'online', location: 'B排汇流箱', lastUpdate: '2026-08-10 13:01' }, - { id: 'CAM-05', name: '逆变器舱监控', device: '固定枪机', status: 'online', location: '逆变器室', lastUpdate: '2026-08-10 13:00' }, - { id: 'CAM-06', name: '组件热斑巡检通道', device: '无人机-02', status: 'offline', location: 'C排组件', lastUpdate: '2026-08-09 17:45' }, -]; +const NODEVIDEO_BASE = 'http://1.95.137.212:30003'; + +const fetchList = async (body: Record = {}) => { + const res = await axios.post(`${NODEVIDEO_BASE}/list`, body); + return res.data as { code: number; path: string; directories: string[]; files: { fileName: string; size: number; sizeFormatted: string }[]; error?: string }; +}; + +const buildDownloadUrl = (p: { deviceId: string; year: string; month: string; day: string; fileName: string }) => + `${NODEVIDEO_BASE}/video/download?deviceId=${encodeURIComponent(p.deviceId)}&year=${p.year}&month=${p.month}&day=${p.day}&fileName=${encodeURIComponent(p.fileName)}`; + +const isFlv = (name: string) => name.toLowerCase().endsWith('.flv'); const VideoManagement = () => { const navigate = useNavigate(); - const [channels] = useState(MOCK_CHANNELS); + const [channels, setChannels] = useState([]); + const [channel, setChannel] = useState(); + const [years, setYears] = useState([]); + const [year, setYear] = useState(); + const [months, setMonths] = useState([]); + const [month, setMonth] = useState(); + const [days, setDays] = useState([]); + const [day, setDay] = useState(); + const [files, setFiles] = useState<{ fileName: string; size: number; sizeFormatted: string }[]>([]); + const [loading, setLoading] = useState(false); + const [preview, setPreview] = useState<{ url: string; fileName: string } | null>(null); + const videoRef = useRef(null); + const flvPlayerRef = useRef(null); - const onlineCount = channels.filter((c) => c.status === 'online').length; - - const handlePreview = (ch: any) => { - if (ch.status !== 'online') { - message.warning(`${ch.name} 当前离线,无法预览`); - return; + // 1. 加载通道列表(deviceId) + const loadChannels = async () => { + setLoading(true); + try { + const data = await fetchList({}); + if (data.code === 200) { + setChannels(data.directories || []); + } else { + setChannels([]); + message.warning(data.error || '读取通道失败'); + } + } catch (e) { + setChannels([]); + message.error('无法连接 nodevideo 服务(9528)'); + } finally { + setLoading(false); } - // 跳转至实时监控页,可携带通道信息 - navigate('/monitor', { state: { channel: ch.id, name: ch.name } }); }; + useEffect(() => { loadChannels(); }, []); + + // 2. 选通道 → 加载年份 + const onChannelChange = async (val: string) => { + setChannel(val); + setYear(undefined); setYears([]); + setMonth(undefined); setMonths([]); + setDay(undefined); setDays([]); + setFiles([]); + if (!val) return; + setLoading(true); + try { + const data = await fetchList({ deviceId: val }); + setYears(data.code === 200 ? (data.directories || []) : []); + } catch { setYears([]); } + finally { setLoading(false); } + }; + + // 3. 选年份 → 加载月份 + const onYearChange = async (val: string) => { + setYear(val); + setMonth(undefined); setMonths([]); + setDay(undefined); setDays([]); + setFiles([]); + if (!val || !channel) return; + setLoading(true); + try { + const data = await fetchList({ deviceId: channel, year: val }); + setMonths(data.code === 200 ? (data.directories || []) : []); + } catch { setMonths([]); } + finally { setLoading(false); } + }; + + // 4. 选月份 → 加载日期 + const onMonthChange = async (val: string) => { + setMonth(val); + setDay(undefined); setDays([]); + setFiles([]); + if (!val || !channel || !year) return; + setLoading(true); + try { + const data = await fetchList({ deviceId: channel, year, month: val }); + setDays(data.code === 200 ? (data.directories || []) : []); + } catch { setDays([]); } + finally { setLoading(false); } + }; + + // 5. 选日期 → 加载当天视频文件 + const onDayChange = async (val: string) => { + setDay(val); + setFiles([]); + if (!val || !channel || !year || !month) return; + setLoading(true); + try { + const data = await fetchList({ deviceId: channel, year, month, day: val }); + setFiles(data.code === 200 ? (data.files || []) : []); + if (data.code !== 200) message.warning(data.error || '读取文件失败'); + } catch { setFiles([]); message.error('读取文件失败'); } + finally { setLoading(false); } + }; + + // 预览:flv 用 flv.js,其余用原生 video + useEffect(() => { + if (!preview) return; + const video = videoRef.current; + if (!video) return; + if (isFlv(preview.fileName) && flvjs.isSupported()) { + const player = flvjs.createPlayer({ type: 'flv', url: preview.url, isLive: false }); + player.attachMediaElement(video); + player.load(); + player.play().catch(() => { /* 自动播放策略可能拦截,用户手动点击 */ }); + flvPlayerRef.current = player; + } + return () => { + flvPlayerRef.current?.destroy(); + flvPlayerRef.current = null; + }; + }, [preview]); + + const openPreview = (file: { fileName: string }) => { + if (!channel || !year || !month || !day) return; + setPreview({ + url: buildDownloadUrl({ deviceId: channel, year, month, day, fileName: file.fileName }), + fileName: file.fileName, + }); + }; + + const columns = [ + { title: '文件名', dataIndex: 'fileName', key: 'fileName', ellipsis: true }, + { title: '大小', dataIndex: 'sizeFormatted', key: 'sizeFormatted', width: 120 }, + { + title: '操作', key: 'action', width: 160, + render: (_: any, rec: { fileName: string }) => ( + + + + + + + ), + }, + ]; + return (
视频管理 - 视频通道总览与预览管理,仅超级管理员可查看 · 在线 {onlineCount}/{channels.length} + + 录像通道与回放管理(对接 nodevideo :9528) · 共 {channels.length} 个通道 +
- - {channels.map((ch) => { - const online = ch.status === 'online'; - return ( - - - {/* 视频快照占位 */} -
- -
- {online ? '● 在线' : '○ 离线'} -
-
{ch.id}
-
+ + + + 通道 + ({ value: y, label: y }))} /> + + + 月 + ({ value: d, label: d }))} /> + + + + + + -
{ch.name}
- - - {ch.device} - {ch.location} - + + {loading ? ( +
+ ) : !channel ? ( + + ) : !day ? ( + + ) : files.length === 0 ? ( + + ) : ( + `共 ${t} 个文件` }} + /> + )} + -
- - -
- - - ); - })} - + setPreview(null)} width={880} destroyOnClose + > + {preview && isFlv(preview.fileName) ? ( + ); };