地图资源 全部换成 npm的资源 加快了加载速度 ,地图加了一个定位到机器的按钮,手动定位到机器 ,实时显示工作中空闲状态 机器加入显示设备类型 机器人任务界面 保存定时任务 bug修复

This commit is contained in:
mmc
2026-10-29 16:39:25 +08:00
parent 91c01e249f
commit 04f74277bf
9 changed files with 392 additions and 568 deletions

View File

@@ -12,7 +12,7 @@
<link rel="dns-prefetch" href="https://unpkg.com">
<link rel="dns-prefetch" href="https://cdn.jsdelivr.net">
<link rel="dns-prefetch" href="https://lf-unpkg.volccdn.com">
<link rel="stylesheet" href="/css/widgets.css" media="print" onload="this.media='all'">
<!--<link rel="stylesheet" href="/css/widgets.css" media="print" onload="this.media='all'">-->
<!-- CSS 异步加载,不阻塞页面渲染 -->
@@ -23,8 +23,11 @@
- 不阻塞 HTML 解析与首屏渲染(解决白屏)
- 保持脚本执行顺序(cesium/hls/veplayer 先于 main.tsx 执行)
-->
<script>
window.CESIUM_BASE_URL = '/cesium/';
</script>
<script defer src="/js/jswebrtc.min.js"></script>
<script defer src="/js/cesium.js"></script>
<!--<script defer src="/js/cesium.js"></script>-->
<script defer src="/js/hls.js"></script>
<script defer src="/js/veplayer.js"></script>
@@ -78,27 +81,27 @@
<script type="module" src="/src/main.tsx"></script>
<script>
// 等页面加载完成后,再异步加载地图/视频库,不阻塞首屏
window.addEventListener('DOMContentLoaded', () => {
const loadScript = (src) => {
return new Promise((resolve) => {
const s = document.createElement('script');
s.src = src;
s.async = true;
s.onload = resolve;
document.body.appendChild(s);
});
};
//window.addEventListener('DOMContentLoaded', () => {
// const loadScript = (src) => {
// return new Promise((resolve) => {
// const s = document.createElement('script');
// s.src = src;
// s.async = true;
// s.onload = resolve;
// document.body.appendChild(s);
// });
// };
// 按顺序加载
Promise.resolve()
//.then(() => loadScript('/js/jswebrtc.min.js'))
//.then(() => loadScript('/js/jswebrtcnew.js'))
//.then(() => loadScript('https://cdn.jsdelivr.net/npm/cesium@latest/Build/Cesium/Cesium.js'))
.then(() => {
console.log('✅ 所有地图/视频SDK加载完成');
window.CESIUM_BASE_URL = "https://cdnjs.cloudflare.com/ajax/libs/cesium/1.114.0/";
});
});
// // 按顺序加载
// Promise.resolve()
// //.then(() => loadScript('/js/jswebrtc.min.js'))
// //.then(() => loadScript('/js/jswebrtcnew.js'))
// //.then(() => loadScript('https://cdn.jsdelivr.net/npm/cesium@latest/Build/Cesium/Cesium.js'))
// .then(() => {
// console.log('✅ 所有地图/视频SDK加载完成');
// //window.CESIUM_BASE_URL = "https://cdnjs.cloudflare.com/ajax/libs/cesium/1.114.0/";
// });
//});
</script>
</body>

File diff suppressed because it is too large Load Diff

View File

