工单告警完善
This commit is contained in:
20
env.js
20
env.js
@@ -9,17 +9,17 @@ const currentEnv = import.meta.env?.MODE || process.env.NODE_ENV;
|
||||
// 环境配置映射
|
||||
const envConfig = {
|
||||
[ENV.DEV]: {
|
||||
baseURL: 'http://192.168.2.59:8081',//http://192.168.2.56:8081
|
||||
//baseURL: 'http://1.95.137.212:59015',//http://192.168.2.56:8081
|
||||
WS_URL: 'ws://192.168.2.59:9002/ws/',
|
||||
mqtt_url: "ws://1.95.137.212:8083/mqtt",
|
||||
geoserver_url: "http://192.168.2.59:7000/geoserver"
|
||||
|
||||
//baseURL: 'http://1.95.137.212:8081',//http://192.168.2.56:8081
|
||||
////baseURL: 'https://serviceri.satabot.com',
|
||||
//WS_URL: 'ws://1.95.137.212:9002/ws/',
|
||||
//baseURL: 'http://192.168.2.59:8081',//http://192.168.2.56:8081
|
||||
////baseURL: 'http://1.95.137.212:59015',//http://192.168.2.56:8081
|
||||
//WS_URL: 'ws://192.168.2.59:9002/ws/',
|
||||
//mqtt_url: "ws://1.95.137.212:8083/mqtt",
|
||||
//geoserver_url: "http://1.95.137.212:59018/geoserver"
|
||||
//geoserver_url: "http://192.168.2.59:7000/geoserver"
|
||||
|
||||
baseURL: 'http://1.95.137.212:8081',//http://192.168.2.56:8081
|
||||
//baseURL: 'https://serviceri.satabot.com',
|
||||
WS_URL: 'ws://1.95.137.212:9002/ws/',
|
||||
mqtt_url: "ws://1.95.137.212:8083/mqtt",
|
||||
geoserver_url: "http://1.95.137.212:59018/geoserver"
|
||||
|
||||
//baseURL: 'http://1.95.137.212:59015',//http://192.168.2.56:8081
|
||||
////baseURL: 'https://serviceri.satabot.com',
|
||||
|
||||
@@ -39,7 +39,7 @@ export function updateAlarm(data) {
|
||||
export function handleAlarm(data) {
|
||||
return request({
|
||||
url: '/iot/alarm/handle',
|
||||
method: 'put',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
@@ -51,7 +51,8 @@ const DraggableBox: React.FC<Props> = ({
|
||||
</div>
|
||||
|
||||
{/* 传入的视频内容 */}
|
||||
<div>{children}</div>
|
||||
<div style={{ height: 'calc(100% - 50px)', width: '100%' }}>
|
||||
{children}</div>
|
||||
</div>
|
||||
</Draggable>
|
||||
);
|
||||
|
||||
@@ -915,7 +915,12 @@ const CesiumMap = React.forwardRef(({ ifClear, ifClearPlanLine, ifClearNavLine,
|
||||
}
|
||||
viewer.scene.requestRender();
|
||||
}
|
||||
} else {
|
||||
tracePointRef.current.setMode(TPMode.LOCATION);
|
||||
isNavigationModeRef.current = false;
|
||||
lastFinishPointRef.current = null;
|
||||
}
|
||||
|
||||
}, [drawRealTime]);
|
||||
|
||||
// 处理完成点
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
Col,
|
||||
App,
|
||||
Typography,
|
||||
Slider,
|
||||
} from 'antd';
|
||||
|
||||
const { Text } = Typography;
|
||||
@@ -767,6 +768,19 @@ export default function DeviceManagementPage() {
|
||||
<Form.Item label="运行速度" name="runSpeed" rules={[{ required: true, message: '请输入运行速度' }]}>
|
||||
<InputNumber placeholder="请输入运行速度" style={{ width: '100%' }} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item label="左轮增益系数" name="leftWheelGain" rules={[{ required: true, message: '请设置左轮增益系数' }]}>
|
||||
<div style={{ display: 'flex', gap: 12, alignItems: 'center' }}>
|
||||
<InputNumber min={0.1} max={1} step={0.01} style={{ width: 100 }} placeholder="0.1~1" />
|
||||
</div>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item label="右轮增益系数" name="rightWheelGain" rules={[{ required: true, message: '请设置右轮增益系数' }]}>
|
||||
<div style={{ display: 'flex', gap: 12, alignItems: 'center' }}>
|
||||
{/*<Slider min={0} max={1} step={0.01} style={{ flex: 1 }} />*/}
|
||||
<InputNumber min={0.1} max={1} step={0.01} style={{ width: 100 }} placeholder="0.1~1" />
|
||||
</div>
|
||||
</Form.Item>
|
||||
<Form.Item>
|
||||
<Button type="primary" htmlType="submit">保存参数</Button>
|
||||
</Form.Item>
|
||||
@@ -921,7 +935,8 @@ export default function DeviceManagementPage() {
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div >
|
||||
);
|
||||
}
|
||||
|
||||
@@ -11,19 +11,11 @@ import {
|
||||
getAlarmList,
|
||||
getAlarmDetail
|
||||
} from '../../api/alarmApi.js';
|
||||
import { alarmTypeMap } from '@/constants.js';
|
||||
|
||||
const { Option } = Select;
|
||||
const { RangePicker } = DatePicker;
|
||||
|
||||
// ====================== 枚举配置 ======================
|
||||
const alarmTypeMap = {
|
||||
1: '设备故障',
|
||||
2: '数据异常',
|
||||
3: '通信中断',
|
||||
4: '性能告警',
|
||||
5: '安全告警',
|
||||
6: '环境告警'
|
||||
};
|
||||
|
||||
const alarmLevelConfig = {
|
||||
1: { description: '严重', color: '#FF4D4F' },
|
||||
@@ -120,6 +112,7 @@ const AlarmHistory = () => {
|
||||
setQueryParams({
|
||||
deviceId: values.deviceId || '',
|
||||
alarmLevel: values.alarmLevel || '',
|
||||
alarmType: values.alarmType || '',
|
||||
handleStatus: values.handleStatus || '',
|
||||
startTime,
|
||||
endTime,
|
||||
@@ -142,6 +135,12 @@ const AlarmHistory = () => {
|
||||
},
|
||||
{ title: '设备ID', dataIndex: 'deviceId', width: 160 },
|
||||
{ title: '设备名称', dataIndex: 'deviceName', ellipsis: true },
|
||||
{
|
||||
title: '告警类型',
|
||||
dataIndex: 'alarmType',
|
||||
width: 130,
|
||||
render: (t) => alarmTypeMap[t] || '-'
|
||||
},
|
||||
{
|
||||
title: '告警级别',
|
||||
width: 100,
|
||||
@@ -201,6 +200,16 @@ const AlarmHistory = () => {
|
||||
</Select>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item name="alarmType" label="告警类型">
|
||||
<Select placeholder="全部" style={{ width: 150 }} allowClear>
|
||||
<Option value="UAV_FAULT">无人机故障</Option>
|
||||
<Option value="MOWER_FAULT">割草机故障</Option>
|
||||
<Option value="OTHER_DEVICE_FAULT">其他设备故障</Option>
|
||||
<Option value="SERVER_FAILURE">服务器故障</Option>
|
||||
<Option value="SYSTEM_ERROR">系统错误</Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item name="handleStatus" label="处理状态">
|
||||
<Select placeholder="全部" style={{ width: 130 }} allowClear>
|
||||
<Option value={1}>待处理</Option>
|
||||
@@ -266,6 +275,7 @@ const AlarmHistory = () => {
|
||||
<Descriptions.Item label="告警时间">
|
||||
{currentAlarm?.alarmTime ? dayjs(currentAlarm.alarmTime).format('YYYY-MM-DD HH:mm:ss') : '-'}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="告警类型">{alarmTypeMap[currentAlarm?.alarmType] || '-'}</Descriptions.Item>
|
||||
<Descriptions.Item label="告警级别">
|
||||
<Tag color={levelColor[currentAlarm?.alarmLevel]} style={{ border: 'none', color: '#fff' }}>
|
||||
{levelText[currentAlarm?.alarmLevel]}
|
||||
|
||||
@@ -129,6 +129,7 @@ export default function AlarmCenterPage() {
|
||||
const [queryParams, setQueryParams] = useState({
|
||||
deviceId: '',
|
||||
alarmLevel: '',
|
||||
alarmType: '',
|
||||
handleStatus: '',
|
||||
startTime: '',
|
||||
endTime: '',
|
||||
@@ -198,7 +199,7 @@ export default function AlarmCenterPage() {
|
||||
const doHandle = async (values) => {
|
||||
try {
|
||||
await handleAlarm({
|
||||
id: currentAlarm.id,
|
||||
alarmId: currentAlarm.id,
|
||||
handleStatus: values.handleStatus,
|
||||
handleRemark: values.handleRemark || '已处理'
|
||||
});
|
||||
@@ -357,19 +358,20 @@ export default function AlarmCenterPage() {
|
||||
const day = dayjs(item.alarmTime).format('MM-DD');
|
||||
const level = String(item.alarmLevel);
|
||||
|
||||
if (!groupMap[day]) groupMap[day] = {};
|
||||
if (!groupMap[day]) groupMap[day] = { ERROR: 0, WARNING: 0, INFO: 0 };
|
||||
groupMap[day][level] = (groupMap[day][level] || 0) + 1;
|
||||
});
|
||||
|
||||
// 规整成图表一维数组
|
||||
// 直接返回 ERROR/WARNING/INFO 字段,匹配图表series key
|
||||
return Object.entries(groupMap).map(([date, obj]) => ({
|
||||
date,
|
||||
severe: obj['ERROR'] || 0, // 严重
|
||||
important: obj['WARNING'] || 0, // 重要
|
||||
normal: obj['INFO'] || 0, // 一般
|
||||
ERROR: obj.ERROR || 0,
|
||||
WARNING: obj.WARNING || 0,
|
||||
INFO: obj.INFO || 0,
|
||||
}));
|
||||
};
|
||||
|
||||
|
||||
const pieData = [
|
||||
{
|
||||
name: '错误',
|
||||
@@ -417,6 +419,19 @@ export default function AlarmCenterPage() {
|
||||
}
|
||||
};
|
||||
|
||||
// 联系负责人
|
||||
const handleContactUser = () => {
|
||||
// 自行实现:弹窗联系人列表、拨打电话、跳转聊天、弹窗信息等
|
||||
console.log('联系负责人', currentAlarm);
|
||||
};
|
||||
|
||||
// 派发工单
|
||||
const handleDispatchOrder = () => {
|
||||
// 自行实现:选择处理人、分配工单接口、弹窗派发表单
|
||||
console.log('派发工单', currentAlarm);
|
||||
};
|
||||
|
||||
|
||||
// 生成工单
|
||||
const handleaddOrder = async () => {
|
||||
if (!currentAlarm) {
|
||||
@@ -805,12 +820,15 @@ export default function AlarmCenterPage() {
|
||||
{/* 告警详情抽屉 */}
|
||||
<Drawer
|
||||
title="告警详情"
|
||||
//open={true}
|
||||
open={drawerVisible}
|
||||
onClose={() => setDrawerVisible(false)}
|
||||
width={480}
|
||||
destroyOnClose
|
||||
>
|
||||
|
||||
<Spin spinning={detailLoading}>
|
||||
|
||||
{currentAlarm && (
|
||||
<Form form={form} onFinish={doHandle} layout="vertical">
|
||||
<>
|
||||
@@ -867,11 +885,35 @@ export default function AlarmCenterPage() {
|
||||
<div>
|
||||
|
||||
</div>
|
||||
<Button type="primary" onClick={handleaddOrder}>生成工单</Button>
|
||||
<div style={{ display: 'flex', justifyContent: 'flex-end', gap: 12 }}>
|
||||
<Button type="default" onClick={handleContactUser}>联系负责人</Button>
|
||||
<Button type="primary" onClick={handleaddOrder}>
|
||||
生成工单
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* 处理操作 */}
|
||||
<Card size="small" title="处理操作" style={{ marginBottom: 16 }}>
|
||||
<Form.Item label="处理状态" name="handleStatus" rules={[{ required: true, message: '请选择处理状态' }]}>
|
||||
<Select>
|
||||
<Option value={1}>待处理</Option>
|
||||
<Option value={2}>处理中</Option>
|
||||
<Option value={3}>已关闭</Option>
|
||||
<Option value={4}>已忽略</Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Form.Item label="处理备注" name="handleRemark">
|
||||
<Input.TextArea rows={2} placeholder="请输入处理备注" />
|
||||
</Form.Item>
|
||||
</Card>
|
||||
|
||||
|
||||
{/* 底部按钮 */}
|
||||
<Button type="primary" block htmlType="submit">确认处理</Button>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -922,12 +964,11 @@ export default function AlarmCenterPage() {
|
||||
rules={[{ required: true, message: '请选择告警类型' }]}
|
||||
>
|
||||
<Select>
|
||||
<Option value={1}>设备故障</Option>
|
||||
<Option value={2}>数据异常</Option>
|
||||
<Option value={3}>通信中断</Option>
|
||||
<Option value={4}>性能告警</Option>
|
||||
<Option value={5}>安全告警</Option>
|
||||
<Option value={6}>环境告警</Option>
|
||||
<Option value="UAV_FAULT">无人机故障</Option>
|
||||
<Option value="MOWER_FAULT">割草机故障</Option>
|
||||
<Option value="OTHER_DEVICE_FAULT">其他设备故障</Option>
|
||||
<Option value="SERVER_FAILURE">服务器故障</Option>
|
||||
<Option value="SYSTEM_ERROR">系统错误</Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
|
||||
|
||||
@@ -304,7 +304,7 @@ export default function RobotTaskPage() {
|
||||
const data = {
|
||||
lon: robotRealtimePosition?.longitude || 0,
|
||||
lat: robotRealtimePosition?.latitude || 0,
|
||||
//heading: robotRealtimePosition?.yaw || 0,
|
||||
heading: robotRealtimePosition?.yaw || 0,
|
||||
}
|
||||
return data;
|
||||
}, [robotRealtimePosition])
|
||||
@@ -1772,7 +1772,7 @@ export default function RobotTaskPage() {
|
||||
title={`机器人全景视频 - ${executingRobot.deviceAlias || executingRobot.serialNumber}`}
|
||||
onClose={() => setShowVideo(false)}
|
||||
>
|
||||
<div >
|
||||
<div style={{ height: '100%', width: '100%' }}>
|
||||
<MowerAllView
|
||||
serialNumber={executingRobot.serialNumber}
|
||||
robotVideo={robotVideo}
|
||||
|
||||
@@ -205,7 +205,7 @@ export function MowerAllView({ serialNumber, robotVideo, error, ready, statusDat
|
||||
<span>俯仰角:</span>
|
||||
<span>{statusData.pitch !== undefined ? `${Number(statusData.pitch).toFixed(1)}°` : '-'}</span>
|
||||
<span>航向角状态:</span>
|
||||
<span>{runningStatus.headingStatus !== undefined ? `${runningStatus.headingStatus == 1 ? '初始化' : '未初始化'}` : '-'}</span>
|
||||
<span>{statusData.headingStatus !== undefined ? `${statusData.headingStatus == 1 ? '初始化' : '未初始化'}` : '-'}</span>
|
||||
<span>定位:</span>
|
||||
<span>
|
||||
{statusData.qual == 0 ? '无效' :
|
||||
|
||||
@@ -18,12 +18,11 @@ export const sourceTypeMap = {
|
||||
};
|
||||
|
||||
export const alarmTypeMap = {
|
||||
1: '设备故障',
|
||||
2: '数据异常',
|
||||
3: '通信中断',
|
||||
4: '性能告警',
|
||||
5: '安全告警',
|
||||
6: '环境告警'
|
||||
'UAV_FAULT': '无人机故障',
|
||||
'MOWER_FAULT': '割草机故障',
|
||||
'OTHER_DEVICE_FAULT': '其他设备故障',
|
||||
'SERVER_FAILURE': '服务器故障',
|
||||
'SYSTEM_ERROR': '系统错误'
|
||||
};
|
||||
|
||||
export const alarmLevelConfig = {
|
||||
|
||||
@@ -423,7 +423,8 @@ const WorkOrderPage = () => {
|
||||
const submitComplete = async (values) => {
|
||||
try {
|
||||
const now = dayjs().format('YYYY-MM-DDTHH:mm:ss');
|
||||
const params = {
|
||||
// 1. 组装后端需要的 IOTWorkOrder JSON 对象
|
||||
const workOrderObj = {
|
||||
...currentDetail,
|
||||
id: values.id,
|
||||
orderNo: currentDetail?.orderNo,
|
||||
@@ -433,7 +434,24 @@ const WorkOrderPage = () => {
|
||||
handleResult: values.handleResult,
|
||||
handleRemark: values.handleRemark,
|
||||
};
|
||||
await completeWorkOrder(params);
|
||||
|
||||
// 2. 新建 FormData,适配 @RequestPart 混合参数
|
||||
const formData = new FormData();
|
||||
// workOrder 字段:转JSON字符串
|
||||
formData.append(
|
||||
"workOrder",
|
||||
new Blob([JSON.stringify(workOrderObj)], {
|
||||
type: "application/json"
|
||||
})
|
||||
);
|
||||
|
||||
//formData.append('workOrder', JSON.stringify(workOrderObj));
|
||||
|
||||
|
||||
|
||||
// 4. 请求方法 completeWorkOrder 必须修改:传 formData,删除 headers 的 Content-Type
|
||||
await completeWorkOrder(formData);
|
||||
|
||||
messageApi.success('工单已完成');
|
||||
setCompleteModalVisible(false);
|
||||
getWorkOrderList();
|
||||
@@ -444,6 +462,7 @@ const WorkOrderPage = () => {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// 获取工单详情
|
||||
const getWorkOrderDetail = async (id) => {
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user