refactor(ui): unify all dialogs on radix base per guide ch.6/7

- base dialog: z raised to 300/301 (was below sidebar z-200 - dialogs
  appeared sunken under navigation), overlay bg-black/45 + 2px blur,
  unified close button with hover/focus-visible states, footer pt-4
- FormDialog normalized: width presets sm/md/lg/xl + optional
  description, single scrollable body (header/footer fixed), unified
  top-right close from base
- ModalOverlay rewritten on radix kernel, same props (+title/noScroll):
  portal/focus trap/scroll lock/ESC with proper nesting (fixes
  chain-close when ticket detail opens quick-review), 200ms animation,
  z-300 layering - was a bare div with no a11y, no animation, ESC
  via document listener that leaked to nested dialogs
- killed box-in-box: all 14 ModalOverlay callers stripped their inner
  card wrapper (double border/shadow/radius/padding gone) and duplicate
  scroll containers; EditInstanceDialog (4th standalone system) migrated
  to ModalOverlay, gains ESC/animation/portal
- visual unification per guide: dialog title text-base semibold
  (was 4 sizes), close button one form (was 5), footer buttons on
  dg-btn system (secondary/primary/danger, was 4 systems), primary
  color var(--dg-blue) everywhere (yellow/emerald/blue-500/600 mixed
  before), widths 4 presets (was 7 arbitrary values)
- dead code removed: 3 orphaned LDAP dialog components, leftover
  create-OU state/handler in BatchImportModal, unused icon imports

verified in browser: users create dialog shows single card (0 inner
cards), 12px radius, z-301/300, overlay blur, sidebar correctly
covered; tsc/build/audit gates green
This commit is contained in:
Logan.Li committed 2026-10-27 16:35:32 +08:00
1 parent 36724bba94
commit 48c8fddbe9
20 files changed
+1645 -1258

No files matched your search

