修复场站管理中编辑场站之后 侧边栏电站的显示信息 完善 home页面的天气信息
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Outlet, useNavigate, useLocation } from 'react-router-dom';
|
||||
import {
|
||||
Layout, Menu, Button, Space, Select, Avatar, Card, Tag
|
||||
@@ -15,7 +15,7 @@ import logo from '../assets/logo.png';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { RootState, useAppDispatch } from '../store';
|
||||
import { logout } from '../store/userSlice';
|
||||
import { setCurrentStation, clearStation } from '../store/stationSlice';
|
||||
import { setCurrentStation, clearStation, setStationList as setStoreStationList } from '../store/stationSlice';
|
||||
import { getMenuList } from '../api/mune';
|
||||
import { getStationByUserId } from '../api/stationManage';
|
||||
import LanguageSwitcher from './LanguageSwitcher';
|
||||
@@ -36,13 +36,19 @@ export default function AppLayout() {
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const { userInfo } = useSelector((state: RootState) => state.user);
|
||||
const { currentStation, stationId } = useSelector((state: RootState) => state.station);
|
||||
// 从 store 中同时取出 stationList(优先级最高,保证最新)
|
||||
const { currentStation, stationId, stationList: storeStationList } = useSelector((state: RootState) => state.station);
|
||||
|
||||
// 真正用于展示和选择的列表:优先用 store 中的(StationManage 编辑后会同步),否则用本地接口的
|
||||
const mergedStationList = storeStationList?.length ? storeStationList : stationList;
|
||||
|
||||
const getStationData = () => {
|
||||
getStationByUserId().then(res => {
|
||||
if (res.code === 200) {
|
||||
const list = res.data || [];
|
||||
setStationList(list);
|
||||
// 同步到全局 store,确保各组件共享同一份最新列表
|
||||
dispatch(setStoreStationList(list));
|
||||
if (!currentStation && list.length > 0) {
|
||||
dispatch(setCurrentStation(list[0]));
|
||||
}
|
||||
@@ -63,7 +69,9 @@ export default function AppLayout() {
|
||||
};
|
||||
|
||||
const handleStationChange = (id: number) => {
|
||||
const station = stationList.find(s => s.id === id);
|
||||
// 优先从合并后的列表中取(包含 store 中最新编辑的数据),其次从本地 stationList
|
||||
const station = mergedStationList.find(s => Number(s.id) === Number(id))
|
||||
|| stationList.find(s => Number(s.id) === Number(id));
|
||||
if (station) {
|
||||
dispatch(setCurrentStation(station));
|
||||
}
|
||||
@@ -206,7 +214,7 @@ export default function AppLayout() {
|
||||
value={stationId}
|
||||
placeholder={t('layout.selectStation')}
|
||||
onChange={handleStationChange}
|
||||
options={stationList.map(s => ({ label: s.siteName, value: s.id }))}
|
||||
options={mergedStationList.map(s => ({ label: s.siteName, value: s.id }))}
|
||||
style={{
|
||||
width: 'clamp(160px, 15vw, 220px)',
|
||||
backgroundColor: '#0837a8',
|
||||
|
||||
@@ -15,7 +15,12 @@ import { getOrgList } from '../../api/organization';
|
||||
import { fetchPublishedLayers } from '../../lib/geoServer';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { useAppDispatch, RootState } from '../../store';
|
||||
import { setCurrentStation as setStoreStation } from '../../store/stationSlice';
|
||||
import {
|
||||
setCurrentStation as setStoreStation,
|
||||
setStationList,
|
||||
updateStationInList,
|
||||
removeStationFromList,
|
||||
} from '../../store/stationSlice';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const { Option } = Select;
|
||||
@@ -96,12 +101,15 @@ export default function StationManage() {
|
||||
};
|
||||
getStationList(params).then(res => {
|
||||
if (res.code === 200) {
|
||||
setStationList(res.rows || []);
|
||||
const list = res.rows || [];
|
||||
setStationList(list);
|
||||
|
||||
setPagination({
|
||||
...pagination,
|
||||
total: res.total || res.rows?.length || 0
|
||||
});
|
||||
|
||||
dispatch(setStationList(list));
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -193,11 +201,18 @@ export default function StationManage() {
|
||||
saveSite(params).then(res => {
|
||||
if (res.code === 200) {
|
||||
messageApi.success(editRecord ? t('common.editSuccess') : t('common.addSuccess'));
|
||||
getStationData();
|
||||
// 编辑的场站若正是当前选中场站,则同步更新到 store(尤其 siteMapName)
|
||||
if (editRecord && storeStation && editRecord.id === storeStation.id) {
|
||||
dispatch(setStoreStation({ ...storeStation, ...params }));
|
||||
|
||||
// ========== 关键修复:同步更新全局 store ==========
|
||||
// 优先使用接口返回的最新对象(res.data),否则回退到提交参数
|
||||
const latestStation = { ...(editRecord || {}), ...params };
|
||||
|
||||
if (editRecord) {
|
||||
// 编辑:更新 stationList 中对应项(slice 内部会自动同步 currentStation)
|
||||
dispatch(updateStationInList(latestStation));
|
||||
}
|
||||
// ===================================================
|
||||
|
||||
getStationData();
|
||||
setModalVisible(false);
|
||||
} else {
|
||||
messageApi.error(res.msg || t('common.saveFail'));
|
||||
@@ -211,6 +226,8 @@ export default function StationManage() {
|
||||
deleteSite([id]).then(res => {
|
||||
if (res.code === 200) {
|
||||
messageApi.success(t('common.deleteSuccess'));
|
||||
// 同步从全局 store 中移除
|
||||
dispatch(removeStationFromList(id));
|
||||
getStationData();
|
||||
} else {
|
||||
messageApi.error(res.msg || t('common.deleteFail'));
|
||||
|
||||
@@ -647,8 +647,8 @@ export default function DeviceOverviewPage() {
|
||||
<Card title={<><SettingOutlined />{t('devices.fixed2EquipmentListFixed2')}</>} variant="borderless" style={{ borderRadius: 8, marginBottom: 8 }}>
|
||||
<Table rowKey={(record) => record.id || record.serialNumber || record.device_sn} size="small" pagination={false}
|
||||
columns={[
|
||||
{ title: t('devices.fixed2EquipmentFixed2NameFixed2'), dataIndex: 'name', width: 140 },
|
||||
{ title: t('common.type'), dataIndex: 'type', width: 90 },
|
||||
{ title: t('devices.fixed2EquipmentFixed2NameFixed2'), dataIndex: 'name', width: 180 },
|
||||
{ title: t('common.type'), dataIndex: 'type', },
|
||||
{
|
||||
title: t('workOrder.currentStatus'),
|
||||
dataIndex: 'onlineStatus',
|
||||
@@ -659,15 +659,16 @@ export default function DeviceOverviewPage() {
|
||||
return <Tag color={color} style={{ margin: 0 }}>{text}</Tag>;
|
||||
}
|
||||
}, {
|
||||
title: t('devices.abMode'), dataIndex: 'mode', width: 70, render: (text) => {
|
||||
let color = 'default';
|
||||
if (text === '作业中') color = 'processing';
|
||||
if (text === t('devices.idle')) color = 'success';
|
||||
if (text === '空闲中') color = 'success';
|
||||
if (text === '现场调试') color = 'warning';
|
||||
if (text === '远程调试') color = 'warning';
|
||||
if (text === '固件升级中') color = 'error';
|
||||
return <Tag color={color} style={{ margin: 0 }}>{text}</Tag>;
|
||||
title: t('workOrder.currentStatus'), dataIndex: 'feStatus', width: 70, render: (text) => {
|
||||
let color;
|
||||
if (text == '1') color = 'processing';
|
||||
if (text == '2') color = 'success';
|
||||
if (text == '3') color = 'default'; // default 就是灰色标签
|
||||
|
||||
return <Tag color={color} style={{ margin: 0 }}>
|
||||
{text == '1' ? "工作中" : text == '2' ? "空闲中" : "离线"}
|
||||
</Tag>;
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -464,6 +464,7 @@ const zh = {
|
||||
execTime: '执行时间',
|
||||
saveTask: '保存任务',
|
||||
abMode: '自定义模式',
|
||||
|
||||
saveFail: '保存失败',
|
||||
activatedTime: '已激活时间',
|
||||
aiAction1: 'AI',
|
||||
|
||||
@@ -89,18 +89,28 @@ export default function StationDashboard() {
|
||||
report_time: "2026-03-27 12:35:08"
|
||||
});
|
||||
const weatherType = getWeatherType(weatherdata.weather);
|
||||
// 请求天气
|
||||
// 请求天气:按当前场站地址/经纬度动态定位
|
||||
useEffect(() => {
|
||||
console.log('当前电站信息:', currentStation);
|
||||
const fetchWeather = async () => {
|
||||
try {
|
||||
const res = await getWeatherData();
|
||||
setWeatherData(res);
|
||||
const options = {} as any;
|
||||
|
||||
if (currentStation?.address) {
|
||||
options.city = currentStation.address;
|
||||
}
|
||||
const res = await getWeatherData(options);
|
||||
setWeatherData({
|
||||
...res,
|
||||
city: res?.city || currentStation?.siteName || '',
|
||||
district: res?.district || '',
|
||||
});
|
||||
} catch (err) {
|
||||
console.error("天气接口请求失败", err);
|
||||
}
|
||||
};
|
||||
fetchWeather();
|
||||
}, []);
|
||||
}, [currentStation]);
|
||||
// 模拟数据
|
||||
const stationOverview = {
|
||||
todayEnergy: 4752.0,
|
||||
|
||||
@@ -10,9 +10,20 @@ const loadStationFromStorage = () => {
|
||||
}
|
||||
};
|
||||
|
||||
// 从 localStorage 加载场站列表(可选,加速首屏)
|
||||
const loadStationListFromStorage = () => {
|
||||
try {
|
||||
const list = localStorage.getItem('stationList');
|
||||
return list ? JSON.parse(list) : [];
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
const initialState = {
|
||||
currentStation: loadStationFromStorage(), // 当前选中场站(完整对象)
|
||||
stationId: loadStationFromStorage()?.id || null, // 方便直接用 id
|
||||
stationList: loadStationListFromStorage(), // 全局场站列表(用于跨组件共享最新数据)
|
||||
};
|
||||
|
||||
const stationSlice = createSlice({
|
||||
@@ -24,19 +35,107 @@ const stationSlice = createSlice({
|
||||
state.currentStation = action.payload;
|
||||
state.stationId = action.payload?.id || null;
|
||||
localStorage.setItem('currentStation', JSON.stringify(action.payload));
|
||||
|
||||
// 同时更新 stationList 中对应项(保证列表也是最新)
|
||||
if (action.payload?.id && state.stationList?.length) {
|
||||
const idx = state.stationList.findIndex(s => Number(s.id) === Number(action.payload.id));
|
||||
if (idx >= 0) {
|
||||
state.stationList[idx] = { ...state.stationList[idx], ...action.payload };
|
||||
localStorage.setItem('stationList', JSON.stringify(state.stationList));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// 设置全局场站列表
|
||||
setStationList: (state, action) => {
|
||||
state.stationList = action.payload || [];
|
||||
localStorage.setItem('stationList', JSON.stringify(state.stationList));
|
||||
|
||||
// 如果当前 currentStation 在列表中,同步更新为列表中的最新版本
|
||||
if (state.stationId && state.stationList?.length) {
|
||||
const latest = state.stationList.find(s => Number(s.id) === Number(state.stationId));
|
||||
if (latest) {
|
||||
state.currentStation = latest;
|
||||
localStorage.setItem('currentStation', JSON.stringify(latest));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// 部分更新当前选中场站(不覆盖全部字段)
|
||||
updateCurrentStation: (state, action) => {
|
||||
if (!state.currentStation) return;
|
||||
state.currentStation = { ...state.currentStation, ...action.payload };
|
||||
state.stationId = state.currentStation?.id || state.stationId;
|
||||
localStorage.setItem('currentStation', JSON.stringify(state.currentStation));
|
||||
|
||||
// 同步更新 stationList 中对应项
|
||||
if (state.currentStation?.id && state.stationList?.length) {
|
||||
const idx = state.stationList.findIndex(s => Number(s.id) === Number(state.currentStation.id));
|
||||
if (idx >= 0) {
|
||||
state.stationList[idx] = { ...state.stationList[idx], ...action.payload };
|
||||
localStorage.setItem('stationList', JSON.stringify(state.stationList));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// 更新列表中的单个场站(编辑场站后调用)
|
||||
updateStationInList: (state, action) => {
|
||||
const updatedStation = action.payload;
|
||||
if (!updatedStation?.id) return;
|
||||
|
||||
if (!state.stationList) state.stationList = [];
|
||||
|
||||
const idx = state.stationList.findIndex(s => Number(s.id) === Number(updatedStation.id));
|
||||
if (idx >= 0) {
|
||||
state.stationList[idx] = { ...state.stationList[idx], ...updatedStation };
|
||||
} else {
|
||||
state.stationList.push(updatedStation);
|
||||
}
|
||||
localStorage.setItem('stationList', JSON.stringify(state.stationList));
|
||||
|
||||
// 如果更新的场站正好是当前选中的,同步 currentStation
|
||||
if (state.stationId && Number(state.stationId) === Number(updatedStation.id)) {
|
||||
state.currentStation = { ...state.currentStation, ...updatedStation };
|
||||
localStorage.setItem('currentStation', JSON.stringify(state.currentStation));
|
||||
}
|
||||
},
|
||||
|
||||
// 从列表中删除场站
|
||||
removeStationFromList: (state, action) => {
|
||||
const deletedId = action.payload;
|
||||
if (!state.stationList) return;
|
||||
|
||||
state.stationList = state.stationList.filter(s => Number(s.id) !== Number(deletedId));
|
||||
localStorage.setItem('stationList', JSON.stringify(state.stationList));
|
||||
|
||||
// 如果删除的是当前选中场站,清空 currentStation
|
||||
if (state.stationId && Number(state.stationId) === Number(deletedId)) {
|
||||
state.currentStation = null;
|
||||
state.stationId = null;
|
||||
localStorage.removeItem('currentStation');
|
||||
}
|
||||
},
|
||||
|
||||
// 清空场站(退出登录时用)
|
||||
clearStation: (state) => {
|
||||
state.currentStation = null;
|
||||
state.stationId = null;
|
||||
state.stationList = [];
|
||||
localStorage.removeItem('currentStation');
|
||||
localStorage.removeItem('stationList');
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const { setCurrentStation, clearStation } = stationSlice.actions;
|
||||
export const {
|
||||
setCurrentStation,
|
||||
setStationList,
|
||||
updateCurrentStation,
|
||||
updateStationInList,
|
||||
removeStationFromList,
|
||||
clearStation,
|
||||
} = stationSlice.actions;
|
||||
export default stationSlice.reducer;
|
||||
|
||||
|
||||
//使用const { currentStation, stationId } = useSelector((state: RootState) => state.station);
|
||||
|
||||
//使用const { currentStation, stationId, stationList } = useSelector((state: RootState) => state.station);
|
||||
|
||||
Reference in New Issue
Block a user