feat: add camera configuration translations and enhance Camera components with internationalization support

This commit is contained in:
2026-02-09 21:55:56 +07:00
parent 674d53bcc5
commit 9d211ed43c
7 changed files with 489 additions and 80 deletions

View File

@@ -1,5 +1,5 @@
import { apiQueryConfigAlarm } from '@/services/master/MessageController';
import { useModel } from '@umijs/max';
import { useIntl, useModel } from '@umijs/max';
import {
Button,
Card,
@@ -10,17 +10,10 @@ import {
Tooltip,
Typography,
} from 'antd';
import { useEffect, useState } from 'react';
import { useEffect, useMemo, useState } from 'react';
const { Text } = Typography;
// Recording modes for V6
const RECORDING_MODES = [
{ label: 'Không ghi', value: 'none' },
{ label: 'Theo cảnh báo', value: 'alarm' },
{ label: '24/24', value: 'all' },
];
interface CameraV6Props {
thing: MasterModel.Thing | null;
cameraConfig?: MasterModel.CameraV6 | null;
@@ -35,6 +28,7 @@ const CameraV6: React.FC<CameraV6Props> = ({
isOnline = false,
}) => {
const { token } = theme.useToken();
const intl = useIntl();
const { initialState } = useModel('@@initialState');
const [selectedAlerts, setSelectedAlerts] = useState<string[]>([]);
const [recordingMode, setRecordingMode] =
@@ -43,6 +37,34 @@ const CameraV6: React.FC<CameraV6Props> = ({
null,
);
// Recording modes for V6 - using useMemo for i18n
const RECORDING_MODES = useMemo(
() => [
{
label: intl.formatMessage({
id: 'master.camera.config.recordingMode.none',
defaultMessage: 'Không ghi',
}),
value: 'none',
},
{
label: intl.formatMessage({
id: 'master.camera.config.recordingMode.alarm',
defaultMessage: 'Theo cảnh báo',
}),
value: 'alarm',
},
{
label: intl.formatMessage({
id: 'master.camera.config.recordingMode.all',
defaultMessage: '24/24',
}),
value: 'all',
},
],
[intl],
);
// Initialize states from cameraConfig when it's available
useEffect(() => {
if (cameraConfig) {
@@ -125,7 +147,10 @@ const CameraV6: React.FC<CameraV6Props> = ({
<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
{intl.formatMessage({
id: 'master.camera.config.recording',
defaultMessage: 'Ghi dữ liệu camera',
})}
</Text>
<Select
value={recordingMode}
@@ -135,13 +160,25 @@ const CameraV6: React.FC<CameraV6Props> = ({
popupMatchSelectWidth={false}
/>
</div>
<Tooltip title={!isOnline ? 'Thiết bị đang ngoại tuyến' : ''}>
<Tooltip
title={
!isOnline
? intl.formatMessage({
id: 'master.camera.table.offline.tooltip',
defaultMessage: 'Thiết bị đang ngoại tuyến',
})
: ''
}
>
<Button
type="primary"
onClick={handleSubmitConfig}
disabled={!isOnline}
>
Gửi đi
{intl.formatMessage({
id: 'master.camera.config.send',
defaultMessage: 'Gửi đi',
})}
</Button>
</Tooltip>
</div>
@@ -151,7 +188,10 @@ const CameraV6: React.FC<CameraV6Props> = ({
{recordingMode === 'alarm' && (
<div>
<Text strong className="block mb-2">
Danh sách cảnh báo
{intl.formatMessage({
id: 'master.camera.config.alarmList',
defaultMessage: 'Danh sách cảnh báo',
})}
</Text>
<div
@@ -161,9 +201,22 @@ const CameraV6: React.FC<CameraV6Props> = ({
borderColor: token.colorBorder,
}}
>
<Text type="secondary">đã chọn {selectedAlerts.length} mục</Text>
<Text type="secondary">
{intl.formatMessage(
{
id: 'master.camera.config.selected',
defaultMessage: 'đã chọn {0} mục',
},
{
0: selectedAlerts.length,
},
)}
</Text>
<Button type="link" onClick={handleClearAlerts}>
Xóa
{intl.formatMessage({
id: 'master.camera.config.clear',
defaultMessage: 'Xóa',
})}
</Button>
</div>