@@ -531,7 +531,7 @@ export default function DeviceOverviewPage() {
...d,
id: d.deviceId || index,
name: d.deviceAlias || d.deviceName || d.callsign || '未知设备',
type: d.productName || t('constants.uav'),
type: d.deviceType || "割草机",
status: d.onlineStatus === 1 ? t('devices.online') : t('devices.offline'),
mode: d.feStatus == 1 ? '作业中' : d.feStatus == 2 ? t('devices.idle') : d.mode_code == 0 ? t('devices.idle') : d.mode_code == 1 ? '现场调试' : d.mode_code == 2 ? '远程调试' : d.mode_code == 3 ? '固件升级中' : '作业中',
capacity_percent: d.capacity_percent || 100,
@@ -823,6 +823,12 @@ export default function DeviceOverviewPage() {
<span style={{ fontSize: 12 }}>v{selectedDevice.firmwareVersion}</span>
</div>
)}
{selectedDevice.deviceType && (
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<span style={{ color: '#666', fontSize: 12 }}>{t('devices.deviceType')}</span>
<span style={{ fontSize: 12 }}>{selectedDevice.deviceType}</span>
</div>
)}
{(selectedDevice.productName?.includes(t('constants.uav')) || selectedDevice.device_sn) && (
<>
<div style={{ display: 'flex', justifyContent: 'space-between' }}>

View File

@@ -2174,138 +2174,6 @@ export default function DeviceStatusPage() {
{/* 页面顶部按钮区域 */}
{/*{!isUAV && (
<div
style={{
marginBottom: 8,
padding: '4px 0px',
background: '#f5f7fa',
borderRadius: 8,
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
gap: 12,
}}
>
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
<Text strong>{t('devices.pathPlanning')}:</Text>
<Text type="secondary" style={{ color: '#8c8c8c' }}>{t('devices.markedPointsCount', { count: markedPoints?.length })}</Text>
</div>
<Space size="middle">
<Space>
<span>{t('devices.workMode')}</span>
<Switch
size="small"
checked={isLoopMode}
onChange={handleChange}
/>
<span>{isLoopMode ? t('devices.bowMode') : t('devices.abMode')}</span>
</Space>
<Button
type="primary"
onClick={handleMarkPoint}
disabled={!realtimePosition}
>
{t('devices.markPoint')}
</Button>
<Button
type="default"
onClick={handleUndoMark}
disabled={markedPoints?.length === 0}
>
{t('devices.undoMark')}
</Button>
<Button
type="default"
onClick={handleClearPoints}
>
{t('devices.clearMarks')}
</Button>
{/*<Button
type="primary"
ghost
onClick={handleComplete}
disabled={markedPoints?.length < 2}
>
{t('devices.complete')}
</Button>*/}
{/*<Button
type="primary"
onClick={handleOpenSaveModal}
//disabled={!completeFlag}
>
{t('common.save')}
</Button>
</Space>
</div>
)}}*/}
<div
@@ -2390,7 +2258,7 @@ export default function DeviceStatusPage() {
<Tag color={isUAV ? 'cyan' : 'blue'}>
{isUAV ? t('constants.uav') : t('devices.robot')}
{isUAV ? t('constants.uav') : device?.deviceType ? device?.deviceType : t('devices.robot')}
</Tag>

View File

@@ -144,10 +144,14 @@ export default function MapEditorPage() {
};
loadDevices();
}, [stationId]);
useEffect(() => {
console.log("siteMapInfoId state:", siteMapInfoId);
}, [siteMapInfoId]);
const getSiteMapInfoFn = () => {
getSiteMapInfo({ siteId: stationId }).then((res: any) => {
if (res?.code === 200 && res.data) {
setSiteMapInfoId(res.data.id ?? null);
console.log(res.data.id, "res.data.id")
setReturnPointConfigList(res?.data?.restPoints || []);
// 同时加载已保存的障碍物点(tempObstaclePoints),方便编辑
const savedObstacles = (res?.data?.tempObstaclePoints || []).map((op: any) => ({
@@ -161,12 +165,16 @@ export default function MapEditorPage() {
} else {
setSiteMapInfoId(null);
console.log("res.data.id111")
setReturnPointConfigList([]);
setObstaclePointConfigList([]);
}
}).catch(() => {
setSiteMapInfoId(null);
console.log("res.data.id112221")
setReturnPointConfigList([]);
setObstaclePointConfigList([]);
@@ -737,7 +745,8 @@ export default function MapEditorPage() {
const handleObstacleRadiusChange = async (
index: number,
radius: number
radius: number,
siteMapInfoId: number | null
) => {
console.log("nextList")
@@ -749,6 +758,7 @@ export default function MapEditorPage() {
? { ...item, radius: roundedRadius }
: item
);
console.log(nextList, "333", siteMapInfoId, "siteMapInfoIdnextList")
const payload = {
id: siteMapInfoId,
tempObstaclePoints: nextList?.map((item) => ({
@@ -1097,6 +1107,8 @@ export default function MapEditorPage() {
onObstacleRadiusChange={handleObstacleRadiusChange}
siteMapInfoId={siteMapInfoId}
/>

View File

@@ -1400,23 +1400,21 @@ export default function RobotTaskPage() {
rules = { type: 'MONTH', dayOfMonth: scheduleForm.dayOfMonth, dayTime: scheduleForm.dayTime };
}
let success = true;
for (const sn of dispatchRobotSns) {
for (const route of routes) {
const finalData = {
deviceId: sn,
orgId: currentStation?.orgId,
planName: scheduleForm.planName,
routeId: route.id,
siteId: stationId,
deviceTaskPlanRules: rules,
startTime: scheduleForm.excuteDayStartTime,
finishTime: scheduleForm.excuteDayEndTime,
};
const res = await saveDeviceTask(finalData);
if (res.code !== 200) {
success = false;
utils.message.error(res.msg || t('devices.createFailed'));
}
for (const route of routes) {
const finalData = {
deviceId: dispatchRobotSns,
orgId: currentStation?.orgId,
planName: scheduleForm.planName,
routeId: route.id,
siteId: stationId,
deviceTaskPlanRules: rules,
startTime: scheduleForm.excuteDayStartTime,
finishTime: scheduleForm.excuteDayEndTime,
};
const res = await saveDeviceTask(finalData);
if (res.code !== 200) {
success = false;
utils.message.error(res.msg || t('devices.createFailed'));
}
}
if (success) {

View File

@@ -162,6 +162,14 @@ export default class DeviceController {
if (msg?.type == 'device_status_changed') {
this.deviceStatusChangedMsg?.(msg);
}
if (msg?.type == 'route_post') {
console.log('route_post');
this.onRoutePost?.(msg);
}
};
ws.onerror = () => {
@@ -508,7 +516,7 @@ export default class DeviceController {
break;
case 'route_post':
console.log('route post:', msg);
console.log('route_post:', msg);
if (msg.deviceId) {
this.onRoutePost?.(msg);
}

View File

@@ -2701,7 +2701,7 @@ const zh = {
addRule: '新增规则',
editRule: '编辑规则',
viewRule: '查看规则',
operator: '比较运算符',
//operator: '比较运算符',
invalidJson: '动作参数 JSON 格式不正确',
confirmDeleteRule: '确定删除规则「{{name}}」吗?',
flvPlaybackError: 'FLV 播放出错',

View File

@@ -1,3 +1,5 @@
 // CESIUM_BASE_URL 由 vite-plugin-cesium 自动注入(值为 base + '/cesium/',小写带尾斜杠)
// 手动覆写会与 viteStaticCopy 的小写 cesium/ 目标路径冲突,因此注释掉
import tailwindcss from '@tailwindcss/vite';
import react from '@vitejs/plugin-react';
import path, { resolve } from 'path';
@@ -27,7 +29,22 @@ export default defineConfig(({ mode }) => {
{
src: "node_modules/cesium/Build/Cesium",
dest: ""
}
}, {
src: 'node_modules/cesium/Build/Cesium/Workers/**',
dest: 'cesium/Workers',
},
{
src: 'node_modules/cesium/Build/Cesium/ThirdParty/**',
dest: 'cesium/ThirdParty',
},
{
src: 'node_modules/cesium/Build/Cesium/Assets/**',
dest: 'cesium/Assets',
},
{
src: 'node_modules/cesium/Build/Cesium/Widgets/**',
dest: 'cesium/Widgets',
},
]
})
@@ -50,71 +67,13 @@ export default defineConfig(({ mode }) => {
rollupOptions: {
output: {
// ---- 手动分包策略 ----
// 将第三方库按类型拆分,利于浏览器并行加载与长期缓存
//manualChunks(id) {
// if (!id.includes('node_modules')) return;
// // 1. React 生态
// if (
// id.includes('node_modules/react') ||
// id.includes('node_modules/react-dom') ||
// id.includes('node_modules/react-router') ||
// id.includes('node_modules/react-redux') ||
// id.includes('node_modules/@reduxjs') ||
// id.includes('node_modules/scheduler')
// ) {
// return 'react-vendor';
// }
// // 2. Ant Design 组件库
// if (
// id.includes('node_modules/antd') ||
// id.includes('node_modules/@ant-design') ||
// id.includes('node_modules/@rc-component') ||
// id.includes('node_modules/rc-')
// ) {
// return 'antd-vendor';
// }
// // 3. 图表库(echarts / recharts 体积较大)
// if (
// id.includes('node_modules/echarts') ||
// id.includes('node_modules/recharts') ||
// id.includes('node_modules/zrender')
// ) {
// return 'charts-vendor';
// }
// // 4. 实时音视频 SDK
// if (
// id.includes('node_modules/agora-rtc-sdk-ng') ||
// id.includes('node_modules/@volcengine/rtc')
// ) {
// return 'rtc-vendor';
// }
// // 5. 仅在特定页面使用的重库,单独拆分按需加载(不进首屏 vendor)
// if (id.includes('node_modules/mqtt')) return 'mqtt-vendor';
// if (id.includes('node_modules/socket.io-client')) return 'socket-vendor';
// if (id.includes('node_modules/docx')) return 'docx-vendor';
// if (id.includes('node_modules/qrcode')) return 'qrcode-vendor';
// if (id.includes('node_modules/country-state-city')) return 'csc-vendor';
// if (id.includes('node_modules/flv.js')) return 'flv-vendor';
// // 6. 其他 node_modules(首屏通用依赖:axios、i18next、lodash 等)
// return 'vendor';
//},
},
},
},
define: {
// Cesium 路径注入
CESIUM_BASE_URL: JSON.stringify(
'/Cesium'
),
// 环境变量注入
'import.meta.env.VITE_API_BASE_URL': JSON.stringify(env.VITE_API_BASE_URL ?? env.baseURL ?? ''),
'process.env': {}
},