add types & refactor: simplify rule-item extra handling

* add types

* refactor: simplify rule-item extra handling
This commit is contained in:
Memory 2026-03-28 11:19:31 +08:00 committed by GitHub
parent a068c74307
commit 07dd85db84
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 45 additions and 35 deletions

View File

@ -12,13 +12,11 @@ const RuleItem: React.FC<RuleItemProps> = (props) => {
const { type, payload, proxy, index: listIndex, extra } = props const { type, payload, proxy, index: listIndex, extra } = props
const ruleIndex = props.index ?? listIndex const ruleIndex = props.index ?? listIndex
const { disabled, hitCount, hitAt, missCount, missAt } = extra const [isEnabled, setIsEnabled] = useState(!extra?.disabled)
const [isEnabled, setIsEnabled] = useState(!disabled)
useEffect(() => { useEffect(() => {
setIsEnabled(!disabled) setIsEnabled(!extra?.disabled)
}, [disabled]) }, [extra?.disabled])
const handleToggle = async (v: boolean): Promise<void> => { const handleToggle = async (v: boolean): Promise<void> => {
setIsEnabled(v) setIsEnabled(v)
@ -30,9 +28,6 @@ const RuleItem: React.FC<RuleItemProps> = (props) => {
} }
} }
const totalCount = hitCount + missCount
const hitRate = totalCount > 0 ? (hitCount / totalCount) * 100 : 0
const formatRelativeTime = (timestamp: string): string => { const formatRelativeTime = (timestamp: string): string => {
const now = Date.now() const now = Date.now()
const time = new Date(timestamp).getTime() const time = new Date(timestamp).getTime()
@ -43,8 +38,6 @@ const RuleItem: React.FC<RuleItemProps> = (props) => {
return t('rules.hitAt.days', { count: Math.floor(diff / 86400) }) return t('rules.hitAt.days', { count: Math.floor(diff / 86400) })
} }
const hasStats = totalCount > 0
return ( return (
<div className={`w-full px-2 pb-2 ${listIndex === 0 ? 'pt-2' : ''}`}> <div className={`w-full px-2 pb-2 ${listIndex === 0 ? 'pt-2' : ''}`}>
<Card className={!isEnabled ? 'opacity-50' : ''}> <Card className={!isEnabled ? 'opacity-50' : ''}>
@ -67,29 +60,33 @@ const RuleItem: React.FC<RuleItemProps> = (props) => {
</div> </div>
</div> </div>
{/* 统计信息 */}
{hasStats && (
<div className="flex items-center gap-3 text-xs shrink-0">
<span className="text-foreground-500 whitespace-nowrap">
{formatRelativeTime(hitAt || missAt)}
</span>
<span className="text-foreground-600 font-medium whitespace-nowrap">
{hitCount}/{totalCount}
</span>
<Chip size="sm" variant="flat" color="primary" className="text-xs">
{hitRate.toFixed(1)}%
</Chip>
</div>
)}
</div> </div>
{/* 右侧开关 */} {extra && (() => {
<Switch const total = extra.hitCount + extra.missCount
size="sm" const rate = total > 0 ? (extra.hitCount / total) * 100 : 0
isSelected={isEnabled} return (
onValueChange={handleToggle} <>
aria-label="Toggle rule" <div className="flex items-center gap-3 text-xs shrink-0">
/> <span className="text-foreground-500 whitespace-nowrap">
{formatRelativeTime(extra.hitAt || extra.missAt)}
</span>
<span className="text-foreground-600 font-medium whitespace-nowrap">
{extra.hitCount}/{total}
</span>
<Chip size="sm" variant="flat" color="primary" className="text-xs">
{rate.toFixed(1)}%
</Chip>
</div>
<Switch
size="sm"
isSelected={isEnabled}
onValueChange={handleToggle}
aria-label="Toggle rule"
/>
</>
)
})()}
</div> </div>
</CardBody> </CardBody>
</Card> </Card>

21
src/shared/types.d.ts vendored
View File

@ -3,7 +3,7 @@ type LogLevel = 'info' | 'debug' | 'warning' | 'error' | 'silent'
type SysProxyMode = 'auto' | 'manual' type SysProxyMode = 'auto' | 'manual'
type CardStatus = 'col-span-2' | 'col-span-1' | 'hidden' type CardStatus = 'col-span-2' | 'col-span-1' | 'hidden'
type AppTheme = 'system' | 'light' | 'dark' type AppTheme = 'system' | 'light' | 'dark'
type MihomoGroupType = 'Selector' | 'URLTest' | 'LoadBalance' | 'Relay' type MihomoGroupType = 'Selector' | 'URLTest' | 'Fallback' | 'LoadBalance' | 'Relay'
type Priority = type Priority =
| 'PRIORITY_LOW' | 'PRIORITY_LOW'
| 'PRIORITY_BELOW_NORMAL' | 'PRIORITY_BELOW_NORMAL'
@ -31,10 +31,15 @@ type MihomoProxyType =
| 'Hysteria2' | 'Hysteria2'
| 'Tuic' | 'Tuic'
| 'WireGuard' | 'WireGuard'
| 'Mieru'
| 'AnyTLS'
| 'Sudoku'
| 'Masque'
| 'TrustTunnel'
type TunStack = 'gvisor' | 'mixed' | 'system' type TunStack = 'gvisor' | 'mixed' | 'system'
type FindProcessMode = 'off' | 'strict' | 'always' type FindProcessMode = 'off' | 'strict' | 'always'
type DnsMode = 'normal' | 'fake-ip' | 'redir-host' type DnsMode = 'normal' | 'fake-ip' | 'redir-host' | 'hosts'
type FilterMode = 'blacklist' | 'whitelist' type FilterMode = 'blacklist' | 'whitelist' | 'rule'
type NetworkInterfaceInfo = os.NetworkInterfaceInfo type NetworkInterfaceInfo = os.NetworkInterfaceInfo
interface IAppVersion { interface IAppVersion {
@ -73,7 +78,7 @@ interface IMihomoRulesDetail {
proxy: string proxy: string
size: number size: number
index: number index: number
extra: { extra?: {
disabled: boolean disabled: boolean
hitCount: number hitCount: number
hitAt: string hitAt: string
@ -124,6 +129,7 @@ interface IMihomoConnectionDetail {
download: number download: number
start: string start: string
chains: string[] chains: string[]
providerChains: string[]
rule: string rule: string
rulePayload: string rulePayload: string
} }
@ -149,9 +155,14 @@ interface IMihomoProxy {
tfo: boolean tfo: boolean
type: MihomoProxyType type: MihomoProxyType
udp: boolean udp: boolean
uot: boolean
xudp: boolean xudp: boolean
mptcp: boolean mptcp: boolean
smux: boolean smux: boolean
interface?: string
'routing-mark'?: number
'provider-name'?: string
'dialer-proxy'?: string
} }
interface IMihomoGroup { interface IMihomoGroup {
@ -159,6 +170,7 @@ interface IMihomoGroup {
all: string[] all: string[]
extra: Record<string, { alive: boolean; history: IMihomoHistory[] }> extra: Record<string, { alive: boolean; history: IMihomoHistory[] }>
testUrl?: string testUrl?: string
expectedStatus?: string
fixed?: string fixed?: string
hidden: boolean hidden: boolean
history: IMihomoHistory[] history: IMihomoHistory[]
@ -191,6 +203,7 @@ interface IMihomoRuleProvider {
type: string type: string
updatedAt: string updatedAt: string
vehicleType: string vehicleType: string
payload?: string[]
} }
interface IMihomoProxyProviders { interface IMihomoProxyProviders {