fix: displays rule lineNo instead of index in rule page (#6230) (#6286)

* fix: displays rule lineNo instead of index in rule page (#6230)

* fix(rules): derive line numbers in view model without mutating shared rules

* doc: update changelog

---------

Co-authored-by: Slinetrac <realakayuki@gmail.com>
This commit is contained in:
許景欣 2026-02-10 13:11:14 +08:00 committed by GitHub
parent 5f9096dd6e
commit 277ded4c44
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 14 additions and 15 deletions

View File

@ -10,6 +10,7 @@
- 修复恢复休眠后无法操作托盘 - 修复恢复休眠后无法操作托盘
- 修复首页当前节点图标语义显示不一致 - 修复首页当前节点图标语义显示不一致
- 修复使用 URL scheme 导入订阅时没有及时重载配置 - 修复使用 URL scheme 导入订阅时没有及时重载配置
- 修复规则界面里的行号展示逻辑
<details> <details>
<summary><strong> ✨ 新增功能 </strong></summary> <summary><strong> ✨ 新增功能 </strong></summary>

View File

@ -1,4 +1,5 @@
import { styled, Box, Typography } from "@mui/material"; import { styled, Box, Typography } from "@mui/material";
import { Rule } from "tauri-plugin-mihomo-api";
const Item = styled(Box)(({ theme }) => ({ const Item = styled(Box)(({ theme }) => ({
display: "flex", display: "flex",
@ -15,8 +16,7 @@ const COLOR = [
]; ];
interface Props { interface Props {
index: number; value: Rule & { lineNo: number };
value: IRuleItem;
} }
const parseColor = (text: string) => { const parseColor = (text: string) => {
@ -31,7 +31,7 @@ const parseColor = (text: string) => {
}; };
const RuleItem = (props: Props) => { const RuleItem = (props: Props) => {
const { index, value } = props; const { value } = props;
return ( return (
<Item sx={{ borderBottom: "1px solid var(--divider-color)" }}> <Item sx={{ borderBottom: "1px solid var(--divider-color)" }}>
@ -40,7 +40,7 @@ const RuleItem = (props: Props) => {
variant="body2" variant="body2"
sx={{ lineHeight: 2, minWidth: 30, mr: 2.25, textAlign: "center" }} sx={{ lineHeight: 2, minWidth: 30, mr: 2.25, textAlign: "center" }}
> >
{index} {value.lineNo}
</Typography> </Typography>
<Box sx={{ userSelect: "text" }}> <Box sx={{ userSelect: "text" }}>

View File

@ -30,7 +30,13 @@ const RulesPage = () => {
}, [refreshRules, refreshRuleProviders, pageVisible]); }, [refreshRules, refreshRuleProviders, pageVisible]);
const filteredRules = useMemo(() => { const filteredRules = useMemo(() => {
return rules.filter((item) => match(item.payload)); const rulesWithLineNo = rules.map((item, index) => ({
...item,
// UI-only derived data; keep app context/SWR data immutable
lineNo: index + 1,
}));
return rulesWithLineNo.filter((item) => match(item.payload ?? ""));
}, [rules, match]); }, [rules, match]);
const scrollToTop = () => { const scrollToTop = () => {
@ -81,9 +87,7 @@ const RulesPage = () => {
style={{ style={{
flex: 1, flex: 1,
}} }}
itemContent={(index, item) => ( itemContent={(_index, item) => <RuleItem value={item} />}
<RuleItem index={index + 1} value={item} />
)}
followOutput={"smooth"} followOutput={"smooth"}
scrollerRef={(ref) => { scrollerRef={(ref) => {
if (ref) ref.addEventListener("scroll", handleScroll); if (ref) ref.addEventListener("scroll", handleScroll);

View File

@ -298,7 +298,7 @@ export const AppDataProvider = ({
// 数据 // 数据
proxies: proxiesData, proxies: proxiesData,
clashConfig, clashConfig,
rules: rulesData?.rules || [], rules: rulesData?.rules ?? [],
sysproxy, sysproxy,
runningMode, runningMode,
uptime: uptimeData || 0, uptime: uptimeData || 0,

View File

@ -82,12 +82,6 @@ interface IConfigData {
"proxy-groups"?: IProxyGroupItem[]; "proxy-groups"?: IProxyGroupItem[];
} }
interface IRuleItem {
type: string;
payload: string;
proxy: string;
}
interface IProxyItem { interface IProxyItem {
name: string; name: string;
type: string; type: string;