设置页重做:配置文件下载上传、内核参数、资源、免责声明
配置每次落盘都打顶层 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。 退出登录挪到侧栏底部;密度设置从设置页撤下(侧栏按钮还在); 免责声明和关于做成子页(左上角返回),登录页输入框下加同一份 免责声明的弹层入口。
This commit is contained in:
+38
-1
@@ -30,6 +30,7 @@ import {
|
||||
} from '../vendor/config-editor/index.ts'
|
||||
import type { ConfigDiagnostic, ConfigObject } from '../vendor/config-editor/index.ts'
|
||||
import { restoreInlineCommentAlignment } from '../shared/yaml-cosmetics.ts'
|
||||
import { withMarker } from '../shared/config-marker.ts'
|
||||
import { kernelVersion, validateConfigFile, reloadConfig } from './kernel.ts'
|
||||
import type { Env } from './env.ts'
|
||||
|
||||
@@ -133,7 +134,10 @@ export async function applyConfig(
|
||||
return `${stage} ${String(ms)}ms`
|
||||
}
|
||||
|
||||
const nextYaml = rewriteYaml(current.yaml, nextData)
|
||||
// 每次落盘都打上 Patchbay 标记(顶层 patchbay: 键,内核忽略未知键)。
|
||||
// 上传配置时靠它认「这是 Patchbay 管理过的配置」。标记是幂等的,
|
||||
// 已带标记的配置重打一遍内容不变,不影响下面的「内容没变就短路」
|
||||
const nextYaml = rewriteYaml(current.yaml, withMarker(nextData))
|
||||
|
||||
// 内容没变就不要走后面那一串——不必要的备份和重载只会制造噪音。
|
||||
if (nextYaml === current.yaml) {
|
||||
@@ -282,6 +286,39 @@ async function pruneBackups(env: Env): Promise<void> {
|
||||
await Promise.all(stale.map((name) => unlink(join(dir, name)).catch(() => {})))
|
||||
}
|
||||
|
||||
/**
|
||||
* 用上传的 YAML 原文整份替换当前配置。
|
||||
*
|
||||
* 解析用和读配置同一个引擎,之后走 applyConfig 完整的保护链路(自检、备份、
|
||||
* 重载、失败回退)。没有 baseRevision——整份替换本来就是覆盖语义,同还原备份。
|
||||
*/
|
||||
export async function importConfig(env: Env, content: string): Promise<ApplyOutcome> {
|
||||
let data: ConfigObject
|
||||
try {
|
||||
const doc = openDocument(content)
|
||||
const broken = doc.diagnostics.filter((d) => d.severity === 'error')
|
||||
if (broken.length > 0) {
|
||||
return {
|
||||
ok: false,
|
||||
stage: 'self-check',
|
||||
message: broken.map((p) => `${p.path.join('.')}:${p.message}`).join('\n'),
|
||||
hint: '上传的文件解析不过,当前配置没有被改动。',
|
||||
restored: false,
|
||||
}
|
||||
}
|
||||
data = doc.data
|
||||
} catch (error) {
|
||||
return {
|
||||
ok: false,
|
||||
stage: 'self-check',
|
||||
message: `上传的文件不是合法的 YAML:${String(error)}`,
|
||||
hint: '当前配置没有被改动。',
|
||||
restored: false,
|
||||
}
|
||||
}
|
||||
return applyConfig(env, data)
|
||||
}
|
||||
|
||||
/** 把某个备份恢复成当前配置。走的是和普通改动同一条保护链路。 */
|
||||
export async function restoreBackup(env: Env, name: string): Promise<ApplyOutcome> {
|
||||
const dir = await backupDir(env)
|
||||
|
||||
Reference in New Issue
Block a user