Files

225 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Message 全局提示
## 概述
全局提示(Message)用于在页面顶部居中展示轻量级的操作反馈信息,属于非阻断性反馈组件。它在操作完成后自动出现在页面顶部,短暂停留后自动消失,不打断用户的操作流程。适用于表单提交成功/失败、异步操作状态提示、系统信息通知等场景。
AtomUI 的 `Message` 控件对标 [Ant Design 5.0 Message](https://ant.design/components/message-cn) 的设计规范,在 .NET / Avalonia 平台上提供一致的全局提示体验。
---
## 设计原理
### Ant Design 的全局提示设计哲学
Ant Design 对全局提示的定位是:**「全局展示操作反馈信息,居顶部居中显示并自动消失,是一种不打断用户操作的轻量级提示方式」**。它与 Notification(通知提醒)的关键区别在于:
| 特性 | Message(全局提示) | Notification(通知提醒) |
|---|---|---|
| **位置** | 页面顶部居中 | 页面四角 |
| **内容量** | 仅文本,轻量单行 | 标题 + 详细描述 + 操作按钮 |
| **交互** | 无交互,自动消失 | 可关闭、可操作 |
| **适用场景** | 操作反馈(成功/失败/警告) | 需要用户关注的复杂通知 |
**五种消息类型**(对应不同操作结果和语义):
| 类型 | 图标 | 设计意图 | 典型用途 |
|---|---|---|---|
| ℹ️ **Information** | `InfoCircleFilled`(蓝色) | 普通信息提示,中性语义 | 一般性操作提示、说明信息 |
| ✅ **Success** | `CheckCircleFilled`(绿色) | 操作成功确认 | 表单提交成功、保存完成 |
| ⚠️ **Warning** | `ExclamationCircleFilled`(黄色) | 警告提示,需要注意 | 操作有风险但可继续 |
| ❌ **Error** | `CloseCircleFilled`(红色) | 操作失败,需要关注 | 提交失败、网络错误 |
| 🔄 **Loading** | `LoadingOutlined`(蓝色旋转) | 异步操作进行中 | 数据加载、文件上传中 |
### AtomUI 的架构设计
AtomUI 的 Message 系统由三个核心组件协作完成:
```
WindowMessageManager(容器管理器)
├── 挂载在 TopLevel 的 AdornerLayer 上
├── 管理消息的生命周期(显示、自动关闭、最大数量控制)
└── MessageCard(单条消息卡片)× N
├── 图标(根据 MessageType 自动匹配)
├── 文本内容
└── 入场/出场动画(MoveUpIn / MoveUpOut)
```
**职责分离**:
- `IMessage` / `Message` — 数据模型,承载消息内容、类型、过期时间等信息
- `MessageCard` — 视觉控件,负责单条消息的渲染和动画
- `WindowMessageManager` — 容器管理器,负责消息的创建、排布和生命周期管理
---
## 功能详解
### 消息类型(MessageType)
消息类型通过 `MessageType` 枚举指定,每种类型会自动匹配对应的图标和颜色:
| 类型 | 默认图标 | 图标颜色来源 |
|---|---|---|
| `Information` | `InfoCircleFilled` | `SharedToken.ColorPrimary`(蓝色) |
| `Success` | `CheckCircleFilled` | `SharedToken.ColorSuccess`(绿色) |
| `Warning` | `ExclamationCircleFilled` | `SharedToken.ColorWarning`(黄色) |
| `Error` | `CloseCircleFilled` | `SharedToken.ColorError`(红色) |
| `Loading` | `LoadingOutlined`(旋转) | `SharedToken.ColorPrimary`(蓝色) |
### 自动关闭与过期时间
每条消息都有 `Expiration` 属性控制自动关闭时间:
- 默认值为 **5 秒**
- 设置为 `TimeSpan.Zero` 时消息不会自动关闭,需要手动调用 `Close()`
- 过期后通过 `DispatcherTimer.RunOnce` 触发关闭流程
### 最大显示数量
`WindowMessageManager.MaxItems` 控制同时可见的最大消息数量(默认为 5)。当新消息导致超出上限时,最早显示的消息会被自动关闭。
### 入场/出场动画
MessageCard 使用 `MoveUpIn` / `MoveUpOut` 动画实现消息的入场和出场效果:
- **入场**:从上方滑入 + 透明度从 0 到 1,使用 `CubicEaseOut` 缓动
- **出场**:向上滑出 + 透明度从 1 到 0,使用 `CubicEaseIn` 缓动
- 动画偏移量固定为 100px(`AnimationMaxOffsetY`)
- 动画时长由 `SharedToken.MotionDurationMid` 控制
- 可通过 `IsMotionEnabled = false` 禁用动画
### 关闭回调
通过 `Message` 构造函数的 `onClose` 参数传入关闭回调,当消息关闭(无论自动或手动)时执行。这支持链式消息——在一条消息关闭后立即显示下一条。
### 自定义图标
通过 `Message` 构造函数的 `icon` 参数可以传入自定义 `PathIcon`,覆盖默认的类型图标。
---
## 与 Ant Design 规范的对齐程度
| 特性 | Ant Design (React) | AtomUI (Avalonia) | 对齐情况 |
|---|---|---|---|
| 五种消息类型 | ✅ `info / success / warning / error / loading` | ✅ `MessageType` 枚举 | ✅ 完全对齐 |
| 顶部居中显示 | ✅ | ✅ `HorizontalAlignment="Center"` + `VerticalAlignment="Top"` | ✅ 完全对齐 |
| 自动关闭 | ✅ 默认 3 秒 | ✅ 默认 5 秒 | ⚠️ 默认时长不同 |
| 自定义图标 | ✅ `icon` 属性 | ✅ `Icon` 参数 | ✅ 对齐 |
| 关闭回调 | ✅ `onClose` | ✅ `OnClose` 回调 | ✅ 对齐 |
| Loading 类型 | ✅ | ✅ 旋转 `LoadingOutlined` 图标 | ✅ 完全对齐 |
| 自定义时长 | ✅ `duration` 参数 | ✅ `Expiration` 参数 | ✅ 对齐 |
| 最大显示数量 | ✅ `maxCount` | ✅ `MaxItems` 属性 | ✅ 对齐 |
| Promise 接口 | ✅ `message.open().then(...)` | ❌ 使用回调模式 | ⚠️ C# 无 Promise,使用 `OnClose` 回调 |
| 全局配置 | ✅ `message.config()` | ❌ 通过 `WindowMessageManager` 实例配置 | ⚠️ 实例级配置 vs 全局配置 |
| 更新消息内容 | ✅ 通过 `key` 更新 | ✅ `Message.Content` 支持 `INotifyPropertyChanged` | ⚠️ 机制不同但功能可实现 |
---
## 继承关系
### MessageCard
```
Avalonia.Controls.Primitives.TemplatedControl
└── AtomUI.Desktop.Controls.MessageCard
└── implements IMotionAwareControl
```
### WindowMessageManager
```
Avalonia.Controls.Primitives.TemplatedControl
└── AtomUI.Desktop.Controls.WindowMessageManager
├── implements IMessageManager
├── implements IMotionAwareControl
└── implements IDisposable
```
### Message(数据模型)
```
AtomUI.Desktop.Controls.Message
├── implements IMessage
└── implements INotifyPropertyChanged
```
**各层级职责划分:**
| 层级 | 提供的能力 |
|---|---|
| `TemplatedControl` | 模板化控件基础设施、`OnApplyTemplate`、`CornerRadius` 等 |
| `MessageCard` | 单条消息的视觉呈现:图标自动匹配、伪类管理、入场/出场动画 |
| `WindowMessageManager` | 消息容器管理:挂载到 TopLevel、消息排布、最大数量控制、自动关闭计时器 |
| `Message` | 消息数据模型:内容、类型、过期时间、关闭回调 |
**实现的接口:**
| 接口 | 定义位置 | 控件 | 作用 |
|---|---|---|---|
| `IMessage` | `AtomUI.Desktop.Controls` | 数据模型 | 定义消息数据契约(Content、Type、Expiration、OnClose、Icon) |
| `IMessageManager` | `AtomUI.Desktop.Controls` | WindowMessageManager | 定义消息管理器契约(`Show` 方法) |
| `IMotionAwareControl` | `AtomUI.Controls` | MessageCard / WindowMessageManager | 支持动画启用/禁用控制 |
| `INotifyPropertyChanged` | `System.ComponentModel` | Message | 支持属性变更通知(Content、Icon 可动态更新) |
| `IDisposable` | `System` | WindowMessageManager | 支持资源释放(从 AdornerLayer 卸载、清理事件订阅) |
---
## 源码位置
| 层级 | 文件路径 | 说明 |
|---|---|---|
| 数据接口 | `src/AtomUI.Desktop.Controls/Message/IMessage.cs` | IMessage 消息数据契约 |
| 管理器接口 | `src/AtomUI.Desktop.Controls/Message/IMessageManager.cs` | IMessageManager 管理器契约 |
| 数据模型 | `src/AtomUI.Desktop.Controls/Message/Message.cs` | Message 消息数据实现 |
| 消息卡片 | `src/AtomUI.Desktop.Controls/Message/MessageCard.cs` | MessageCard 视觉控件 |
| 消息类型枚举 | `src/AtomUI.Desktop.Controls/Message/MessageType.cs` | MessageType 枚举 |
| 伪类常量 | `src/AtomUI.Desktop.Controls/Message/MessageCardPseudoClass.cs` | 伪类常量定义 |
| 容器管理器 | `src/AtomUI.Desktop.Controls/Message/WindowMessageManager.cs` | WindowMessageManager 容器 |
| Token 定义 | `src/AtomUI.Desktop.Controls/Message/MessageToken.cs` | 组件级 Design Token |
| 消息卡片主题 | `src/AtomUI.Desktop.Controls/Message/Themes/MessageCardTheme.axaml` | MessageCard ControlTheme |
| 容器主题 | `src/AtomUI.Desktop.Controls/Message/Themes/WindowMessageManagerTheme.axaml` | WindowMessageManager ControlTheme |
| 主题注册 | `src/AtomUI.Desktop.Controls/Message/Themes/MessageThemes.axaml` | 主题合并注册 |
| 模板常量 | `src/AtomUI.Desktop.Controls/Message/Themes/MessageThemeConstants.cs` | 模板部件名称常量 |
| Gallery 示例 | `controlgallery/AtomUIGallery/ShowCases/Views/Feedback/MessageShowCase.axaml` | 使用范例 |
---
## 模板结构
### MessageCard 模板
MessageCard 使用 `MotionActor` 包裹以支持入场/出场动画:
```
MotionActor (PART_MotionActor) ← 动画容器
└── Border (PART_Frame) ← 主框架(背景、圆角、阴影)
└── DockPanel (PART_HeaderContainer) ← 内容布局容器
├── IconPresenter (PART_IconContent) ← 消息图标(DockPanel.Dock="Left")
└── SelectableTextBlock (PART_Message) ← 消息文本(可选中复制)
```
**设计理由:**
- **MotionActor 包裹**:使整个消息卡片可以参与 Move 动画,实现滑入/滑出效果
- **SelectableTextBlock**:使用可选择文本控件,用户可以选中并复制消息内容
- **DockPanel 布局**:图标靠左固定,文本填满剩余空间
### WindowMessageManager 模板
```
ReversibleStackPanel (PART_Items) ← 消息堆叠容器
├── MessageCard ← 消息卡片 1
├── MessageCard ← 消息卡片 2
└── ...
```
`ReversibleStackPanel` 支持 `ReverseOrder`,当 Position 为 `TopCenter` 时反转堆叠顺序,使最新消息出现在最上方。
### 模板部件常量
| 常量名 | 值 | 所属 | 说明 |
|---|---|---|---|
| `MessageCardThemeConstants.FramePart` | `"PART_Frame"` | MessageCard | 主框架边框 |
| `MessageCardThemeConstants.IconContentPart` | `"PART_IconContent"` | MessageCard | 图标展示器 |
| `MessageCardThemeConstants.HeaderContainerPart` | `"PART_HeaderContainer"` | MessageCard | 内容布局容器 |
| `MessageCardThemeConstants.MessagePart` | `"PART_Message"` | MessageCard | 消息文本 |
| `WindowMessageManagerThemeConstants.ItemsPart` | `"PART_Items"` | WindowMessageManager | 消息列表面板 |