feat: add MQTT client for camera configuration and enhance camera management

This commit is contained in:
2026-02-08 11:58:57 +07:00
parent 78162fc0cb
commit d619534a73
14 changed files with 1254 additions and 111 deletions

View File

@@ -1,6 +1,15 @@
import { apiQueryConfigAlarm } from '@/services/master/MessageController';
import { useModel } from '@umijs/max';
import { Button, Card, Col, Row, Select, theme, Typography } from 'antd';
import {
Button,
Card,
Col,
Row,
Select,
theme,
Tooltip,
Typography,
} from 'antd';
import { useEffect, useState } from 'react';
const { Text } = Typography;
@@ -15,15 +24,24 @@ const RECORDING_MODES = [
interface CameraV6Props {
thing: MasterModel.Thing | null;
cameraConfig?: MasterModel.CameraV6 | null;
onSubmit?: (config: {
recordingMode: MasterModel.CameraV6['record_type'];
selectedAlerts: string[];
}) => void;
isOnline?: boolean;
}
const CameraV6: React.FC<CameraV6Props> = ({ thing, cameraConfig }) => {
const CameraV6: React.FC<CameraV6Props> = ({
thing,
cameraConfig,
onSubmit,
isOnline = false,
}) => {
const { token } = theme.useToken();
const { initialState } = useModel('@@initialState');
const [selectedAlerts, setSelectedAlerts] = useState<string[]>([]);
const [recordingMode, setRecordingMode] = useState<'none' | 'alarm' | 'all'>(
'none',
);
const [recordingMode, setRecordingMode] =
useState<MasterModel.CameraV6['record_type']>('none');
const [alarmConfig, setAlarmConfig] = useState<MasterModel.Alarm[] | null>(
null,
);
@@ -95,31 +113,39 @@ const CameraV6: React.FC<CameraV6Props> = ({ thing, cameraConfig }) => {
setSelectedAlerts([]);
};
const handleSubmitAlerts = () => {
console.log('Submit alerts:', {
const handleSubmitConfig = () => {
onSubmit?.({
recordingMode,
selectedAlerts,
});
// TODO: Call API to save alert configuration
};
return (
<Card className="p-4">
{/* Recording Mode */}
<div className="mb-6">
<Text strong className="block mb-2">
Ghi dữ liệu camera
</Text>
<div className="flex gap-8 items-center">
<Select
value={recordingMode}
onChange={setRecordingMode}
options={RECORDING_MODES}
className="w-full sm:w-1/2 md:w-1/3 lg:w-1/4"
/>
<Button type="primary" onClick={handleSubmitAlerts}>
Gửi đi
</Button>
<div className="flex flex-col sm:flex-row gap-2 sm:gap-4 items-start sm:items-end">
<div className="w-full sm:w-1/3 lg:w-1/4">
<Text strong className="block mb-2">
Ghi dữ liệu camera
</Text>
<Select
value={recordingMode}
onChange={setRecordingMode}
options={RECORDING_MODES}
className="w-full"
popupMatchSelectWidth={false}
/>
</div>
<Tooltip title={!isOnline ? 'Thiết bị đang ngoại tuyến' : ''}>
<Button
type="primary"
onClick={handleSubmitConfig}
disabled={!isOnline}
>
Gửi đi
</Button>
</Tooltip>
</div>
</div>
@@ -155,7 +181,7 @@ const CameraV6: React.FC<CameraV6Props> = ({ thing, cameraConfig }) => {
size="small"
hoverable
onClick={() => handleAlertToggle(alarmId)}
className="cursor-pointer h-20 flex items-center justify-center"
className="cursor-pointer h-24 flex items-center justify-center"
style={{
borderColor: isSelected
? token.colorPrimary
@@ -166,14 +192,21 @@ const CameraV6: React.FC<CameraV6Props> = ({ thing, cameraConfig }) => {
: token.colorBgContainer,
}}
>
<div className="p-2 text-center w-full">
<div className="p-1 text-center w-full flex items-center justify-center h-full">
<Text
className="text-xs break-words"
className="text-xs"
style={{
color: isSelected
? token.colorPrimary
: token.colorText,
display: '-webkit-box',
WebkitLineClamp: 3,
WebkitBoxOrient: 'vertical',
overflow: 'hidden',
wordBreak: 'break-word',
lineHeight: '1.2em',
}}
title={alarm.name}
>
{alarm.name}
</Text>