fix: 总览筛选竞态守卫 + 时间戳统一上海时间序列化
- dashboard loadOverview 加请求令牌:快速切换站点时丢弃过期响应, 防旧数据覆盖与旧 finally 提前清 loading - 后端序列化统一 timezone.localtime:sites.created_at 与 visitors 的 first/last_seen_at、会话 started/ended_at、时间线事件 time—— USE_TZ 下 isoformat() 是 UTC,与上海自然日口径同屏矛盾(差 8 小时) - 站点弹窗域名加轻量主机名正则校验与实时提示(拦含空格等垃圾输入) Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -142,17 +142,21 @@
|
||||
}
|
||||
}
|
||||
|
||||
// 请求令牌:快速切换站点时丢弃过期响应,避免旧数据覆盖新数据/旧 finally 提前清 loading
|
||||
let reqSeq = 0
|
||||
const loadOverview = async () => {
|
||||
const id = ++reqSeq
|
||||
overviewLoading.value = true
|
||||
try {
|
||||
overview.value = await getOverview(
|
||||
const resp = await getOverview(
|
||||
selectedSiteId.value === ALL_SITES ? undefined : selectedSiteId.value
|
||||
)
|
||||
if (id === reqSeq) overview.value = resp
|
||||
} catch {
|
||||
// 失败已由请求层统一 ElMessage 提示;overview 置空让图表/表格走空态
|
||||
overview.value = null
|
||||
if (id === reqSeq) overview.value = null
|
||||
} finally {
|
||||
overviewLoading.value = false
|
||||
if (id === reqSeq) overviewLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -91,6 +91,9 @@
|
||||
return s.split('/')[0].split(':')[0]
|
||||
}
|
||||
|
||||
/** 轻量主机名校验:点分级,每级字母/数字/连字符且不以连字符开头结尾(IPv4/单级内网名天然匹配) */
|
||||
const HOSTNAME_RE = /^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/
|
||||
|
||||
/** textarea 按行解析 → 归一 → 去空去重 */
|
||||
const parseDomains = (text: string): string[] => {
|
||||
const out: string[] = []
|
||||
@@ -246,9 +249,14 @@
|
||||
validator: (_rule, value: string, callback) => {
|
||||
if (value && !parseDomains(value).length) {
|
||||
callback(new Error('未解析到有效域名,请检查格式'))
|
||||
} else {
|
||||
callback()
|
||||
return
|
||||
}
|
||||
const invalid = parseDomains(value).filter((d) => !HOSTNAME_RE.test(d))
|
||||
if (invalid.length) {
|
||||
callback(new Error(`以下内容不是有效主机名:${invalid.join('、')}`))
|
||||
return
|
||||
}
|
||||
callback()
|
||||
},
|
||||
trigger: 'blur'
|
||||
}
|
||||
@@ -264,6 +272,10 @@
|
||||
.map((l) => l.trim())
|
||||
.filter(Boolean)
|
||||
const normalized = parseDomains(text)
|
||||
const invalid = normalized.filter((d) => !HOSTNAME_RE.test(d))
|
||||
if (invalid.length) {
|
||||
return `以下内容不是有效主机名:${invalid.join('、')}(仅限字母/数字/连字符/点)`
|
||||
}
|
||||
const changed =
|
||||
normalized.join('\n') !== rawLines.join('\n') || rawLines.length !== normalized.length
|
||||
if (!changed) return ''
|
||||
|
||||
Reference in New Issue
Block a user