Files
web-Iot/src/pages/CleanOptimization.tsx

597 lines
28 KiB
TypeScript

import React, { useState } from 'react';
import {
Row, Col, Card, Button, Table, Tag, Typography, Space, Statistic, DatePicker,
Divider, Progress, Badge, Select, Tooltip, Avatar
} from 'antd';
import {
ReloadOutlined, PlusOutlined, ArrowUpOutlined, ArrowDownOutlined,
CheckCircleOutlined, CloudOutlined, SunOutlined, MoneyCollectOutlined,
CalendarOutlined, DropOutlined, DownloadOutlined, InfoCircleOutlined,
EnvironmentOutlined, RocketOutlined, UserOutlined, WindOutlined,
PercentageOutlined, GlobalOutlined, AimOutlined, FilterOutlined,
FullscreenOutlined, ZoomInOutlined, ZoomOutOutlined
} from '@ant-design/icons';
import { Line, Pie, Column, DualAxes } from '@ant-design/charts';
import {
Droplets,
Zap,
TrendingUp,
Calendar,
DollarSign,
LayoutGrid,
ChevronRight,
Bot,
User,
CloudRain,
Thermometer,
Wind,
Info,
ShieldCheck,
Leaf
} from 'lucide-react';
import { UniversalBarChart, UniversalLineChart, UniversalPieChart } from '../components/recharts';
import { useTranslation } from 'react-i18next';
const { Title, Text } = Typography;
const { RangePicker } = DatePicker;
const { Option } = Select;
// 模拟数据
const pollutionLineData = [
{ date: '05-18', pollution: 78, threshold: 75 },
{ date: '05-19', pollution: 72, threshold: 75 },
{ date: '05-20', pollution: 65, threshold: 75 },
{ date: '05-21', pollution: 75, threshold: 75 },
{ date: '05-22', pollution: 68, threshold: 75 },
{ date: '05-23', pollution: 60, threshold: 75 },
{ date: '05-24', pollution: 68.5, threshold: 75 },
];
const compareChartData = [
{ date: 'D-7', before: 800, after: 1200 },
{ date: 'D-6', before: 850, after: 1250 },
{ date: 'D-5', before: 900, after: 1300 },
{ date: 'D-4', before: 880, after: 1280 },
{ date: 'D-3', before: 920, after: 1320 },
{ date: 'D-2', before: 950, after: 1350 },
{ date: 'D-1', before: 980, after: 1380 },
];
export default function CleanOptimizationPage() {
const { t } = useTranslation();
const cardStyle = {
borderRadius: 12,
border: '1px solid #f0f0f0',
boxShadow: '0 4px 12px rgba(0,0,0,0.05)',
overflow: 'hidden'
};
const smartCleanPlanData = [
{ id: t('clean.plan', { name: '01' }), priority: t('workOrder.high'), area: t('clean.block', { block: '15, 01' }), boost: '4,250 kWh', weather: '88%' },
{ id: t('clean.plan', { name: '02' }), priority: t('workOrder.high'), area: t('clean.block', { block: '02, 11' }), boost: '3,180 kWh', weather: '85%' },
{ id: t('clean.plan', { name: '03' }), priority: t('workOrder.medium'), area: t('clean.block', { block: '05, 12' }), boost: '2,210 kWh', weather: '80%' },
{ id: t('clean.plan', { name: '04' }), priority: t('workOrder.medium'), area: t('clean.block', { block: '07, 03' }), boost: '1,620 kWh', weather: '78%' },
{ id: t('clean.plan', { name: '05' }), priority: t('workOrder.low'), area: t('clean.block', { block: '17, 13' }), boost: '1,210 kWh', weather: '82%' },
];
const workOrderPreviewData = [
{ area: t('clean.block', { block: '15' }), priority: t('workOrder.high'), duration: '4.0 h', handler: t('clean.engineer', { name: 'Li' }), planTime: '2025-05-26 - 05-27', status: t('clean.pendingCreate') },
{ area: t('clean.block', { block: '01' }), priority: t('workOrder.high'), duration: '3.5 h', handler: t('clean.engineer', { name: 'Li' }), planTime: '2025-05-26 - 05-27', status: t('clean.pendingCreate') },
{ area: t('clean.block', { block: '02' }), priority: t('workOrder.high'), duration: '2.8 h', handler: t('clean.engineer', { name: 'Wang' }), planTime: '2025-05-28 - 05-29', status: t('clean.pendingCreate') },
{ area: t('clean.block', { block: '11' }), priority: t('workOrder.high'), duration: '2.6 h', handler: t('clean.engineer', { name: 'Wang' }), planTime: '2025-05-28 - 05-29', status: t('clean.pendingCreate') },
{ area: t('clean.block', { block: '05' }), priority: t('workOrder.medium'), duration: '2.2 h', handler: t('clean.engineer', { name: 'Zhao' }), planTime: '2025-05-29 - 05-30', status: t('clean.pendingCreate') },
];
const dualAxesData = [
[
{ date: 'D-7', value: 800, type: t('clean.generationBefore') },
{ date: 'D-7', value: 1200, type: t('clean.generationAfter') },
{ date: 'D-6', value: 850, type: t('clean.generationBefore') },
{ date: 'D-6', value: 1250, type: t('clean.generationAfter') },
{ date: 'D-5', value: 900, type: t('clean.generationBefore') },
{ date: 'D-5', value: 1300, type: t('clean.generationAfter') },
{ date: 'D-4', value: 880, type: t('clean.generationBefore') },
{ date: 'D-4', value: 1280, type: t('clean.generationAfter') },
{ date: 'D-3', value: 920, type: t('clean.generationBefore') },
{ date: 'D-3', value: 1320, type: t('clean.generationAfter') },
{ date: 'D-2', value: 950, type: t('clean.generationBefore') },
{ date: 'D-2', value: 1350, type: t('clean.generationAfter') },
{ date: 'D-1', value: 980, type: t('clean.generationBefore') },
{ date: 'D-1', value: 1380, type: t('clean.generationAfter') },
],
[
{ date: 'D-7', rate: 35 },
{ date: 'D-6', rate: 32 },
{ date: 'D-5', rate: 30 },
{ date: 'D-4', rate: 28 },
{ date: 'D-3', rate: 31 },
{ date: 'D-2', rate: 29 },
{ date: 'D-1', rate: 33 },
],
];
const pieChartData = [
{ name: t('clean.dustAccumulation'), value: 6120, color: '#165DFF' },
{ name: t('clean.birdDroppings'), value: 1480, color: '#F53F3F' },
{ name: t('clean.sandDeposition'), value: 1120, color: '#F7BA1E' },
{ name: t('constants.others'), value: 600, color: '#86909C' },
];
const renderPriorityTag = (priority: string) => {
const config: Record<string, any> = {
[t('workOrder.high')]: { color: '#ff4d4f', bg: '#fff1f0' },
[t('workOrder.medium')]: { color: '#faad14', bg: '#fff7e6' },
[t('workOrder.low')]: { color: '#52c41a', bg: '#f6ffed' },
};
return <Tag color={config[priority]?.bg} style={{ color: config[priority]?.color, border: `1px solid ${config[priority]?.color}`, margin: 0, borderRadius: 4 }}>{priority}</Tag>;
};
return (
<div style={{ background: '#f5f7fa', minHeight: '100vh', padding: '12px 0px', boxSizing: 'border-box' }}>
<style>
{`
.compact-table .ant-table-thead > tr > th {
background: #f8fafc;
padding: 8px 12px !important;
font-size: 12px;
color: #4E5969;
}
.compact-table .ant-table-tbody > tr > td {
padding: 8px 12px !important;
font-size: 12px;
}
.map-block {
transition: all 0.3s;
cursor: pointer;
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
}
.map-block:hover {
transform: scale(1.05);
box-shadow: 0 8px 16px rgba(0,0,0,0.3);
z-index: 10;
}
`}
</style>
<Row
gutter={[8, 8]}
style={{
marginBottom: 16,
flexWrap: 'wrap',
}}
>
{[
{
title: t('clean.s7'),
value: '68.5',
unit: '',
tag: t('clean.levelMedium'),
tagColor: '#52c41a',
trend: t('devices.vsYesterday', { value: '▼ 5.3' }),
trendColor: '#ff4d4f',
icon: <SunOutlined />,
color: '#faad14',
bg: '#fff7e6'
},
{
title: t('clean.fixed2RecommendedCleanBlock'),
value: '8 / 20',
unit: '',
trend: t('clean.share', { value: '40%' }),
icon: <LayoutGrid />,
color: '#1890ff',
bg: '#e6f7ff'
},
{
title: t('clean.generation'),
value: '12,850',
unit: t('home.kWh'),
trend: t('clean.shareOfTodayGeneration', { value: '14.2%' }),
icon: <TrendingUp />,
color: '#1890ff',
bg: '#f0f5ff'
},
{
title: t('clean.fixed2EstimatedRevenue'),
value: '¥ 7,286',
unit: '',
trend: t('clean.calcByElectricityPrice', { value: `0.568 ${t('clean.kwhFixed2')}` }),
icon: <DollarSign />,
color: '#faad14',
bg: '#fff7e6'
},
{
title: t('clean.cleaningFixed2TimeFixed2'),
value: '2025-05-12',
unit: '',
trend: t('clean.daysAgo', { days: '12' }),
icon: <Calendar />,
color: '#1890ff',
bg: '#f0f5ff'
},
{
title: t('clean.fixed2CleaningCost'),
value: '¥ 3,200',
unit: '',
trend: t('clean.estimatedTotalCostPerClean'),
icon: <Droplets />,
color: '#1890ff',
bg: '#e6f7ff'
},
].map((item, index) => (
<Col key={index} style={{ minWidth: '168px', flex: '1 0 auto', maxWidth: "250px" }}>
<Card
variant="borderless"
styles={{ body: { padding: '16px' } }}
style={{ borderRadius: 8, height: 120 }}
>
<div style={{ display: 'flex', justifyContent: 'space-between', height: '100%' }}>
<div style={{ display: 'flex', flexDirection: 'column', justifyContent: 'center' }}>
<div style={{ fontSize: 13, color: '#86909C', marginBottom: 4 }}>{item.title}</div>
<div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 4 }}>
<div style={{ fontSize: 24, fontWeight: 700, color: item.color }}>
{item.value}
</div>
{item.unit && (
<span style={{ fontSize: 14, color: '#4E5969' }}>{item.unit}</span>
)}
{item.tag && (
<Tag
color={item.tagColor}
style={{
borderRadius: 10,
margin: 0,
padding: '0 8px',
fontSize: 12
}}
>
{item.tag}
</Tag>
)}
</div>
<div style={{ fontSize: 12, color: item.trendColor || '#86909C' }}>
{item.trend}
</div>
</div>
<div style={{
width: 40,
height: 40,
borderRadius: '50%',
background: item.bg,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
flexShrink: 0
}}>
{React.cloneElement(item.icon, { style: { fontSize: 20, color: item.color } })}
</div>
</div>
</Card>
</Col>
))}
</Row>
{/* 标题与操作栏 */}
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 8 }}>
<Space size={8}>
<Typography.Title level={4} style={{ margin: 0, fontSize: 'clamp(18px, 1.5vw, 24px)', }}>{t('clean.fixed2CleaningOptimization')}</Typography.Title>
<InfoCircleOutlined style={{ color: '#86909C' }} />
</Space>
<Space>
<Text type="secondary" style={{ fontSize: 12 }}><ReloadOutlined />{t('clean.fixed2UpdatedAt202505240930')}</Text>
<Button icon={<ReloadOutlined />}>{t('aiAnalysis.fixed2Refresh')}</Button>
<Select defaultValue="7d" style={{ width: 110 }}>
<Option value="7d">{t('clean.7')}</Option>
<Option value="30d">{t('clean.30')}</Option>
</Select>
<Button type="primary" icon={<DownloadOutlined />}>{t('aiAnalysis.fixed2Export')}</Button>
</Space>
</div>
<Row gutter={[8, 8]} style={{ display: 'flex', alignItems: 'stretch' }}>
{/* 左侧:分析图表 */}
<Col xs={24} xl={6} style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
<Card title={<span style={{ fontSize: 14, fontWeight: 700 }}>{t('clean.s6')}</span>} variant="borderless" style={cardStyle} styles={{ body: { padding: 16 } }}>
<div style={{ fontSize: 12, color: '#86909C', marginBottom: 16, display: 'flex', justifyContent: 'space-between' }}>
<span>{t('clean.s7')}</span>
<Space size={12}>
<span style={{ display: 'flex', alignItems: 'center' }}><div style={{ width: 8, height: 8, background: '#165DFF', marginRight: 4 }}></div>{t('clean.s7')}</span>
<span style={{ display: 'flex', alignItems: 'center' }}><div style={{ width: 8, height: 2, borderBottom: '1px dashed #F53F3F', marginRight: 4 }}></div>{t('alerts.threshold')}</span>
</Space>
</div>
<UniversalLineChart
data={pollutionLineData}
xKey="date"
height={180}
dot
series={[
{
key: 'pollution',
name: t('clean.s7'),
color: '#1890ff',
strokeWidth: 3,
},
{
key: 'threshold',
name: t('alerts.threshold'),
color: '#ff4d4f',
dashed: true,
strokeWidth: 2,
},
]}
/>
</Card>
<Card title={<span style={{ fontSize: 14, fontWeight: 700 }}>{t('clean.fixed2Generation')}<Text type="secondary" style={{ fontWeight: 400, fontSize: 12 }}>{t('clean.near7Days')}</Text></span>} variant="borderless" style={cardStyle} styles={{ body: { padding: 16 } }}>
<div style={{ position: 'relative', height: "100%" }}>
<UniversalPieChart
data={pieChartData}
height={220}
innerRadius={50}
outerRadius={80}
showLabel={false}
/>
<div style={{ position: 'absolute', left: '30%', top: '50%', transform: 'translate(-50%, -50%)', textAlign: 'center' }}>
<div style={{ fontSize: 10, color: '#86909C' }}>{t('clean.batteryFixed2')}</div>
<div style={{ fontSize: 16, fontWeight: 800, color: '#1D2129' }}>9,320</div>
<div style={{ fontSize: 10, color: '#86909C' }}>{t('home.kWh')}</div>
</div>
</div>
</Card>
<Card title={<span style={{ fontSize: 14, fontWeight: 700 }}>{t('clean.fixed2Cleaning2')}<Text type="secondary" style={{ fontWeight: 400, fontSize: 12 }}>{t('clean.nearLast')}</Text></span>} variant="borderless" style={cardStyle} styles={{ body: { padding: 16 } }}>
<UniversalBarChart
data={compareChartData}
xKey="date"
height={220}
barSize={18}
series={[
{
key: 'before',
name: `${t('clean.generationBefore')} (kWh)`,
color: '#1890ff',
},
{
key: 'after',
name: `${t('clean.generationAfter')} (kWh)`,
color: '#52c41a',
},
]}
/>
</Card>
<Card title={<span style={{ fontSize: 14, fontWeight: 700 }}>{t('clean.fixed2CleaningFixed2')}</span>} variant="borderless" style={cardStyle} styles={{ body: { padding: 16 } }}>
<Row gutter={[16, 16]}>
<Col span={12}>
<div style={{ fontSize: 11, color: '#86909C', marginBottom: 4 }}>{t('clean.generation')}</div>
<div style={{ fontSize: 15, fontWeight: 800 }}>12,850 <span style={{ fontSize: 11, fontWeight: 400 }}>{t('home.kWh')}</span></div>
</Col>
<Col span={12}>
<div style={{ fontSize: 11, color: '#86909C', marginBottom: 4 }}>{t('clean.electricityPrice')}</div>
<div style={{ fontSize: 15, fontWeight: 800 }}>0.568 <span style={{ fontSize: 11, fontWeight: 400 }}>{t('clean.kwhFixed2')}</span></div>
</Col>
<Col span={12}>
<div style={{ fontSize: 11, color: '#86909C', marginBottom: 4 }}>{t('clean.netRevenueFixed2')}</div>
<div style={{ fontSize: 15, fontWeight: 800, color: '#00B42A' }}>7,286 <span style={{ fontSize: 11, fontWeight: 400 }}>{t('clean.s16')}</span></div>
</Col>
<Col span={12}>
<div style={{ fontSize: 11, color: '#86909C', marginBottom: 4 }}>{t('clean.roi')}</div>
<div style={{ fontSize: 20, fontWeight: 800, color: '#00B42A' }}>227%</div>
</Col>
</Row>
<Divider style={{ margin: '16px 0' }} />
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', background: '#f8fafc', padding: '10px 16px', borderRadius: 8 }}>
<span style={{ fontSize: 12, color: '#86909C' }}>{t('clean.s17')}</span>
<span style={{ fontSize: 18, fontWeight: 800 }}>0.44 <Text style={{ fontSize: 12 }}>{t('devices.day')}</Text></span>
</div>
</Card>
</Col>
{/* 中间:地图分布与工单预览 */}
<Col xs={24} xl={11} style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
<Card
title={<span style={{ fontSize: 15, fontWeight: 700 }}>{t('clean.recommendedCleanBlock')}</span>}
variant="borderless"
style={{ ...cardStyle, }}
styles={{ body: { padding: 0, position: 'relative', overflow: 'hidden', minHeight: 500 } }}
>
<div style={{ background: '#f8fafc', padding: '10px 20px', display: 'flex', justifyContent: 'space-between', borderBottom: '1px solid #f0f0f0', flexWrap: 'wrap', gap: 8 }}>
<Space size={16} wrap style={{ fontSize: 11 }}>
<span style={{ color: '#86909C' }}>{t('clean.s20')}</span>
<Badge color="#F53F3F" text={t('clean.priorityClean')} />
<Badge color="#FF7D00" text={t('clean.higherRange')} />
<Badge color="#F7BA1E" text={t('clean.mediumRange')} />
<Badge color="#D1FF6B" text={t('clean.lowerRange')} />
<Badge color="#00B42A" text={t('clean.cleanRange')} />
</Space>
</div>
{/* 地图背景图与浮动标签 */}
<div style={{ position: 'relative', width: '100%', height: '100%', background: '#e5e6eb' }}>
<img src="https://images.unsplash.com/photo-1509391366360-2e959784a276?ixlib=rb-1.2.1&auto=format&fit=crop&w=1200&q=80" style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
{/* 模拟区块叠加层 */}
<div style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%', background: 'rgba(0,0,0,0.1)' }} />
{/* 具体的污染区块标签 */}
{[
{ id: '01', score: '82.3', top: '25%', left: '30%', color: '#F53F3F' },
{ id: '02', score: '76.8', top: '20%', left: '45%', color: '#F53F3F' },
{ id: '03', score: '63.2', top: '22%', left: '60%', color: '#FF7D00' },
{ id: '08', score: '19.7', top: '28%', left: '75%', color: '#00B42A' },
{ id: '04', score: '33.6', top: '45%', left: '20%', color: '#F7BA1E' },
{ id: '05', score: '68.7', top: '42%', left: '38%', color: '#F53F3F' },
{ id: '15', score: '82.9', top: '48%', left: '55%', color: '#F53F3F' },
{ id: '19', score: '44.4', top: '55%', left: '65%', color: '#F7BA1E' },
{ id: '11', score: '44.8', top: '65%', left: '42%', color: '#F7BA1E' },
{ id: '13', score: '28.6', top: '75%', left: '30%', color: '#F7BA1E' },
{ id: '19', score: '24.5', top: '78%', left: '50%', color: '#D1FF6B' },
{ id: '20', score: '17.8', top: '85%', left: '40%', color: '#00B42A' },
].map(block => (
<div key={block.id} className="map-block" style={{ position: 'absolute', top: block.top, left: block.left, background: block.color, color: '#fff', padding: '4px 10px', borderRadius: 6, border: '1.5px solid #fff', textAlign: 'center', minWidth: 60 }}>
<div style={{ fontSize: 9, opacity: 0.9 }}>{t('clean.block', { block: block.id })}</div>
<div style={{ fontSize: 13, fontWeight: 800 }}>{block.score}</div>
</div>
))}
{/* 右侧悬浮控制按钮 */}
<div style={{ position: 'absolute', top: 20, right: 20, display: 'flex', flexDirection: 'column', gap: 10 }}>
<Button icon={<AimOutlined />} style={{ borderRadius: 8, width: 40, height: 40, background: 'rgba(255,255,255,0.9)', border: 'none' }} />
<Button icon={<FilterOutlined />} style={{ borderRadius: 8, width: 40, height: 40, background: 'rgba(255,255,255,0.9)', border: 'none' }} />
<Button icon={<ZoomInOutlined />} style={{ borderRadius: 8, width: 40, height: 40, background: 'rgba(255,255,255,0.9)', border: 'none' }} />
<Button icon={<ZoomOutOutlined />} style={{ borderRadius: 8, width: 40, height: 40, background: 'rgba(255,255,255,0.9)', border: 'none' }} />
<Button icon={<ReloadOutlined />} style={{ borderRadius: 8, width: 40, height: 40, background: 'rgba(255,255,255,0.9)', border: 'none' }} />
</div>
</div>
</Card>
<Card
title={<span style={{ fontSize: 15, fontWeight: 700 }}>{t('clean.fixed2Cleaning2')}</span>}
extra={<Button type="link" size="small">{t('devices.viewMore')}<ChevronRight size={14} /></Button>}
variant="borderless"
style={cardStyle}
styles={{ body: { padding: 0 } }}
>
<Table
rowKey="area"
columns={[
{ title: t('clean.s45'), dataIndex: 'area', key: 'area' },
{ title: t('workOrder.priority'), dataIndex: 'priority', key: 'priority', render: renderPriorityTag },
{ title: t('clean.s46'), dataIndex: 'duration', key: 'duration' },
{ title: t('systemSetting.leader'), dataIndex: 'handler', key: 'handler' },
{ title: t('clean.timeFixed2'), dataIndex: 'planTime', key: 'planTime' },
{ title: t('roles.status'), dataIndex: 'status', key: 'status', render: (s) => <Tag color="blue" variant="outline" style={{ borderRadius: 4 }}>{s}</Tag> },
{ title: t('roles.actions'), key: 'action', render: () => <Button type="primary" size="small" style={{ borderRadius: 4 }}>{t('clean.s23')}</Button> },
]}
dataSource={workOrderPreviewData}
pagination={false}
size="small"
className="compact-table"
/>
</Card>
</Col>
{/* 右侧:决策建议与参考 */}
<Col xs={24} xl={7} style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
<Card title={<span style={{ fontSize: 14, fontWeight: 700 }}>{t('clean.cleaning2')}</span>} variant="borderless" style={cardStyle} styles={{ body: { padding: 0 } }}>
<div style={{ background: '#f8fafc', padding: '8px 16px', borderBottom: '1px solid #f0f0f0' }}>
<Text type="secondary" style={{ fontSize: 11 }}>{t('clean.algorithmModel')}</Text>
</div>
<Table
rowKey="id"
columns={[
{ title: t('clean.s48'), dataIndex: 'id', key: 'id', width: 85 },
{ title: t('workOrder.priority'), dataIndex: 'priority', key: 'priority', render: (p) => <span style={{ color: p === t('workOrder.high') ? '#F53F3F' : '#F7BA1E', fontWeight: 600 }}>{p}</span>, width: 65 },
{ title: t('clean.s49'), dataIndex: 'area', key: 'area' },
{ title: t('clean.s50'), dataIndex: 'boost', key: 'boost', render: (b) => <span style={{ color: '#00B42A', fontWeight: 600 }}>{b}</span> },
{ title: t('clean.fixed2WeatherAdvice2Fixed2SuitableExec2'), dataIndex: 'weather', key: 'weather', render: (w) => <Space size={4}>{w} <SunOutlined style={{ color: '#F7BA1E' }} /></Space> },
]}
dataSource={smartCleanPlanData}
pagination={false}
size="small"
className="compact-table"
/>
</Card>
<Card title={<span style={{ fontSize: 14, fontWeight: 700 }}>{t('clean.fixed2Cleaning2')}</span>} variant="borderless" style={cardStyle} styles={{ body: { padding: 16 } }}>
<Row gutter={12}>
<Col span={12}>
<div style={{ background: '#F9F0FF', borderRadius: 12, padding: 16, border: '1px solid #D3ADF7', height: '100%' }}>
<Space align="center" style={{ marginBottom: 12 }}>
<div style={{ width: 32, height: 32, background: '#722ED1', borderRadius: '50%', display: 'flex', alignItems: 'center', justifyContent: 'center' }}><Bot size={18} color="#fff" /></div>
<Text strong style={{ fontSize: 13, color: '#391085' }}>{t('clean.robot')}</Text>
</Space>
<div style={{ fontSize: 11, color: '#531DAB', marginBottom: 12, lineHeight: 1.5 }}>{t('clean.cleaning')}</div>
<div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 11 }}>
<span style={{ color: '#8c8c8c' }}>{t('clean.s28')}</span>
<Text strong>{t('clean.18')}</Text>
</div>
</div>
</Col>
<Col span={12}>
<div style={{ background: '#E6F7FF', borderRadius: 12, padding: 16, border: '1px solid #91D5FF', height: '100%' }}>
<Space align="center" style={{ marginBottom: 12 }}>
<div style={{ width: 32, height: 32, background: '#1890FF', borderRadius: '50%', display: 'flex', alignItems: 'center', justifyContent: 'center' }}><User size={18} color="#fff" /></div>
<Text strong style={{ fontSize: 13, color: '#003A8C' }}>{t('clean.fixed2Manual')}</Text>
</Space>
<div style={{ fontSize: 11, color: '#0050B3', marginBottom: 12, lineHeight: 1.5 }}>{t('clean.handleCriticalArea')}</div>
<div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 11 }}>
<span style={{ color: '#8c8c8c' }}>{t('clean.s28')}</span>
<Text strong>{t('clean.32')}</Text>
</div>
</div>
</Col>
</Row>
</Card>
<Card title={<span style={{ fontSize: 14, fontWeight: 700 }}>{t('clean.fixed2WeatherAdvice2')}<Text type="secondary" style={{ fontSize: 12, fontWeight: 400 }}>({t('clean.plan', { name: '01' })})</Text></span>} variant="borderless" style={cardStyle} styles={{ body: { padding: 16 } }}>
<Row gutter={12}>
<Col span={8}>
<div style={{ background: '#f8fafc', padding: '10px 4px', borderRadius: 8, textAlign: 'center', border: '1px solid #f0f0f0' }}>
<div style={{ fontSize: 11, color: '#86909C' }}>{`05-26 (${t('common.mondayShort')})`}</div>
<SunOutlined style={{ fontSize: 24, color: '#F7BA1E', margin: '8px 0' }} />
<div style={{ fontSize: 12, fontWeight: 700 }}>{t('clean.fixed2Cloudy1828')}</div>
</div>
</Col>
<Col span={8}>
<div style={{ background: '#f8fafc', padding: '10px 4px', borderRadius: 8, textAlign: 'center', border: '1px solid #f0f0f0' }}>
<div style={{ fontSize: 11, color: '#86909C' }}>{`05-27 (${t('common.tuesdayShort')})`}</div>
<SunOutlined style={{ fontSize: 24, color: '#F7BA1E', margin: '8px 0' }} />
<div style={{ fontSize: 12, fontWeight: 700 }}>{t('clean.1930')}</div>
</div>
</Col>
<Col span={8}>
<div style={{ display: 'flex', flexDirection: 'column', gap: 10, justifyContent: 'center', height: '100%' }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
<Wind size={14} style={{ color: '#86909C' }} /><span style={{ fontSize: 11 }}>{t('clean.s36')}<b style={{ color: '#00B42A' }}>{`2.1m/s (${t('clean.suitable')})`}</b></span>
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
<CloudRain size={14} style={{ color: '#86909C' }} /><span style={{ fontSize: 11 }}>{t('clean.s37')}<b style={{ color: '#86909C' }}>{`10% (${t('clean.low')})`}</b></span>
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
<Droplets size={14} style={{ color: '#165DFF' }} /><span style={{ fontSize: 11 }}>{t('clean.s38')}<b style={{ color: '#165DFF' }}>{`${t('clean.sufficient')} (50t)`}</b></span>
</div>
</div>
</Col>
</Row>
</Card>
<Card title={<span style={{ fontSize: 14, fontWeight: 700 }}>{t('clean.fixed2Cleaning')}</span>} variant="borderless" style={cardStyle} styles={{ body: { padding: 16 } }}>
<Row gutter={[16, 16]}>
{[
{ icon: <Droplets size={18} color="#165DFF" />, bg: '#E8F3FF', label: t('clean.s52'), value: t('clean.tonUnit', { value: '18' }), sub: t('clean.waterSaveWithRobot', { value: '30%' }), subColor: '#00B42A' },
{ icon: <Calendar size={18} color="#165DFF" />, bg: '#E8F3FF', label: t('clean.s53'), value: t('clean.hourUnit', { value: '12' }), sub: t('clean.parallelJobs', { count: '2' }), subColor: '#86909C' },
{ icon: <Leaf size={18} color="#00B42A" />, bg: '#E8FFEA', label: t('clean.s54'), value: t('clean.tonUnit', { value: '6.85' }), sub: t('clean.co2Reduction'), subColor: '#86909C' },
{ icon: <ShieldCheck size={18} color="#F7BA1E" />, bg: '#FFF7E8', label: t('clean.s55'), value: t('aiAnalysis.lowRisk'), valueColor: '#00B42A', sub: t('clean.safeControllable'), subColor: '#86909C' },
].map((item, idx) => (
<Col span={12} key={idx}>
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
<div style={{ width: 40, height: 40, background: item.bg, borderRadius: 10, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>{item.icon}</div>
<div>
<div style={{ fontSize: 11, color: '#86909C' }}>{item.label}</div>
<div style={{ fontSize: 14, fontWeight: 800, color: item.valueColor || '#1D2129' }}>{item.value}</div>
<div style={{ fontSize: 9, color: item.subColor }}>{item.sub}</div>
</div>
</div>
</Col>
))}
</Row>
<div style={{ marginTop: 20, padding: 12, background: '#f8fafc', borderRadius: 8, display: 'flex', gap: 8, alignItems: 'flex-start' }}>
<InfoCircleOutlined style={{ fontSize: 12, color: '#86909C', marginTop: 2 }} />
<Text type="secondary" style={{ fontSize: 10, lineHeight: 1.5 }}>{t('clean.generationActualFixed2ExecuteWeatherAdvice2Ok')}</Text>
</div>
</Card>
</Col>
</Row>
</div>
);
}