20260823210241
This commit is contained in:
1 parent
5ff4583aeb
commit
f4c7413dc6
2766 files changed
+1836409
-94689
No files matched your search
@@ -0,0 +1,411 @@
|
||||
# 反馈组件
|
||||
|
||||
<cite>
|
||||
**本文引用的文件**
|
||||
- [modal.vue](file://fms-vue/src/components/ui/modal/modal.vue)
|
||||
- [drawer.vue](file://fms-vue/src/components/ui/drawer/drawer.vue)
|
||||
- [message.vue](file://fms-vue/src/components/ui/message/message.vue)
|
||||
- [notification.vue](file://fms-vue/src/components/ui/notification/notification.vue)
|
||||
- [popover.vue](file://fms-vue/src/components/ui/popover/popover.vue)
|
||||
- [tooltip.vue](file://fms-vue/src/components/ui/tooltip/tooltip.vue)
|
||||
- [focus.js](file://fms-vue/src/components/ui/utils/focus.js)
|
||||
- [scroll.js](file://fms-vue/src/components/ui/utils/scroll.js)
|
||||
- [drag.js](file://fms-vue/src/components/ui/utils/drag.js)
|
||||
- [position.js](file://fms-vue/src/components/ui/utils/position.js)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
3. [核心组件](#核心组件)
|
||||
4. [架构总览](#架构总览)
|
||||
5. [详细组件分析](#详细组件分析)
|
||||
6. [依赖关系分析](#依赖关系分析)
|
||||
7. [性能与可访问性](#性能与可访问性)
|
||||
8. [异步操作与错误处理](#异步操作与错误处理)
|
||||
9. [动画、定位与多语言](#动画定位与多语言)
|
||||
10. [故障排查](#故障排查)
|
||||
11. [结论](#结论)
|
||||
|
||||
## 简介
|
||||
本章节面向 FMS 前端组件库中的“用户反馈”类组件,涵盖模态框(Modal)、抽屉(Drawer)、消息提示(Message)、通知(Notification)、气泡卡片(Popover)与工具提示(Tooltip)。文档从设计理念、触发机制、生命周期管理、状态控制、选择策略、交互原则、异步反馈与错误处理、动画效果、定位算法、多语言支持等维度进行系统化说明,帮助开发者在不同场景下正确选用并组合这些组件。
|
||||
|
||||
## 项目结构
|
||||
反馈组件集中在 fms-vue 的 ui 目录下,按功能划分:
|
||||
- 弹层容器与交互:modal、drawer、popover、tooltip
|
||||
- 全局轻提示与通知:message、notification
|
||||
- 通用能力:focus(焦点陷阱)、scroll(滚动锁)、drag(拖拽/缩放)、position(浮层定位)
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "弹层与浮层"
|
||||
M["Modal"]
|
||||
D["Drawer"]
|
||||
P["Popover"]
|
||||
T["Tooltip"]
|
||||
end
|
||||
subgraph "全局反馈"
|
||||
MSG["Message"]
|
||||
NTF["Notification"]
|
||||
end
|
||||
subgraph "通用能力"
|
||||
F["focus.js"]
|
||||
S["scroll.js"]
|
||||
G["drag.js"]
|
||||
POS["position.js"]
|
||||
end
|
||||
M --> F
|
||||
M --> S
|
||||
M --> G
|
||||
D --> F
|
||||
D --> S
|
||||
D --> G
|
||||
P --> POS
|
||||
T --> P
|
||||
MSG --> |渲染| MSG
|
||||
NTF --> |渲染| NTF
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [modal.vue:1-291](file://fms-vue/src/components/ui/modal/modal.vue#L1-L291)
|
||||
- [drawer.vue:1-219](file://fms-vue/src/components/ui/drawer/drawer.vue#L1-L219)
|
||||
- [popover.vue:1-294](file://fms-vue/src/components/ui/popover/popover.vue#L1-L294)
|
||||
- [tooltip.vue:1-59](file://fms-vue/src/components/ui/tooltip/tooltip.vue#L1-L59)
|
||||
- [message.vue:1-77](file://fms-vue/src/components/ui/message/message.vue#L1-L77)
|
||||
- [notification.vue:1-82](file://fms-vue/src/components/ui/notification/notification.vue#L1-L82)
|
||||
- [focus.js:1-63](file://fms-vue/src/components/ui/utils/focus.js#L1-L63)
|
||||
- [scroll.js:1-42](file://fms-vue/src/components/ui/utils/scroll.js#L1-L42)
|
||||
- [drag.js:1-202](file://fms-vue/src/components/ui/utils/drag.js#L1-L202)
|
||||
- [position.js:1-99](file://fms-vue/src/components/ui/utils/position.js#L1-L99)
|
||||
|
||||
章节来源
|
||||
- [modal.vue:1-291](file://fms-vue/src/components/ui/modal/modal.vue#L1-L291)
|
||||
- [drawer.vue:1-219](file://fms-vue/src/components/ui/drawer/drawer.vue#L1-L219)
|
||||
- [popover.vue:1-294](file://fms-vue/src/components/ui/popover/popover.vue#L1-L294)
|
||||
- [tooltip.vue:1-59](file://fms-vue/src/components/ui/tooltip/tooltip.vue#L1-L59)
|
||||
- [message.vue:1-77](file://fms-vue/src/components/ui/message/message.vue#L1-L77)
|
||||
- [notification.vue:1-82](file://fms-vue/src/components/ui/notification/notification.vue#L1-L82)
|
||||
- [focus.js:1-63](file://fms-vue/src/components/ui/utils/focus.js#L1-L63)
|
||||
- [scroll.js:1-42](file://fms-vue/src/components/ui/utils/scroll.js#L1-L42)
|
||||
- [drag.js:1-202](file://fms-vue/src/components/ui/utils/drag.js#L1-L202)
|
||||
- [position.js:1-99](file://fms-vue/src/components/ui/utils/position.js#L1-L99)
|
||||
|
||||
## 核心组件
|
||||
- Modal:居中或顶部对齐的对话框,支持受控/非受控开关、遮罩关闭、Esc 关闭、标题/内容/底部插槽、确定/取消按钮、加载态、全屏切换、拖拽与四边缩放、焦点陷阱与滚动锁定、ARIA 无障碍。
|
||||
- Drawer:贴边滑出面板,支持四方向 placement、尺寸可调、三段式布局(header/body/footer)、焦点与滚动管理。
|
||||
- Message:页面顶部居中的轻量提示,自动消失,支持类型与手动关闭。
|
||||
- Notification:右上角通知卡片,承载标题+描述,支持手动关闭与自动消失、堆叠重排。
|
||||
- Popover:基于触发器的浮层,支持多种触发方式、智能定位(flip/shift)、箭头、跟随宽度等。
|
||||
- Tooltip:对 Popover 的 hover 薄封装,提供轻量文本提示。
|
||||
|
||||
章节来源
|
||||
- [modal.vue:1-291](file://fms-vue/src/components/ui/modal/modal.vue#L1-L291)
|
||||
- [drawer.vue:1-219](file://fms-vue/src/components/ui/drawer/drawer.vue#L1-L219)
|
||||
- [message.vue:1-77](file://fms-vue/src/components/ui/message/message.vue#L1-L77)
|
||||
- [notification.vue:1-82](file://fms-vue/src/components/ui/notification/notification.vue#L1-L82)
|
||||
- [popover.vue:1-294](file://fms-vue/src/components/ui/popover/popover.vue#L1-L294)
|
||||
- [tooltip.vue:1-59](file://fms-vue/src/components/ui/tooltip/tooltip.vue#L1-L59)
|
||||
|
||||
## 架构总览
|
||||
反馈组件采用“声明式组件 + 命令式管理器”的组合模式:
|
||||
- Modal/Drawer/Popover/Tooltip:以组件形式声明使用,内部通过 Teleport 挂载到 body,结合 Transition 实现动画;Modal/Drawer 共享 focus/scroll/drag 能力。
|
||||
- Message/Notification:提供命令式 API(如 success/open),在首次调用时创建单例容器挂载至 body,内部维护活跃条目数组并使用 TransitionGroup 完成堆叠与过渡。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant U as "业务代码"
|
||||
participant M as "Modal/Drawer"
|
||||
participant F as "focus.js"
|
||||
participant S as "scroll.js"
|
||||
participant G as "drag.js"
|
||||
U->>M : 打开(open=true)
|
||||
M->>S : lockScroll()
|
||||
M->>F : focusFirst(panelRef)
|
||||
M->>G : bindDrag/bindResize(可选)
|
||||
Note over M : 键盘监听/ESC关闭/焦点陷阱生效
|
||||
U->>M : 关闭(open=false)
|
||||
M->>F : trapFocus解除
|
||||
M->>G : destroy()
|
||||
M->>S : unlockScroll()
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [modal.vue:118-198](file://fms-vue/src/components/ui/modal/modal.vue#L118-L198)
|
||||
- [drawer.vue:106-154](file://fms-vue/src/components/ui/drawer/drawer.vue#L106-L154)
|
||||
- [focus.js:22-63](file://fms-vue/src/components/ui/utils/focus.js#L22-L63)
|
||||
- [scroll.js:15-42](file://fms-vue/src/components/ui/utils/scroll.js#L15-L42)
|
||||
- [drag.js:26-111](file://fms-vue/src/components/ui/utils/drag.js#L26-L111)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### Modal 模态框
|
||||
- 触发机制:v-model:open 受控或 defaultOpen 非受控;支持遮罩点击、Esc、关闭按钮、取消按钮关闭;confirmLoading 期间阻止关闭。
|
||||
- 生命周期:打开时记录触发元素、锁定滚动、聚焦首项、绑定键盘事件、启用拖拽/缩放;关闭时恢复滚动、解绑事件、还原焦点。
|
||||
- 状态控制:isOpen 计算属性统一受控/非受控;panelStyle 根据是否缩放决定宽高;isFullscreen 控制全屏。
|
||||
- 可访问性:role=dialog、aria-modal、aria-labelledby 关联标题,关闭按钮 aria-label。
|
||||
- 交互增强:标题栏拖拽移动、四边缩放手柄、全屏切换。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start(["打开"]) --> Lock["锁定滚动"]
|
||||
Lock --> Focus["聚焦首项"]
|
||||
Focus --> Bind["绑定键盘/拖拽/缩放"]
|
||||
Bind --> Wait{"等待关闭"}
|
||||
Wait --> |Esc/遮罩/取消| Close["请求关闭"]
|
||||
Close --> Unlock["解锁滚动"]
|
||||
Unlock --> Restore["还原焦点"]
|
||||
Restore --> End(["结束"])
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [modal.vue:118-198](file://fms-vue/src/components/ui/modal/modal.vue#L118-L198)
|
||||
- [modal.vue:201-285](file://fms-vue/src/components/ui/modal/modal.vue#L201-L285)
|
||||
|
||||
章节来源
|
||||
- [modal.vue:1-291](file://fms-vue/src/components/ui/modal/modal.vue#L1-L291)
|
||||
- [focus.js:22-63](file://fms-vue/src/components/ui/utils/focus.js#L22-L63)
|
||||
- [scroll.js:15-42](file://fms-vue/src/components/ui/utils/scroll.js#L15-L42)
|
||||
- [drag.js:26-111](file://fms-vue/src/components/ui/utils/drag.js#L26-L111)
|
||||
|
||||
### Drawer 抽屉
|
||||
- 触发机制:placement 控制滑出方向(left/right/top/bottom),默认右侧;支持遮罩点击、Esc、关闭按钮关闭。
|
||||
- 生命周期:打开时锁定滚动、聚焦首项、绑定键盘事件、启用边缘缩放;关闭时恢复滚动、解绑事件、还原焦点。
|
||||
- 状态控制:isOpen 计算属性统一受控/非受控;panelStyle 根据方向与是否缩放决定 width/height。
|
||||
- 可访问性:role=dialog、aria-modal、aria-labelledby 关联标题,关闭按钮 aria-label。
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class Drawer {
|
||||
+open
|
||||
+defaultOpen
|
||||
+title
|
||||
+placement
|
||||
+width
|
||||
+height
|
||||
+mask
|
||||
+maskClosable
|
||||
+keyboard
|
||||
+closable
|
||||
+resizable
|
||||
+setOpen(value)
|
||||
+requestClose()
|
||||
}
|
||||
Drawer --> Focus : "focusFirst/trapFocus"
|
||||
Drawer --> Scroll : "lock/unlock"
|
||||
Drawer --> Drag : "bindResize"
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [drawer.vue:1-219](file://fms-vue/src/components/ui/drawer/drawer.vue#L1-L219)
|
||||
- [focus.js:22-63](file://fms-vue/src/components/ui/utils/focus.js#L22-L63)
|
||||
- [scroll.js:15-42](file://fms-vue/src/components/ui/utils/scroll.js#L15-L42)
|
||||
- [drag.js:130-202](file://fms-vue/src/components/ui/utils/drag.js#L130-L202)
|
||||
|
||||
章节来源
|
||||
- [drawer.vue:1-219](file://fms-vue/src/components/ui/drawer/drawer.vue#L1-L219)
|
||||
- [focus.js:22-63](file://fms-vue/src/components/ui/utils/focus.js#L22-L63)
|
||||
- [scroll.js:15-42](file://fms-vue/src/components/ui/utils/scroll.js#L15-L42)
|
||||
- [drag.js:130-202](file://fms-vue/src/components/ui/utils/drag.js#L130-L202)
|
||||
|
||||
### Message 消息提示
|
||||
- 触发机制:通常由命令式 API 调用(见计划文档),组件本身支持 props 配置 type/content/duration/closable。
|
||||
- 生命周期:mounted 启动自动关闭计时器,beforeUnmount 清理计时器;close 事件交由容器移除条目。
|
||||
- 状态控制:duration<=0 不自动关闭;closable 显示关闭按钮。
|
||||
- 可访问性:role="alert",图标与文案清晰表达类型。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant C as "容器"
|
||||
participant M as "Message"
|
||||
C->>M : 渲染条目(id,type,content,duration,closable)
|
||||
M->>M : onMounted -> startTimer()
|
||||
alt 自动关闭
|
||||
M-->>C : emit('close') after duration
|
||||
else 手动关闭
|
||||
C->>M : 点击关闭
|
||||
M-->>C : emit('close')
|
||||
end
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [message.vue:1-77](file://fms-vue/src/components/ui/message/message.vue#L1-L77)
|
||||
|
||||
章节来源
|
||||
- [message.vue:1-77](file://fms-vue/src/components/ui/message/message.vue#L1-L77)
|
||||
|
||||
### Notification 通知
|
||||
- 触发机制:命令式 open(options),组件支持 title/description/duration/closable。
|
||||
- 生命周期:同 Message,自动关闭计时器在 mounted 启动、卸载时清理。
|
||||
- 状态控制:duration<=0 不自动关闭;closable 显示关闭按钮。
|
||||
- 可访问性:role="alert",标题与描述层次清晰。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant C as "容器"
|
||||
participant N as "Notification"
|
||||
C->>N : 渲染条目(id,type,title,description,duration,closable)
|
||||
N->>N : onMounted -> startTimer()
|
||||
alt 自动关闭
|
||||
N-->>C : emit('close') after duration
|
||||
else 手动关闭
|
||||
C->>N : 点击关闭
|
||||
N-->>C : emit('close')
|
||||
end
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [notification.vue:1-82](file://fms-vue/src/components/ui/notification/notification.vue#L1-L82)
|
||||
|
||||
章节来源
|
||||
- [notification.vue:1-82](file://fms-vue/src/components/ui/notification/notification.vue#L1-L82)
|
||||
|
||||
### Popover 气泡卡片
|
||||
- 触发机制:trigger 支持 click/hover/focus/contextmenu/manual;hover 时通过延迟定时器避免误触。
|
||||
- 定位算法:computePosition 基于期望 placement,计算初始坐标,溢出时 flip 翻转主轴方向,再 shift 约束回视口内;支持箭头与跟随触发器宽度。
|
||||
- 生命周期:打开时注册全局 pointerdown/keydown/resize/scroll 监听,nextTick 后计算位置并启动 ResizeObserver;关闭时清理所有监听与定时器。
|
||||
- 可访问性:hover 触发时 contentRole 为 tooltip,其余为 dialog。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["打开"] --> B["nextTick 计算位置"]
|
||||
B --> C{"溢出?"}
|
||||
C -- 是 --> D["flip 翻转主轴"]
|
||||
D --> E{"仍溢出?"}
|
||||
E -- 是 --> F["shift 约束回视口"]
|
||||
E -- 否 --> G["应用位置"]
|
||||
C -- 否 --> G
|
||||
G --> H["监听 resize/scroll 更新"]
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [popover.vue:94-148](file://fms-vue/src/components/ui/popover/popover.vue#L94-L148)
|
||||
- [position.js:76-99](file://fms-vue/src/components/ui/utils/position.js#L76-L99)
|
||||
|
||||
章节来源
|
||||
- [popover.vue:1-294](file://fms-vue/src/components/ui/popover/popover.vue#L1-L294)
|
||||
- [position.js:1-99](file://fms-vue/src/components/ui/utils/position.js#L1-L99)
|
||||
|
||||
### Tooltip 工具提示
|
||||
- 触发机制:固定 trigger=hover,其他行为(定位、Teleport、延迟、Esc 关闭)由 Popover 提供。
|
||||
- 内容优先级:content 纯文本与 #content 插槽同时存在时,插槽优先。
|
||||
|
||||
章节来源
|
||||
- [tooltip.vue:1-59](file://fms-vue/src/components/ui/tooltip/tooltip.vue#L1-L59)
|
||||
- [popover.vue:1-294](file://fms-vue/src/components/ui/popover/popover.vue#L1-L294)
|
||||
|
||||
## 依赖关系分析
|
||||
- Modal/Drawer 依赖 focus.js(焦点陷阱)、scroll.js(滚动锁)、drag.js(拖拽/缩放)。
|
||||
- Popover/Tooltip 依赖 position.js(定位算法)。
|
||||
- Message/Notification 作为单条渲染单元,被各自管理器(计划文档中定义)在 body 上以单例容器管理,使用 TransitionGroup 完成堆叠与过渡。
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
Modal --> Focus
|
||||
Modal --> Scroll
|
||||
Modal --> Drag
|
||||
Drawer --> Focus
|
||||
Drawer --> Scroll
|
||||
Drawer --> Drag
|
||||
Popover --> Position
|
||||
Tooltip --> Popover
|
||||
Message --> |被容器管理| Message
|
||||
Notification --> |被容器管理| Notification
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [modal.vue:1-291](file://fms-vue/src/components/ui/modal/modal.vue#L1-L291)
|
||||
- [drawer.vue:1-219](file://fms-vue/src/components/ui/drawer/drawer.vue#L1-L219)
|
||||
- [popover.vue:1-294](file://fms-vue/src/components/ui/popover/popover.vue#L1-L294)
|
||||
- [tooltip.vue:1-59](file://fms-vue/src/components/ui/tooltip/tooltip.vue#L1-L59)
|
||||
- [focus.js:1-63](file://fms-vue/src/components/ui/utils/focus.js#L1-L63)
|
||||
- [scroll.js:1-42](file://fms-vue/src/components/ui/utils/scroll.js#L1-L42)
|
||||
- [drag.js:1-202](file://fms-vue/src/components/ui/utils/drag.js#L1-L202)
|
||||
- [position.js:1-99](file://fms-vue/src/components/ui/utils/position.js#L1-L99)
|
||||
|
||||
章节来源
|
||||
- [modal.vue:1-291](file://fms-vue/src/components/ui/modal/modal.vue#L1-L291)
|
||||
- [drawer.vue:1-219](file://fms-vue/src/components/ui/drawer/drawer.vue#L1-L219)
|
||||
- [popover.vue:1-294](file://fms-vue/src/components/ui/popover/popover.vue#L1-L294)
|
||||
- [tooltip.vue:1-59](file://fms-vue/src/components/ui/tooltip/tooltip.vue#L1-L59)
|
||||
- [focus.js:1-63](file://fms-vue/src/components/ui/utils/focus.js#L1-L63)
|
||||
- [scroll.js:1-42](file://fms-vue/src/components/ui/utils/scroll.js#L1-L42)
|
||||
- [drag.js:1-202](file://fms-vue/src/components/ui/utils/drag.js#L1-L202)
|
||||
- [position.js:1-99](file://fms-vue/src/components/ui/utils/position.js#L1-L99)
|
||||
|
||||
## 性能与可访问性
|
||||
- 性能
|
||||
- Modal/Drawer:仅在打开期间注册全局键盘事件与拖拽/缩放监听,关闭/卸载时彻底清理;Transition 仅使用 opacity/transform 等低成本属性。
|
||||
- Popover:使用 requestAnimationFrame 合并高频滚动/缩放更新;ResizeObserver 观察浮层尺寸变化;hover 触发使用延迟定时器减少抖动。
|
||||
- Message/Notification:单例容器,条目数量受控;计时器在卸载时清理,避免内存泄漏。
|
||||
- 可访问性
|
||||
- Modal/Drawer:role=dialog、aria-modal、aria-labelledby 关联标题,关闭按钮具备 aria-label;焦点陷阱确保 Tab 循环。
|
||||
- Popover:hover 触发时 contentRole 为 tooltip,其余为 dialog;箭头与定位保证信息可读。
|
||||
- Message/Notification:role="alert",明确语义。
|
||||
|
||||
章节来源
|
||||
- [modal.vue:118-198](file://fms-vue/src/components/ui/modal/modal.vue#L118-L198)
|
||||
- [drawer.vue:106-154](file://fms-vue/src/components/ui/drawer/drawer.vue#L106-L154)
|
||||
- [popover.vue:212-244](file://fms-vue/src/components/ui/popover/popover.vue#L212-L244)
|
||||
- [message.vue:34-56](file://fms-vue/src/components/ui/message/message.vue#L34-L56)
|
||||
- [notification.vue:36-58](file://fms-vue/src/components/ui/notification/notification.vue#L36-L58)
|
||||
|
||||
## 异步操作与错误处理
|
||||
- 异步操作反馈
|
||||
- Modal 确定按钮 loading 态(confirmLoading):在加载中禁止重复提交与关闭,避免打断异步流程。
|
||||
- Message/Notification:自动关闭时长可通过 duration 配置;0 表示不自动关闭,适合需要用户确认的错误提示。
|
||||
- 错误处理
|
||||
- 全局键盘事件与拖拽/缩放监听均在打开时注册、关闭/卸载时清理,防止残留导致异常。
|
||||
- 滚动锁计数式管理,支持多层弹窗嵌套,最后一个关闭才恢复滚动,避免样式错乱。
|
||||
- 计时器在 beforeUnmount 清理,避免组件销毁后回调引发异常。
|
||||
|
||||
章节来源
|
||||
- [modal.vue:90-104](file://fms-vue/src/components/ui/modal/modal.vue#L90-L104)
|
||||
- [modal.vue:128-198](file://fms-vue/src/components/ui/modal/modal.vue#L128-L198)
|
||||
- [drawer.vue:91-154](file://fms-vue/src/components/ui/drawer/drawer.vue#L91-L154)
|
||||
- [message.vue:34-56](file://fms-vue/src/components/ui/message/message.vue#L34-L56)
|
||||
- [notification.vue:36-58](file://fms-vue/src/components/ui/notification/notification.vue#L36-L58)
|
||||
- [scroll.js:15-42](file://fms-vue/src/components/ui/utils/scroll.js#L15-L42)
|
||||
|
||||
## 动画、定位与多语言
|
||||
- 动画效果
|
||||
- Modal:遮罩淡入/淡出,面板缩放进入/退出;支持 prefers-reduced-motion 降级。
|
||||
- Drawer:遮罩淡入/淡出,面板按方向平移滑入/滑出。
|
||||
- Popover/Tooltip:使用 Transition 名称与 CSS 变量控制过渡。
|
||||
- Message/Notification:单条过渡与 TransitionGroup 重排,实现平滑堆叠与退场。
|
||||
- 定位算法
|
||||
- Popover 使用 computePosition:先按期望 placement 计算坐标,溢出则 flip 翻转主轴方向,再 shift 约束回视口内;支持 offset 与箭头吸附。
|
||||
- 多语言支持
|
||||
- 组件文案(如 Modal 的 okText/cancelText、Drawer 的关闭按钮标签)通过 props 或插槽注入,便于接入 i18n 系统;计划文档指出复用 lucide 图标与主题变量,未硬编码颜色与文案。
|
||||
|
||||
章节来源
|
||||
- [modal.vue:201-285](file://fms-vue/src/components/ui/modal/modal.vue#L201-L285)
|
||||
- [drawer.vue:157-213](file://fms-vue/src/components/ui/drawer/drawer.vue#L157-L213)
|
||||
- [popover.vue:247-289](file://fms-vue/src/components/ui/popover/popover.vue#L247-L289)
|
||||
- [tooltip.vue:27-54](file://fms-vue/src/components/ui/tooltip/tooltip.vue#L27-L54)
|
||||
- [position.js:76-99](file://fms-vue/src/components/ui/utils/position.js#L76-L99)
|
||||
|
||||
## 故障排查
|
||||
- 焦点丢失或无法关闭
|
||||
- 检查是否在打开时成功执行 focusFirst 与 trapFocus;确认 panelRef 已渲染且可聚焦。
|
||||
- 确认 Esc 键监听已绑定且未被 preventDefault 拦截。
|
||||
- 滚动异常
|
||||
- 检查 lockScroll/unlockScroll 是否成对调用;多个弹窗嵌套时确保计数归零才恢复滚动。
|
||||
- 浮层遮挡或错位
|
||||
- 检查 Popover 的 placement、offset 与 followTriggerWidth;确认 computePosition 返回值与 floatStyle 应用正确。
|
||||
- 计时器未清理
|
||||
- 确认 message/notification 的 beforeUnmount 清理了 setTimeout;避免组件销毁后继续触发 close。
|
||||
|
||||
章节来源
|
||||
- [modal.vue:118-198](file://fms-vue/src/components/ui/modal/modal.vue#L118-L198)
|
||||
- [drawer.vue:106-154](file://fms-vue/src/components/ui/drawer/drawer.vue#L106-L154)
|
||||
- [popover.vue:212-244](file://fms-vue/src/components/ui/popover/popover.vue#L212-L244)
|
||||
- [message.vue:34-56](file://fms-vue/src/components/ui/message/message.vue#L34-L56)
|
||||
- [notification.vue:36-58](file://fms-vue/src/components/ui/notification/notification.vue#L36-L58)
|
||||
- [scroll.js:15-42](file://fms-vue/src/components/ui/utils/scroll.js#L15-L42)
|
||||
|
||||
## 结论
|
||||
FMS 反馈组件体系围绕“可控、可访问、可组合”的原则构建:Modal/Drawer 提供强交互弹层能力,Message/Notification 提供轻量全局反馈,Popover/Tooltip 提供灵活的上下文提示。通过统一的焦点与滚动管理、健壮的定位算法与低开销动画,满足复杂业务场景下的用户体验需求。建议在实际项目中:
|
||||
- 根据反馈强度与上下文选择合适组件(强中断用 Modal,弱提示用 Message/Notification,上下文提示用 Popover/Tooltip)。
|
||||
- 使用受控 open 状态管理生命周期,确保资源释放与状态一致。
|
||||
- 借助 props 与插槽注入多语言文案,保持视觉与交互一致性。
|
||||
- 在异步操作中合理使用 loading 与自动关闭策略,提升可用性。
|
||||
Reference in new issue
Block a user