安全加固 + 结构清理:修注入/串写/竞态,DOMPurify 上线,后端补事务与 handler 测试
后端: - ORDER BY 白名单(sanitizeOrder)堵住 ?order= SQL 注入,补回归测试 - 登录限速(每 IP 10 次失败/10 分钟 429)、TLS/反代下 Secure cookie、NewAPI 构造器 - Delete/setTags/MergeTags/DeleteTag 包事务;Archive 去 500 篇上限 - 列表接口裁剪:不传 content_md,长文 content_html 截 600,新增 content_len;health 探 DB 前端: - EditorView 路由复用串写修复(RouterView :key + sync watch 回写原文章) - v-html 出口统一过 DOMPurify(sanitizeHtml),stripTags 改 DOMParser - 列表竞态防护(Home/Tag/Posts 请求序号)、TagView 分页修复 - 侧栏接口 30s 缓存去重;one:unauthorized 监听器泄漏修复 - 删 styles.css 498 行重复块;移除 tailwind/marked/vue-tsc 死依赖;CommandPalette a11y 语义
This commit is contained in:
@@ -87,6 +87,10 @@ function onKey(e) {
|
||||
e.preventDefault()
|
||||
const it = flat.value[idx.value]
|
||||
if (it) run(it.item)
|
||||
} else if (e.key === 'Tab') {
|
||||
// 面板内只有一个输入框,Tab 不外逃
|
||||
e.preventDefault()
|
||||
inputEl.value?.focus()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,9 +111,13 @@ onBeforeUnmount(() => window.removeEventListener('keydown', onKey))
|
||||
v-model="query"
|
||||
placeholder="输入命令、文章标题…"
|
||||
aria-label="搜索命令和文章"
|
||||
role="combobox"
|
||||
aria-expanded="true"
|
||||
aria-controls="cmd-listbox"
|
||||
:aria-activedescendant="flat.length ? 'cmd-opt-' + idx : undefined"
|
||||
@input="idx = 0"
|
||||
/>
|
||||
<div class="cmd-list">
|
||||
<div class="cmd-list" id="cmd-listbox" role="listbox">
|
||||
<template v-for="(sec, si) in sections" :key="si">
|
||||
<div style="padding: 8px 18px 4px; font-size: 11px; color: var(--admin-muted); letter-spacing: 0.08em; text-transform: uppercase;">
|
||||
{{ sec.name }}
|
||||
@@ -119,6 +127,9 @@ onBeforeUnmount(() => window.removeEventListener('keydown', onKey))
|
||||
:key="it.id"
|
||||
class="row"
|
||||
:class="{ on: idx === it._idx }"
|
||||
role="option"
|
||||
:id="'cmd-opt-' + it._idx"
|
||||
:aria-selected="idx === it._idx"
|
||||
@click="run(it)"
|
||||
@mouseenter="idx = it._idx"
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user