im0o
|
91243354de
|
取消文件选择不再把弹窗一起关掉
input[type=file] 在用户取消选择时发出的 cancel 事件会冒泡,带 DropFile
的三个弹窗把它当成了 dialog 自己的 Esc 取消。cancel 处理器现在只认
target 是 dialog 本身的事件。
|
2026-08-12 03:22:53 +08:00 |
|
im0o
|
25d60f9718
|
表单行不再用 label 包 button 型控件
没有 for 的 label 会绑定内部第一个可关联控件。导入 ini 的「内容」行里
那是 DropFile 的按钮:悬停 textarea 会点亮投放区,点到行内空白处直接
弹出文件选择框。SelectBox 的开关按钮同理(InboundForm、RuleGroupForm、
ini 映射行),悬停整行都会点亮它。这些行改用 div,无障碍名换成控件
自己的 aria-label。ComboBox 的行保持 label——它第一个可关联控件是文本
输入框,label 转发过去正是想要的行为。
|
2026-08-12 03:18:43 +08:00 |
|
im0o
|
158dc9fca7
|
消化一批 P3:GEOIP 附加参数、坏 JSON 跳行、兜底丢弃;请求连接两页保活
ini 里 []GEOIP,CN,no-resolve 的附加参数原来被并进类别名,生成字段错位
的规则;现在拆出来放在目标之后。表里已有 MATCH 时配方的 []FINAL 不再
追加成死行,改为丢弃并在成功提示里注明——已有兜底是用户自己安排的
分流终点。
遥测流里偶发的坏 JSON 行改为跳过,原来一行坏数据会杀掉整个流进 5 秒
重试循环。请求页:跟随底部的阈值从 24px 降到 8px(原值比行高还大,
向上滚不足一行就被新日志拽回);silent 级别下的空状态不再说「没有流量
经过」。logs.test 的 localStorage 桩用完删掉,bun test 单进程跑,全局
残留会影响之后的测试文件。api.ts 的 format 注释照 provider.go:37 纠正。
请求页和连接页包进 KeepAlive:切走不销毁,筛选词、排序、滚动位置留住。
KeepAlive 常驻、子组件自己 v-if 进出;连接页的轮询改挂 activated——
挂载时它也触发,继续用 onMounted 会叠两个定时器,切走时停掉轮询。
|
2026-08-12 03:07:56 +08:00 |
|
im0o
|
275f536429
|
追加 Hosts、路径撞名拦截、连接页表头随行滚动、GEO 借内核通路
设置页内核参数加 hosts 行,铅笔进弹窗编辑(顶层 hosts: 键,
config.go:454,值单个或数组 parseHosts config.go:1131)。弹窗里随便改、
保存才一次性提交——写配置有几秒的校验重载,逐行失焦提交会把等待塞进
每次输入。没动过的行原样写回,数组不被重整形。
订阅和规则组新增时查缓存路径撞名:路径由名字净化而来,「订阅 A」和
「订阅/A」是两个名字、同一个文件,名字查重挡不住,会互相覆盖缓存。
纯函数在 shared 带测试,页面提交前拦。
连接页表头挪进滚动容器加 sticky:.scroller 声明 overflow-y 后按规范
连带拿到横向滚动上下文,表头留在外面时窄屏横向滚动两者脱节。表头
40px 的窗口偏移由 overscan 8 行吸收,不配 scrollMargin。
GEO 单文件下载先借内核的混合端口出去再退直连——内核自己更新 GEO 走
的是它的分流,Patchbay 直连 GitHub 不一定通。ECharts 拆独立 chunk,
业务代码改动不再让这 500KB 跟着换 hash。
|
2026-08-12 02:47:17 +08:00 |
|
im0o
|
b276c4a8fe
|
轻提示铺开到全部页面;内核状态悬停变重启;GEO 支持单文件下载
侧栏动作排撤掉重启图标,内核状态(圆点加版本号)本身变成按钮:悬停
换层显示「重启内核」,不在线时只当状态看。行高压成 1 修掉圆点和等宽
字体不居中的问题。
四个页面的一次性反馈(保存、删除、更新订阅、断开连接、测延迟结论)
全部改走 toast,commit() 改返回成败给「失败不关对话框」用;持续状态
(连接页轮询失败、请求页日志流失败)留在页内,会自动消失的提示装不下
需要一直可见的信息。toast 加 info 类别给中性结论用。
GEO 每行的更新改成单独下载那一个文件:内核只有全量更新的口子,单文件
只能服务端自己下(POST /api/geo/sync),代价是只有形状校验(MaxMind
末尾标记、geodata 首字节,shared/geo.ts 带测试)且内核重启后才换用新
文件;「更新全部」文字按钮保留内核的全量口子,有完整校验和热加载。
上传两行的按钮改「选择或拖放文件」,投放区拖入高亮,恢复策略挪到
恢复行下方。
|
2026-08-12 02:20:46 +08:00 |
|
im0o
|
f761d13579
|
反馈改右上角轻提示;侧栏加撤回重做等配置动作
设置页的横幅换成 toast(右滑入、几秒后上移淡出,web/toast.ts 单例):
动作结果看一眼就行,不值得在页面里占一块常驻位置。表单校验类的错误
仍留在各自表单里。
撤回栈就是备份链:撤回把最新备份应用回去并消费掉它,撤回前的状态进
重做栈(.patchbay-redo,同样留 10 份);重做反向;新的正常保存清空
重做栈,不留分叉历史。这两条路复用 applyConfig 的保护链路,用
restoreFrom 参数跳过自建备份——否则备份链会被撤回本身污染,撤两次
等于原地打转。侧栏左下角一排图标:撤回、重做、历史记录(备份列表
弹窗)、更新配置(POST /api/kernel/reload,给 SSH 手改后用)、重启
内核;收拢时容器变窄自动折成一列。
设置页顺手修三处:GEO 行的编辑按钮在输入框开着时再点会闪(blur 关了
click 又开),mousedown.prevent 保焦点、click 显式开关;上传按钮改
「选择或拖放文件」,投放区拖入高亮;恢复策略挪到恢复行下面。
|
2026-08-12 01:59:22 +08:00 |
|
im0o
|
2580c03bfa
|
设置页第二轮:行内编辑、GEO 资源展开、恢复与导入分家
单值设置从常驻输入框改成 InlineEdit(纯文本加铅笔,Enter 或失焦提交,
失焦无效直接放弃——失焦是「我走了」,不该把人拽回来)。测速地址加恢复
默认按钮;内核参数逐项提交,不再攒一个保存按钮。
资源一节按文件展开:四类 GEO 文件的大小和更新时间由服务端 stat 内核
工作目录得来(GET /api/geo;文件名和大小写不敏感匹配照 constant/
path.go:18-20,193-224),下载地址可改(geox-url,config.go:363-368,
默认值 578-583)。行内的更新按钮仍是全量更新——内核只有这一个口子,
没变化的文件靠内容哈希跳过。
上传拆成两个入口:恢复只认带 Patchbay 标记的文件,导入收任意配置;
新增恢复策略(兼容只搬接管段落 listeners/proxy-groups/rules/
proxy-providers/rule-providers,覆盖整份替换)。平时是按钮,拖着文件
进窗口时整行变成投放区。
|
2026-08-12 01:40:49 +08:00 |
|
im0o
|
8eb98e2e9a
|
设置页重做:配置文件下载上传、内核参数、资源、免责声明
配置每次落盘都打顶层 patchbay: 标记(盐加版本的哈希)。内核忽略未知
顶层键(yaml.Unmarshal 没开严格模式,config/config.go:612)。刻意不对
内容做哈希:本项目只接管部分段落,手改其余段落是正常用法,内容哈希
会把合法手改判成无效。上传配置时靠标记分流:有标记的确认后替换,
没有的用更重的措辞确认导入;两者都走 config-store 完整保护链路
(新端点 POST /api/config/import)。自动备份列表从界面撤下,改成
下载当前配置 + 拖放上传。
内核参数一组编辑五个老式顶层端口和 keep-alive-interval(config.go:444,
整数秒),走带基准指纹的保存链路。资源一组接 POST /configs/geo
(同步接口,透传给了 300 秒超时)。测速地址成为本地偏好,延迟测试
读它;prefs 模块顶层的浏览器全局加了存在性守卫——api.ts 开始引用
prefs,而 bun test 环境没有 localStorage。
退出登录挪到侧栏底部;密度设置从设置页撤下(侧栏按钮还在);
免责声明和关于做成子页(左上角返回),登录页输入框下加同一份
免责声明的弹层入口。
|
2026-08-12 01:01:33 +08:00 |
|
im0o
|
013f537eaa
|
订阅和规则组支持从文件导入,配置页与表单一批打磨
文件导入走两步:内容先经新端点 POST /api/provider-files 写进内核工作
目录的 providers/ 下(路径白名单校验,只认两个路径助手生成的形状),
成了再写 file 类型的声明——顺序反了内核重载会去读不存在的文件。
file 类型没有地址和自动更新(内核靠文件监视跟进),详情页照此展示,
编辑按钮禁用。ini 导入的取文件按钮换成同一个拖放模块。
订阅的更新间隔改成开关语义:内核只在 interval > 0 时才起定时拉取
(component/resource/fetcher.go:226-228),关掉开关就是不写这个键。
配置页加「更新所有订阅」,详情的「立刻更新」改叫「更新订阅」。
规则表从零开始写入时自动垫上内网直连——保留地址不直连的话第一条
代理规则一生效,访问局域网的流量就全进了代理;按钮改成「补全内网
直连」,只在有缺口时出现。
所有表单对话框点遮罩关闭;失败横幅右侧加关闭按钮。
|
2026-08-12 00:46:17 +08:00 |
|
im0o
|
7d08f37248
|
规则表单:类型候选补全为内核全集,目标候选精简
类型照抄内核解析器的 switch(rules/parser.go:17-98),37 种全给——
候选列表是过滤式的,全集不构成负担,缺项才是。目标反着来:只建议
DIRECT 和 REJECT,策略组名手填——全列出来的话,每路入站自动生成的
三个专属组会把列表灌成一面墙。
按原文编辑的输入框给一个完整的逻辑规则做占位例子(原文模式存在的
理由就是这类规则)。弹层滚动条改细杆透明轨道。
|
2026-08-12 00:13:02 +08:00 |
|
im0o
|
4c43756208
|
下拉弹层改视口定位,规则表单换 ComboBox
absolute 的弹层会计入祖先滚动容器的可滚动区域——在对话框里打开下拉,
modal 会被撑出滚动条。弹层改 position: fixed 按视口摆放:逃出所有
overflow 裁剪,又因为还在 dialog 的 DOM 子树里,照样画在 top layer 之上。
代价是位置不跟随滚动,滚动和缩放时直接收起(弹层内部滚动不算)。
三个弹层组件(SelectBox、ComboBox、SourcePicker)同一套做法。
组件根元素不再写死 width: 100%:它和调用方的宽度规则同权重,谁赢
看样式表加载顺序——请求页的级别下拉被撑满整行就是这么来的。
弹层加 user-select: none 和最大宽度,选项超长省略号截断。
规则表单的类型、载荷、目标原来是 input + datalist,原生建议列表的样式
和开合状态都管不到,换成同族的 ComboBox:选项只是建议、手填合法,
Enter 在弹层开着时选中高亮项、收起时照旧提交表单。
|
2026-08-11 23:58:53 +08:00 |
|
im0o
|
f927f9fff7
|
日志改常驻收集,加清空按钮;原生 select 统一换成 SelectBox
日志收集从请求页组件搬进模块级单例(web/log-store.ts,模式同 telemetry),
切走页面不再清空;离线时保留已收的日志,只提示不再更新。清空只清界面。
五处原生 <select> 在三个文件里各自重复同一套自绘箭头样式,而且原生控件
没有「展开中」状态可读,箭头做不了开合动画——提成 SelectBox 组件统一替换:
箭头随开合旋转 180 度,弹层带出入场动画,下方视口不够时向上弹。背景色
留 --select-bg 口子,对话框里沉一档、页面上浮一档,一个值满足不了两边。
|
2026-08-11 23:47:28 +08:00 |
|
im0o
|
07a43b5a56
|
仪表盘细节修整,内核卡片搬左列并加重启
- 曲线空态和图共用一个定高容器,数据到来不再挤下面的内容
- 路由行去掉行间分割线:它会吃掉 hover 高亮的圆角
- 每路走势线先合并成 28 桶再画。3 秒一个采样直接全画,在一条
百来像素宽的线上只剩噪声;没采集的桶画断口,不画假零
- 环形图两段加圆角,交界用底色描边让出间隙
- 内核卡片从右列搬到服务器和路由之间(左列本来就矮一截),加
「重启内核」:POST /restart 后内核自我 exec、PID 不变,恢复没有
任何通知,只能每 2 秒探一次,半分钟探不到交还给外壳心跳
|
2026-08-11 22:42:40 +08:00 |
|
im0o
|
eec5b791c8
|
仪表盘重做:ECharts 曲线、常驻遥测、路由行直达详情
采集从仪表盘组件挪进模块级单例(web/telemetry.ts),流量曲线和每路
吞吐的历史跨页面留存——跟着组件走的话切一次页面就清零一次。每路吞吐
从 /connections 快照按连接逐条求差再按 inboundName 聚合:先求和再求差
会在连接关闭时算出负数。
图表换 ECharts(按需注册):手写 SVG 折线做不出平滑曲线和时间轴,
颜色在运行时从 CSS 变量取,跟随主题切换重取。
路由列表每行带走势、速率和可选的公网 IP 检测,点击跳路由页并选中
那一路(外壳传 focus 给 RouterPage 消费)。
|
2026-08-11 22:26:36 +08:00 |
|
im0o
|
35eb463633
|
评审 P1 修正一批
设置:显式主题补 color-scheme,滚动条和 select 弹层这些 UA 部件不看
变量。连接:断开失败的提示与轮询取数分成两条通道,不再被下一秒的轮询
成功抹掉;排序加 id 决胜,内核快照的遍历序无序,空闲连接下载量普遍
相同,没有决胜键行会在断开按钮下面跳。仪表盘与请求:一条流断了连带
收掉同组连接;断流不等于内核没了(配置重载掐断流而 online 从未翻转),
5 秒自动重连。规则:正则类规则(DOMAIN-REGEX 等三种)按内核的
payloadCanContainComma 语义拆分与禁入结构化编辑,顶层逗号不再把正则
截一半当目标;findRuleIssues 注释里对内核校验的错误断言改正。
|
2026-08-11 21:14:03 +08:00 |
|
im0o
|
bd087aabea
|
接入六个新页面,外壳加内核状态心跳
导航新增「规则」项;设置、配置、规则页接 saved 事件重读配置,仪表盘只
读传 data。心跳每 10 秒探一次内核在不在:kernel.online 原本只在 load()
里更新,用户停在任何页面期间它都是静态快照,内核重启一次,请求页和
仪表盘会锁死在「内核未连接」,各页等它回来的 watch 永远不可达。恢复
在线的那一次顺带拉新运行时数据。
|
2026-08-11 21:14:03 +08:00 |
|
im0o
|
5bd4e8d609
|
合并规则页(task/rules-page)
# Conflicts:
# web/api.ts
|
2026-08-11 20:08:44 +08:00 |
|
im0o
|
8026c432e7
|
合并配置页(task/config-page)
# Conflicts:
# web/api.ts
|
2026-08-11 20:08:17 +08:00 |
|
im0o
|
5c39f666dc
|
合并仪表盘页(task/dashboard)
|
2026-08-11 20:07:22 +08:00 |
|
im0o
|
76460c7074
|
合并请求页(task/requests)
|
2026-08-11 20:07:07 +08:00 |
|
im0o
|
5b6ea8469f
|
合并连接页(task/connections)
|
2026-08-11 20:07:07 +08:00 |
|
im0o
|
dd100cfc97
|
web/api.ts 行尾归一回 LF
第一版提交把整个文件以 CRLF 写进了 blob,内容与 main 相比只是追加,
但每一行都会在后续分支的合并里制造整文件冲突。
|
2026-08-11 20:06:54 +08:00 |
|
im0o
|
9e87517a4e
|
规则页:全局分流规则的编辑与规则组管理
新增 RulesPage.vue 和规则、规则组、ini 导入三个对话框,纯逻辑放在
shared/rules.ts。拆分规则字符串复用 vendor 的 splitRuleFields——引号和
嵌套括号里的逗号不会被当成字段分隔;目标之后的选项段原样拼回,改一条
规则不会丢掉它的 no-resolve 尾巴。规则组的缓存路径显式生成:不写 path
时内核按 url 哈希自己算一个,那个路径这里算不出来。
|
2026-08-11 18:53:21 +08:00 |
|
im0o
|
0eef680fba
|
配置页:订阅的增删改和立刻更新
写配置的纯逻辑在 shared/providers.ts。删除前 subscriptionReferences 同时查
直接 use 和经订阅副本(共用缓存文件 path)的间接引用,有被引用的就拦下并列出
策略组。订阅不允许改名:名字被 use: 和副本引用,同步所有引用不如删了重建。
页面还没挂进 App.vue 的导航,由集成者统一加。
|
2026-08-11 18:50:13 +08:00 |
|
im0o
|
0eb8d05ed8
|
新增请求页:实时显示内核日志流
流式接口不能走 api.ts 的 request()(它会把整个响应读完),页面自己
fetch 加 stream.ts 按行读。解析和追加上限放在 web/logs.ts 里,因为
「脏行跳过」「超上限丢最旧的」是点名要测的行为,埋在组件里测不到。
收到的行先进缓冲、每 200ms 批量刷进列表;暂停就是不刷但照收,
缓冲也设上限,恢复时补上。级别是建连时定的,切换即重连。
|
2026-08-11 18:49:59 +08:00 |
|
im0o
|
c9a0b87af4
|
连接页:每秒轮询的连接表格,能按入站看、能断开
/connections 没有流式版本,只能全量轮询;断开是运行时动作,不走
落盘那条保护链路。两个容易做反的地方都收在 shared/connections.ts:
chains 数组第一个是最终出口,显示要倒过来;没有连接时 connections
字段是 null 而不是空数组。虚拟滚动用 @tanstack/vue-virtual,ADR 0006
留的两个例外之一,它只有 virtual-core 一个运行时依赖。
|
2026-08-11 18:48:55 +08:00 |
|
im0o
|
97c3943403
|
新增仪表盘页:流量曲线、流量与内存数字、配置概览、内核状态
流量曲线手画 SVG polyline 而不引图表库:60 个点两条线,一个图表库几百 KB,
决策记录 0006 留的例外用在这里不划算。/traffic 和 /memory 是永不结束的流,
api.request() 会把整个响应读完等于挂死,所以新增 api.openStream() 返回响应体,
交给 web/stream.ts 的 readLines 逐行读,离开页面中止 fetch 断流。
导航入口要在 App.vue 里挂,按约定留给集成者统一改。
|
2026-08-11 18:36:00 +08:00 |
|
im0o
|
fb1dd401b2
|
设置页:外观、连接、关于、备份还原
主题用 <html> 的 data-theme 标记显式选择,tokens.css 新增两组选择器块,
权重压过 prefers-color-scheme;选「跟随系统」则不标记,交回媒体查询,
系统主题切换时界面仍跟着变。
顺带把 InboundForm 和 TokenGate 里硬编码的 #fff 换成 var(--c-bg):
深色主题的强调色是浅青,白字压在上面对比度不够,深色下会看不清。
|
2026-08-11 18:35:04 +08:00 |
|
im0o
|
6c8a1c4e0e
|
并行开发前的清场:白名单、读流模块、流量格式化
任务书承诺这些在分发前已存在。/traffic /logs 补进读白名单(在流式清单
里却不在读白名单里,仪表盘和请求页一开工就 403),PUT /providers/rules
补进写白名单(规则页的立刻更新)。web/stream.ts 把分块流缝成完整的行,
分块边界和行边界无关是它存在的全部理由;shared/format.ts 是连接页和
仪表盘共用的流量数字格式化。
|
2026-08-11 18:02:21 +08:00 |
|
im0o
|
d028e63a74
|
路由页双列转单列改按内容区宽度判断,阈值等效提高
原来按视口 900px 切换,侧栏收拢与否会让同一视口下的内容区差出一百多
像素,且用户实测切换时右列已经太窄。改成容器查询,内容区 900px 以下
转单列,等效视口阈值提高到约 1100-1160。
|
2026-08-11 17:52:00 +08:00 |
|
im0o
|
4e504e9003
|
切 tab 时容器高度也做过渡
三个 tab 的成员数不同,内容淡切时高度直接跳。复用换入站那套锁高度、
量目标、过渡、交还的钩子,挂到 tab 的 Transition 上;tab 切换仍然不触发
自动滚动。
|
2026-08-11 17:08:33 +08:00 |
|
im0o
|
58d317afce
|
链式代理段出现消失不再抖动
抖动有两个来源。主要的是 .block + .block 给的 24px 上外边距在高度折叠
动画之外,出现和消失的瞬间各跳一下,折叠钩子现在把 margin-top 和高度
一起做插值。次要的是整页高度跨过视口阈值时滚动条出现消失让内容横移,
用 scrollbar-gutter 把滚动条位置常驻留出来。
|
2026-08-11 17:04:11 +08:00 |
|
im0o
|
272a0931a1
|
文本输入的焦点态统一成描边变色
原来三个组件各写一份、筛选输入框哪份都没有,落到全局的外圈 outline,
和订阅选择器长得不一样。规则上收到 tokens.css 一处,组件里的重复定义
删掉。按钮保留外圈焦点环,那是键盘可达性。
|
2026-08-11 17:03:11 +08:00 |
|
im0o
|
8bc97eb47a
|
卡片 foot 的空白处点击透传为选择
foot 属于卡片,点了没反应像是卡片坏了。延迟按钮 stop 掉冒泡,测延迟
不会连带换线;禁用的卡片照样不可点,光标跟着语义走。
|
2026-08-11 16:57:28 +08:00 |
|
im0o
|
d41012a0ab
|
自动滚动改为折叠进场时预量最终高度;侧栏导航按钮间距加大
原来在 nextTick 量高度,此时折叠动画刚从 0 起步,配置展开量到 0 不滚,
链式代理量到半截滚一半。enter 钩子触发时元素刚插入、还是自然高度,
在把高度压到 0 之前先量,得到的就是折叠结束后的位置,滚动和折叠同时
开跑。触发点也从开关挪进 foldEnter,两个包装函数随之删掉。
|
2026-08-11 16:51:49 +08:00 |
|
im0o
|
0ddefd0d5d
|
侧栏收拢时导航按钮跟着缩窄;配置区高度折叠动画;侧栏不再牵动页面内容
导航按钮宽度写死 159px 而不是 100%,百分比到像素之间没法插值,收拢时
按钮平滑缩成 36px 的方形贴住图标,高亮块不再被裁切出血。配置表单和
链式代理段的出现消失改成高度折叠(量出目标高度做插值,margin 换成
padding 否则那一截在动画之外瞬跳)。路由页「新增」按钮的文字不再跟着
侧栏密度隐藏:侧栏收拢是侧栏自己的事。
|
2026-08-11 16:42:43 +08:00 |
|
im0o
|
5a04968e17
|
详情切换动画与侧栏折叠动画
详情换选中:内容 out-in 淡切,容器高度从旧值滑到新值。auto 高度不可
插值,做法是离开前钉住当前高度,新内容进场时量出目标值过渡过去,结束
后清掉内联样式交还给内容。
侧栏折叠改成裁切式:只过渡外层宽度,内层内容按展开宽度定死、被 overflow
裁掉,文字用透明度淡出(比宽度动画快,先消失再收边,不露半截字)。原来
用 display: none 藏文字加居中图标,动画中途会重排跳位。折叠宽度取 60px
是因为图标中心恰好在 30px,收拢后天然居中,全程不用挪任何东西;折叠
按钮钉在右下角,跟着边缘走。
|
2026-08-11 16:34:20 +08:00 |
|
im0o
|
de3a4c9bcd
|
路由页动效与细节一批
基调是简单快速:hover 颜色 0.15s 过渡(全局规则,只过渡颜色不碰布局)、
对话框入场淡入加 6px 上移、tab 下划线改成共享的一条并在切换时滑动、tab
内容 out-in 淡切、配置折叠箭头居右随展开旋转 90 度、订阅下拉 0.12s 出入场。
不引 animate.css:这些效果各自十几行 CSS,引库只多不少。
配置展开和拨开链式代理时,若详情底部长出窗口则平滑滚进视野;tab 切换
不触发,来回切时页面跟着跳只会晕。二次确认对话框点遮罩可关闭,内边距
挪进内层,否则点在 dialog 自己的 padding 上也会被当成遮罩。新增入站的
表单不做遮罩关闭:误点会丢掉填了一半的内容。对话框标题改为「新增路由」
「编辑路由」。select 换自绘箭头,原生箭头贴边且位置调不了。
|
2026-08-11 16:23:03 +08:00 |
|
im0o
|
a4d08892f7
|
路由页一轮交互细化:草稿预览、预选、若干修正
上半部分收敛成一条规则:草稿和已保存一致时显示内核现状;不一致时显示
按草稿保存后的样子,将移除的画删除线、新增的虚线描边,即将被移除的当前
选中用危险色警示。点击语义只看卡片:现在就存在的成员点了立刻生效,保存
后才加入的点了是预选,保存成功后再作为运行时动作选上。预览的集合运算在
web/member-preview.ts,组件里只留接线。
其余:订阅选择器重写成可搜索多选(原平铺标签订阅一多就是一面墙);删除
入站换成页面内确认对话框;列表右列解析到最终出口并标注链式;「高级配置」
更名「配置」;表单重置改按内容比较(按引用的话任何一次运行时刷新都会冲掉
未保存的草稿,watch 传返回数组的 getter 同样触发这个问题);保存后先刷
运行时再换配置数据,避免卡片区闪空。
|
2026-08-11 14:39:47 +08:00 |
|
im0o
|
e9e2eb555d
|
每路入站配一组专属策略组,换线不再改配置文件
原本换一条线要改 config.yaml、跑校验、等内核重载,几秒起步;而换线恰恰是这个工具
最高频的动作,把它放在最重的路径上方向就错了。现在每一路配一个 select 组加 AUTO、
FALLBACK 两个,入站的 proxy 永久指向 select,换线只是调一次内核接口。这样做的前提是
选中不会丢:内核把它写进 cache 文件,重启后由 patchSelectGroup 恢复,而
profile.store-selected 默认为真。
链式代理靠给来源订阅复制一份声明、挂上 override.dialer-proxy 实现,因为这个字段写在
策略组上内核只会打条日志然后忽略。副本是 type: file 读原订阅已经落盘的缓存,而不是
自己再拉一次:自己拉的话订阅地址一不可达副本就是空的,那一路入站会一条线都不剩,
表现是端口还在监听却没有任何出口。
顺带把 shared/outbound-chain.ts 里「只有 Selector 接受手动选择」那条断言删了,它是
错的(内核检查的是 SelectAble 接口,URLTest 和 Fallback 也实现了)。界面仍然只让
Selector 可点,但理由换成了另外两种的手动指定会被它们自己撤销。
完整取舍见工作区决策记录 0007。
|
2026-08-11 03:10:38 +08:00 |
|
im0o
|
cb8effe05b
|
把入站固定到某条订阅线路
订阅线路不在内核的全局名字表里,入站的 proxy 指不到它(决策记录 0005)。做法是自动建
一个只装它的策略组再指过去,用户看到的只是「这个口固定走这条线」,组是实现细节:
不出现在策略组列表里,列表和详情里都显示成线路本身的名字,没人再引用时自动删掉。
筛选条件必须做对两件事,都写了测试:转义正则元字符(线路名形如 [vmess]DMIT.LAX.Pro
里的方括号和点不转义会匹配错),以及前后加锚点(内核是部分匹配,不加锚点时「香港01」
会把「香港011」也捞进来)。线路名含反引号时表达不了——那是内核切分多个筛选条件的
分隔符——这种情况明说做不到而不是生成一个会静默匹配错的组。
实测:生成的配置 mihomo -t 通过;起一个临时内核问 /proxies,这个组解析出来的成员
恰好只有那一条线路,且确实进了名字表所以入站指得到。
|
2026-08-10 19:33:44 +08:00 |
|
im0o
|
08ab73a4f1
|
默认入站不再显示整块出站选择
它由配置顶层的端口字段声明,没有 proxy 字段可写,画一排点不了的卡片只会让人以为
是坏了。之前藏掉这块会让面板变空,所以留着;现在「流量去向」那一节顶上来了,
默认入站照样有内容可看——它的流量去向由规则表决定,那一节反而是它唯一相关的部分。
「默认」标记和不给删除本来就有:列表里带 tag,详情里不显示编辑和删除按钮。
|
2026-08-10 19:13:54 +08:00 |
|
im0o
|
43d410d02c
|
去掉解释性提示和链条上的类型标注
链条回到纯名字。类型标注和「某某组自己决定选中哪一条」那句解释是我上一版加的,
用来说明为什么那一层点不了——但不能点的东西本来就没画出来,解释一个看不见的东西
只是噪音。
默认入站那条压成一句,内核未连接那条压成四个字,没有附加规则时整行不显示而不是
显示一个破折号。shared 里跟着没人用的 autoDecidedHops 一并删掉。
|
2026-08-10 18:58:34 +08:00 |
|
im0o
|
5049879a70
|
可切换的那一层改成最后一个 Selector,不是最后一个有成员的组
原来的规则会落在 AUTO 上,而 AUTO 是 url-test 类型——它按延迟自己挑,手动选它没有
意义,点完会被下一轮延迟测试算回去。内核里只有 Selector 是「由人来选」的
(constant/adapters.go:240-248 列了全部五种),URLTest 挑最快、Fallback 挑第一个可用、
LoadBalance 分摊,Relay 已被移除。
链条上现在每一跳都标出类型(PROXY Selector → AUTO URLTest → 线路 Vless),并明说
自动决定的那几层不接受手动指定——不说清楚的话,用户看到链条里有个组却点不了,
只会以为是坏了。
|
2026-08-10 18:38:59 +08:00 |
|
im0o
|
c5ac59ecf9
|
按审查结论重构:先补测试网,再搬代码
顺序是刻意的。前端一行测试都没有,直接挪代码挪坏了 bun test 不会红,所以先把纯逻辑
抽到能被测试的位置并补上用例,最后才动组件。测试从 37 条增加到 77 条。
抽出来的四块:
- shared/outbound-chain.ts 「这个端口现在走哪条线」的链路解析,带防环,9 条测试
- web/delay-test.ts 延迟测试失败时说什么,6 个分支原本一条测试都没有
- web/runtime.ts 运行时状态的模块级单例,照 prefs.ts 已有的模式
- web/components/InboundList.vue 入站列表
出站的文本原本散成四份(读一份、显示一份、写回一份、表单又抄一份),加一种出站模式
要同时改四处,漏一个就是显示与写回不一致。合并成 OUTBOUND_PRESETS 一张表。
给认证和透传白名单补了 20 条测试。两者都是安全边界、都是纯函数、都不需要内核在线,
之前却只靠需要活内核的冒烟脚本间接覆盖。其中「形似但不是健康检查的路径」几条确认了
正则没写松。
另外:配置快照不再把整份文件原文下发(前端从不读,白白让响应体积翻倍);
yaml-cosmetics 的测试改走生产路径,之前它自己拼了一遍三步流程,落盘链路漏掉其中一步
测试照样会绿。
|
2026-08-10 18:21:23 +08:00 |
|
im0o
|
6b208847a2
|
修掉审查查出的五个问题
保存失败会丢掉整张表单:对话框在 await commit 之前就关了,重开是空的。改成只有成功才关。
错误响应原本有两种形状({error} 和 {message,hint}),前端只读 message,于是服务端
写好的中文提示一律退化成「请求失败(HTTP 4xx)」。统一成 { message, hint? }。
路由处理器没有兜底:请求体不是合法 JSON、配置文件运行中被删,都会返回一个没有响应体
的 500。这条链路的立意是出事时把用户救回来,而出事时给的偏偏是最没信息量的一句话。
延迟测试失败被写进 done,而 done 的样式是成功绿。拆出中性的 notice——测不通是关于
线路的结论,既不是操作失败也不是成功。
刷新原本只有一个动词,测一条线路的延迟会导致整份配置被重读、重新解析、跑一遍引用校验,
外加四个往返。拆成 saved 和 runtime-changed 两个事件,运行时动作只重读运行时状态。
|
2026-08-10 14:29:46 +08:00 |
|
im0o
|
860da5d28f
|
订阅线路的类型、延迟和测速都改走 provider 接口
404 不是 bug。内核的 /proxies 只返回全局名字表(内置出站、自有线路、策略组),
订阅线路不在里面——跟「订阅线路不能被入站直接引用」是同一条约束,我没想到它同样
适用于运行时接口。所以 /proxies/{订阅线路}/delay 一律 404,而订阅线路的卡片也一直
没有协议和延迟,因为那些数据同样查不到。
现在运行时状态从两处合成:/proxies 给内置出站和策略组,/providers/proxies 给订阅线路
(它返回的线路本来就带完整的协议和延迟历史)。测速按线路归属选接口,订阅线路走
{订阅}/{线路}/healthcheck。实测该接口对同一条线路返回 200 和 325 毫秒。
|
2026-08-10 13:41:42 +08:00 |
|
im0o
|
71adcd60ef
|
界面文案改成中性措辞;延迟测试报出真实原因
原来那句「X 测不通」把两种要查不同地方的情况混在了一起。内核的语义是精确的
(hub/route/proxies.go:122-145):504 表示在给定超时内没有完成,503 表示连接建立失败
或测得延迟为 0。现在分开报,超时会写明是几秒,503 且内核没给具体错误时说明可能是
线路失效或本机到该服务器网络不通。
其余文案统一过一遍:「本机之外也能连」「这个名字已经被占用了」「还没做」这类口语改成
「允许来自其它主机的连接」「名称已存在」「尚未实现」。
|
2026-08-10 13:38:02 +08:00 |
|
im0o
|
e8b8181ef6
|
本地开发换成真订阅;闪电挪到卡片上;忙碌状态改成按卡片
占位线路删了。它们指向 127.0.0.1:1080,从来没测通过,而 URLTest 只在你选的那条
「对测试地址是活的」时才认账(urltest.go:106-111)——所以点了立刻被切回去,
一个正常行为看起来像 bug。现在本地内核直接用真订阅,通过隧道拉。
订阅地址带访问令牌,不能进 git:dev/config.yaml 变成模板,dev:reset 从 .env 取值生成
dev/home/config.yaml。顺带确认内核认 base64 分享链接格式(provider.go:384-390 回退到
ConvertsV2Ray),所以 Sub-Store 的输出直接能用。
闪电从组标题挪到每张卡的左下角,也就是延迟显示的位置:测过显示毫秒数,没测过显示闪电,
两种都能点,点了测这一条。忙碌状态从「禁用整个界面」改成只有正在提交的那张卡显示虚线边框。
|
2026-08-10 13:21:27 +08:00 |
|
im0o
|
5cdc183190
|
去掉转换入口,加测延迟,改掉刷新时丢状态的毛病
最要紧的是第三条:之前每次改完都会先切到「读取中」,页面被拆掉重建,
选中的那一路入站随之丢失,改个设置还得重新找回原来的位置。现在只有首次加载显示占位,
之后都是原地更新。切换策略组还做成了乐观更新——那一步不写配置文件,
没必要让点击等一个往返,真失败了随后的刷新会纠正回来。
测延迟按钮让内核并发测整个策略组。测不通是关于线路的结论而不是 Patchbay 出了问题,
所以全部超时用中性提示,不弹红框。
|
2026-08-10 12:53:56 +08:00 |
|