fix(web): access token 移出 localStorage;401 刷新 single-flight 并跳登录页

- access token 只存内存:XSS 拿不到持久凭据;刷新页面由 bootstrap 用 HttpOnly refresh cookie 静默换新;bootstrap 并发去重
- 并发 401 共享一次刷新(refresh 已是轮换式,各自刷新会互相踩);会话失效自动回登录页
- 防主题闪烁内联脚本挪到外部 theme-init.js(配合 CSP script-src 'self')
- 修 console 用量页与管理用户搜索的查询参数未编码;极小金额不再显示科学计数法;渠道表单数字输入清空后省略字段而非提交 0(权重 0 的渠道永远选不中)
- 改密成功后主动清会话回登录页(后端已递增 token_version,当前会话已作废)
This commit is contained in:
Sakurasan committed 2026-10-29 02:56:52 +08:00
1 parent e3ff0d3329
commit 4df2506a74
9 files changed
+83 -42

No files matched your search

+11 -4
View File
@@ -122,12 +122,19 @@ async function save() {
return
}
saving.value = true
// 数字输入被清空时 v-model 是 ''(Number('')==0):直接提交会把权重写成 0(永远选不中)。
// 省略该字段:创建走后端默认值,更新端点是指针字段不动原值。
const numOrOmit = (v: unknown) => {
if (v === '' || v === null || v === undefined) return undefined
const n = Number(v)
return Number.isNaN(n) ? undefined : n
}
const payload = {
...form,
weight: Number(form.weight),
priority: Number(form.priority),
timeout_ms: Number(form.timeout_ms),
max_concurrency: Number(form.max_concurrency),
weight: numOrOmit(form.weight),
priority: numOrOmit(form.priority),
timeout_ms: numOrOmit(form.timeout_ms),
max_concurrency: numOrOmit(form.max_concurrency),
}
try {
if (editing.value) {