修改部署js
This commit is contained in:
@@ -195,30 +195,68 @@ const generateChartOption = (themes) => {
|
||||
*/
|
||||
const ThemeCometChart = ({ onThemeSelect }) => {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [data, setData] = useState({ themes: [], currentDate: '', availableDates: [] });
|
||||
const [allDatesData, setAllDatesData] = useState({}); // 缓存所有日期的数据
|
||||
const [availableDates, setAvailableDates] = useState([]);
|
||||
const [selectedTheme, setSelectedTheme] = useState(null);
|
||||
const [sliderIndex, setSliderIndex] = useState(0);
|
||||
const [showTooltip, setShowTooltip] = useState(false);
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
const toast = useToast();
|
||||
|
||||
// 加载指定日期的数据
|
||||
const loadData = useCallback(async (dateStr = '') => {
|
||||
// 加载所有日期的数据
|
||||
const loadAllData = useCallback(async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const apiBase = getApiBase();
|
||||
const url = dateStr
|
||||
? `${apiBase}/api/v1/zt/theme-scatter?date=${dateStr}&days=5`
|
||||
: `${apiBase}/api/v1/zt/theme-scatter?days=5`;
|
||||
const response = await fetch(url);
|
||||
// 先获取最新数据,拿到可用日期列表
|
||||
const response = await fetch(`${apiBase}/api/v1/zt/theme-scatter?days=5`);
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success && result.data) {
|
||||
setData({
|
||||
themes: result.data.themes || [],
|
||||
currentDate: result.data.currentDate || '',
|
||||
availableDates: result.data.availableDates || [],
|
||||
const dates = result.data.availableDates || [];
|
||||
setAvailableDates(dates);
|
||||
|
||||
// 缓存第一个日期(最新)的数据
|
||||
const latestDate = dates[0]?.date;
|
||||
const dataCache = {};
|
||||
if (latestDate) {
|
||||
dataCache[latestDate] = {
|
||||
themes: result.data.themes || [],
|
||||
currentDate: result.data.currentDate || '',
|
||||
};
|
||||
}
|
||||
|
||||
// 并行加载其他日期的数据
|
||||
const otherDates = dates.slice(1);
|
||||
const promises = otherDates.map(async (dateInfo) => {
|
||||
try {
|
||||
const res = await fetch(`${apiBase}/api/v1/zt/theme-scatter?date=${dateInfo.date}&days=5`);
|
||||
const data = await res.json();
|
||||
if (data.success && data.data) {
|
||||
return {
|
||||
date: dateInfo.date,
|
||||
themes: data.data.themes || [],
|
||||
currentDate: data.data.currentDate || '',
|
||||
};
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(`加载 ${dateInfo.date} 数据失败:`, e);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
const results = await Promise.all(promises);
|
||||
results.forEach((item) => {
|
||||
if (item) {
|
||||
dataCache[item.date] = {
|
||||
themes: item.themes,
|
||||
currentDate: item.currentDate,
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
setAllDatesData(dataCache);
|
||||
setSliderIndex(0); // 默认显示最新日期
|
||||
} else {
|
||||
throw new Error(result.error || '加载失败');
|
||||
}
|
||||
@@ -230,43 +268,42 @@ const ThemeCometChart = ({ onThemeSelect }) => {
|
||||
}
|
||||
}, [toast]);
|
||||
|
||||
// 初始加载
|
||||
// 初始加载所有数据
|
||||
useEffect(() => {
|
||||
loadData();
|
||||
}, [loadData]);
|
||||
loadAllData();
|
||||
}, [loadAllData]);
|
||||
|
||||
// 滑动条变化时加载对应日期数据
|
||||
// 滑动条变化时实时切换数据
|
||||
const handleSliderChange = useCallback((value) => {
|
||||
setSliderIndex(value);
|
||||
}, []);
|
||||
|
||||
const handleSliderChangeEnd = useCallback((value) => {
|
||||
if (data.availableDates && data.availableDates[value]) {
|
||||
loadData(data.availableDates[value].date);
|
||||
}
|
||||
}, [data.availableDates, loadData]);
|
||||
// 获取当前显示的数据
|
||||
const currentDateStr = availableDates[sliderIndex]?.date;
|
||||
const currentData = allDatesData[currentDateStr] || { themes: [], currentDate: '' };
|
||||
const isCurrentDateLoaded = currentDateStr && allDatesData[currentDateStr];
|
||||
|
||||
const chartOption = useMemo(() => generateChartOption(data.themes), [data.themes]);
|
||||
const chartOption = useMemo(() => generateChartOption(currentData.themes), [currentData.themes]);
|
||||
|
||||
const handleChartClick = useCallback(
|
||||
(params) => {
|
||||
if (params.data) {
|
||||
const theme = data.themes.find((t) => t.label === params.data.name);
|
||||
const theme = currentData.themes.find((t) => t.label === params.data.name);
|
||||
if (theme) {
|
||||
setSelectedTheme(theme);
|
||||
onOpen();
|
||||
}
|
||||
}
|
||||
},
|
||||
[data.themes, onOpen]
|
||||
[currentData.themes, onOpen]
|
||||
);
|
||||
|
||||
const onChartEvents = useMemo(() => ({ click: handleChartClick }), [handleChartClick]);
|
||||
|
||||
// 当前滑动条对应的日期
|
||||
const currentSliderDate = data.availableDates?.[sliderIndex]?.formatted || data.currentDate;
|
||||
const currentSliderDate = availableDates[sliderIndex]?.formatted || currentData.currentDate;
|
||||
|
||||
if (loading && data.themes.length === 0) {
|
||||
if (loading && Object.keys(allDatesData).length === 0) {
|
||||
return (
|
||||
<Center h="300px">
|
||||
<VStack spacing={4}>
|
||||
@@ -299,14 +336,21 @@ const ThemeCometChart = ({ onThemeSelect }) => {
|
||||
{loading && <Spinner size="sm" color="yellow.400" />}
|
||||
</HStack>
|
||||
<Text fontSize="sm" color="whiteAlpha.500">
|
||||
{data.currentDate}
|
||||
{currentSliderDate || currentData.currentDate}
|
||||
</Text>
|
||||
</VStack>
|
||||
</HStack>
|
||||
|
||||
{/* 图表区域 */}
|
||||
<Box h="calc(100% - 100px)">
|
||||
{data.themes.length > 0 ? (
|
||||
<Box h="calc(100% - 100px)" position="relative">
|
||||
{!isCurrentDateLoaded && !loading ? (
|
||||
<Center h="100%">
|
||||
<VStack spacing={2}>
|
||||
<Spinner size="md" color="yellow.400" />
|
||||
<Text color="whiteAlpha.500" fontSize="sm">加载中...</Text>
|
||||
</VStack>
|
||||
</Center>
|
||||
) : currentData.themes.length > 0 ? (
|
||||
<ReactECharts
|
||||
option={chartOption}
|
||||
style={{ height: '100%', width: '100%' }}
|
||||
@@ -321,11 +365,11 @@ const ThemeCometChart = ({ onThemeSelect }) => {
|
||||
</Box>
|
||||
|
||||
{/* 时间滑动条 */}
|
||||
{data.availableDates.length > 1 && (
|
||||
{availableDates.length > 1 && (
|
||||
<Box px={2} pt={2}>
|
||||
<HStack spacing={3}>
|
||||
<Text fontSize="sm" color="whiteAlpha.500" whiteSpace="nowrap">
|
||||
{data.availableDates[data.availableDates.length - 1]?.formatted?.slice(5) || ''}
|
||||
{availableDates[availableDates.length - 1]?.formatted?.slice(5) || ''}
|
||||
</Text>
|
||||
<ChakraTooltip
|
||||
hasArrow
|
||||
@@ -338,11 +382,10 @@ const ThemeCometChart = ({ onThemeSelect }) => {
|
||||
<Slider
|
||||
aria-label="date-slider"
|
||||
min={0}
|
||||
max={data.availableDates.length - 1}
|
||||
max={availableDates.length - 1}
|
||||
step={1}
|
||||
value={sliderIndex}
|
||||
onChange={handleSliderChange}
|
||||
onChangeEnd={handleSliderChangeEnd}
|
||||
onMouseEnter={() => setShowTooltip(true)}
|
||||
onMouseLeave={() => setShowTooltip(false)}
|
||||
isReversed
|
||||
@@ -360,7 +403,7 @@ const ThemeCometChart = ({ onThemeSelect }) => {
|
||||
</Slider>
|
||||
</ChakraTooltip>
|
||||
<Text fontSize="sm" color="whiteAlpha.500" whiteSpace="nowrap">
|
||||
{data.availableDates[0]?.formatted?.slice(5) || ''}
|
||||
{availableDates[0]?.formatted?.slice(5) || ''}
|
||||
</Text>
|
||||
</HStack>
|
||||
</Box>
|
||||
|
||||
Reference in New Issue
Block a user