import { useState } from "react"; import { Button, Box, Dialog, DialogTitle, DialogContent, DialogActions, IconButton, List, ListItem, ListItemText, Typography, Divider, alpha, styled, useTheme } from "@mui/material"; import { useTranslation } from "react-i18next"; import { useLockFn } from "ahooks"; import { ruleProviderUpdate } from "@/services/api"; import { StorageOutlined, RefreshRounded } from "@mui/icons-material"; import { useAppData } from "@/providers/app-data-provider"; import dayjs from "dayjs"; import { showNotice } from "@/services/noticeService"; // 定义规则提供者类型 interface RuleProviderItem { behavior: string; ruleCount: number; updatedAt: number; vehicleType: string; } // 辅助组件 - 类型框 const TypeBox = styled(Box)<{ component?: React.ElementType }>(({ theme }) => ({ display: "inline-block", border: "1px solid #ccc", borderColor: alpha(theme.palette.secondary.main, 0.5), color: alpha(theme.palette.secondary.main, 0.8), borderRadius: 4, fontSize: 10, marginRight: "4px", padding: "0 2px", lineHeight: 1.25, })); export const ProviderButton = () => { const { t } = useTranslation(); const theme = useTheme(); const [open, setOpen] = useState(false); const { ruleProviders, refreshRules, refreshRuleProviders } = useAppData(); const [updating, setUpdating] = useState>({}); // 检查是否有提供者 const hasProviders = Object.keys(ruleProviders || {}).length > 0; // 更新单个规则提供者 const updateProvider = useLockFn(async (name: string) => { try { // 设置更新状态 setUpdating(prev => ({ ...prev, [name]: true })); await ruleProviderUpdate(name); // 刷新数据 await refreshRules(); await refreshRuleProviders(); showNotice('success', `${name} 更新成功`); } catch (err: any) { showNotice('error', `${name} 更新失败: ${err?.message || err.toString()}`); } finally { // 清除更新状态 setUpdating(prev => ({ ...prev, [name]: false })); } }); // 更新所有规则提供者 const updateAllProviders = useLockFn(async () => { try { // 获取所有provider的名称 const allProviders = Object.keys(ruleProviders || {}); if (allProviders.length === 0) { showNotice('info', "没有可更新的规则提供者"); return; } // 设置所有provider为更新中状态 const newUpdating = allProviders.reduce((acc, key) => { acc[key] = true; return acc; }, {} as Record); setUpdating(newUpdating); // 改为串行逐个更新所有provider for (const name of allProviders) { try { await ruleProviderUpdate(name); // 每个更新完成后更新状态 setUpdating(prev => ({ ...prev, [name]: false })); } catch (err) { console.error(`更新 ${name} 失败`, err); // 继续执行下一个,不中断整体流程 } } // 刷新数据 await refreshRules(); await refreshRuleProviders(); showNotice('success', "全部规则提供者更新成功"); } catch (err: any) { showNotice('error', `更新失败: ${err?.message || err.toString()}`); } finally { // 清除所有更新状态 setUpdating({}); } }); const handleClose = () => { setOpen(false); }; if (!hasProviders) return null; return ( <> {t("Rule Providers")} {Object.entries(ruleProviders || {}).map(([key, item]) => { const provider = item as RuleProviderItem; const time = dayjs(provider.updatedAt); const isUpdating = updating[key]; return ( { const bgcolor = mode === "light" ? "#ffffff" : "#24252f"; const hoverColor = mode === "light" ? alpha(primary.main, 0.1) : alpha(primary.main, 0.2); return { backgroundColor: bgcolor, "&:hover": { backgroundColor: hoverColor, borderColor: alpha(primary.main, 0.3) } }; } ]} > {key} {provider.ruleCount} {t("Update At")}: {time.fromNow()} } secondary={ {provider.vehicleType} {provider.behavior} } /> updateProvider(key)} disabled={isUpdating} sx={{ animation: isUpdating ? "spin 1s linear infinite" : "none", "@keyframes spin": { "0%": { transform: "rotate(0deg)" }, "100%": { transform: "rotate(360deg)" } } }} title={t("Update Provider") as string} > ); })} ); };