@@ -1,21 +1,29 @@
# LDAP:借鉴 aiops 的 AD 兼容与配置门控 + 连不上根因说明
# 统一全部弹框(对照指南 06/07 章)
研究结论:LDAP 参数本身没问题(本机对 8.217.205.92:389 实测连接/导入/登录全通,aiops 种子配置与 opsxsql 同源)。「连不了」的根因在**你正在跑的旧后端实例**:① 其 sqlite 只读(实测报 `attempt to write a readonly database`,LDAP 配置根本存不进去);② 旧二进制还有 CORS 白名单 bug(非 5173 端口的前端所有写请求空 403)。需重启到新构建后端+可写 DB。本次按 aiops 补两块真差距:
探索结论:「奇特」的可解释根因——① ModalOverlay 系 14 处全部「弹窗里再套一张卡片」(双边框/双阴影/双圆角/双倍内边距);② 双滚动条;③ **侧栏/顶栏 z-200 浮在弹窗 z-100 之上**(弹窗像陷进布局里、导航不被遮罩仍可点);④ 关闭钮 5 种形态、footer 按钮 4 套体系、主色 5 种、标题字号 4 档、宽度 7 档;⑤ ModalOverlay 系无动画/无 ESC 之外的可达性;⑥ TicketDetailDialog 内嵌弹窗 ESC 会连锁关闭外框;⑦ EditInstanceDialog 独立第四体系(无 ESC/动画/portal);⑧ LDAP 三弹窗疑似孤儿 + BatchImportModal 残留死代码。
## 1. 后端借鉴 aiops(controller/ldap.go)——AD/OpenLDAP 双兼容
opsxsql 只支持 OpenLDAP(objectClass=inetOrgPerson + uid),AD 域(sAMAccountName)会搜不到。移植 aiops 的:
- **多轮过滤器**(ldapUserFilter/ldapADUserFilter/ldapUserListFilters):配置过滤器优先 → `(objectClass=inetOrgPerson)` → AD `(&(objectClass=user)(|(sAMAccountName=*)...))` 兜底;登录时 OpenLDAP 过滤器 + AD 过滤器两轮尝试
- **属性回退链**(ldapEntryAttr):uid→sAMAccountName→userPrincipalName、cn→displayName、mail、telephoneNumber→mobile,映射解析按回退取值
- 应用于 tryLDAPAuth(handler/auth.go)、ListLDAPUsers、BatchImportLDAP
- 保留 opsxsql 的 AES 密码加密(aiops 是明文,不倒退)
## 1. 基座统一(改 3 个基础组件,全站生效)
- `ui/dialog.tsx`:遮罩/面板 z-index 提到 **300/301**(压过侧栏 200,指南 modal=300 档);遮罩 `bg-black/45 + backdrop-blur-[2px]`;保留 fade+zoom 200ms 动画
- `FormDialog` 规范化:统一头(标题 text-base font-semibold + 可选描述)+ **右上角统一关闭钮**(absolute X 16px,替换现在 5 种形态)、内容区单滚动(flex-col,header/footer 固定,max-h-85vh)、footer 右对齐 `gap-2 pt-4`;类名用 cn() 合并
- `ConfirmDialog`:标题加 font-semibold,与 FormDialog 对齐(shadcn Button 保留)
## 2. 前端配置门控(aiops `{ldapConfig && <Section/>}` 模式)
- **LdapConfigPage**:GetLDAPConfig 返回 null(未配置)时,隐藏「LDAP 账号管理」(LdapManagePanel/LdapUserTable/建 OU/建用户/账号测试),显示"未配置,先保存基础连接"引导态;保存成功后管理区出现
- **BatchImportModal**(UsersPage):未配置 LDAP 时隐藏「导入到 LDAP / 从 LDAP 导入」两个 tab,仅保留本地 CSV 导入
## 2. ModalOverlay 重写为 Radix 内核(同 props,14 处零改调用签名)
`open/onClose/width/className` 接口不变,内部改渲染 Radix Dialog → 免费获得 portal/焦点陷阱/滚动锁定/ESC(含嵌套正确分层,修复连锁关闭)/200ms 动画/z-300;面板策略改「header 固定 + 内容区滚动」。**修 ESC 连锁关闭 bug**
## 3. 实测验证(测试后端,独立 DB)
- 全新库未配置态:LdapConfigPage 管理区隐藏 + 导入弹窗无 LDAP tab
- 写入配置(8.217.205.92:389/dc=opsx,dc=vip/admin):管理区出现 → OU(devops/test)/用户列表(OpenLDAP 过滤器)→ 批量导入 → logan LDAP 登录复测
- 全量门禁(tsc/build/28 测试)后提交
## 3. 消灭「框中框」与双滚动(14 + 1 处调用点机械清理)
- 各 ModalOverlay 调用点删除内层 `bg/border/rounded/shadow/p-6` 卡片包装,内容直挂(保留各自布局)
- 删除内层第二个 `max-h/overflow-y-auto`(BatchImportModal/TicketDetailDialog/InstanceGroupPage/UserDetailModal)→ 单滚动条
- `EditInstanceDialog` 迁到 ModalOverlay(同体系,获得 ESC/动画/portal)
不改 aiops 项目;测试数据仍在独立临时库,结束清理。
## 4. 视觉统一(按指南 06 数值层)
- 弹窗圆角统一 rounded-xl(12px);阴影单层 shadow-2xl、去边框(描边/阴影二选一)
- 标题统一 text-base font-semibold;关闭钮统一形态
- footer 按钮统一 **dg-btn 体系**(`dg-btn-sm dg-btn-secondary` 取消 / `dg-btn-primary` 主操作 / `dg-btn-danger` 危险),替换裸 button 四种写法;主色统一 var(--dg-blue)(ResetPasswordModal 的 yellow-500、LDAP 弹窗的 emerald-500 一并收敛);宽度归档 sm/md/lg/xl 四档(内容宽度语义保留,消除随意值)
## 5. 死代码清理
- 验证 LdapCreateOuDialog/LdapAddUserDialog/LdapAccountTestDialog 无引用后删除;BatchImportModal 残留的建 OU 嵌套状态/函数清除
## 6. 验证
- tsc/build/audit:pages 全绿
- 浏览器实测 6 类弹框:用户新建/编辑(rbac)、批量导入、实例编辑(EditInstanceDialog)、工单详情+内嵌快捷审批(验证 ESC 不再连锁、z-index 压过侧栏)、Redis 行编辑、各页删除确认——确认单卡片/单滚动/统一关闭钮与按钮/动画一致
- 提交并推送远程