212 lines
10 KiB
Markdown
212 lines
10 KiB
Markdown
---
|
||
name: message-notification-components
|
||
overview: 在 fms-vue 组件库新增 Message(轻提示)与 Notification(通知)两套组件,提供命令式全局 API(Message.success/error/...、Notification.open/close/closeAll)并保留可声明式使用的组件,遵循现有组件库规范(scoped SCSS + index.scss 变量、lucide 图标、Teleport/Transition 复用),最后在 App.vue 加演示入口并用 Playwright(端口 5082)实测。
|
||
design:
|
||
architecture:
|
||
framework: vue
|
||
component: shadcn
|
||
styleKeywords:
|
||
- 简洁卡片
|
||
- 轻提示
|
||
- 右上角通知
|
||
- 柔和阴影
|
||
- 类型配色
|
||
- 平滑过渡
|
||
fontSystem:
|
||
fontFamily: PingFang SC
|
||
heading:
|
||
size: 20px
|
||
weight: 600
|
||
subheading:
|
||
size: 15px
|
||
weight: 500
|
||
body:
|
||
size: 14px
|
||
weight: 400
|
||
colorSystem:
|
||
primary:
|
||
- "#2563EB"
|
||
- "#16A34A"
|
||
- "#D97706"
|
||
- "#DC2626"
|
||
background:
|
||
- "#FFFFFF"
|
||
- "#F8FAFC"
|
||
text:
|
||
- "#1E293B"
|
||
- "#64748B"
|
||
functional:
|
||
- "#16A34A"
|
||
- "#DC2626"
|
||
- "#D97706"
|
||
- "#2563EB"
|
||
todos:
|
||
- id: explore-export
|
||
content: 用 [subagent:code-explorer] 确认 ui 导出方式与 App.vue 演示结构
|
||
status: completed
|
||
- id: build-message
|
||
content: 实现 message.vue、message-manager.js、index.scss
|
||
status: completed
|
||
dependencies:
|
||
- explore-export
|
||
- id: build-notification
|
||
content: 实现 notification.vue、notification-manager.js、index.scss
|
||
status: completed
|
||
dependencies:
|
||
- explore-export
|
||
- id: app-demo
|
||
content: 在 App.vue 新增 Message/Notification 演示区块
|
||
status: completed
|
||
dependencies:
|
||
- build-message
|
||
- build-notification
|
||
- id: verify-playwright
|
||
content: 用 [skill:playwright-cli] 在 5082 端口验证显示/消失/关闭/堆叠
|
||
status: completed
|
||
dependencies:
|
||
- app-demo
|
||
- id: lint-check
|
||
content: 运行 oxlint 确认新增文件无错误
|
||
status: completed
|
||
dependencies:
|
||
- app-demo
|
||
---
|
||
|
||
## 用户需求
|
||
|
||
在 fms-vue 组件库中新增 Message(轻提示)与 Notification(通知)两套组件,采用命令式 API 为主、声明式组件为辅的设计。
|
||
|
||
## 产品概述
|
||
|
||
- Message:页面顶部居中的轻量级反馈提示,用于操作结果反馈,自动消失,不打断用户操作。
|
||
- Notification:页面右上角的通知卡片,用于承载较丰富的信息(标题 + 描述),支持手动关闭与自动消失。
|
||
- 两者均支持全局命令式调用(Message.success / Notification.open),同时保留 `<Message>` / `<Notification>` 组件供声明式使用。
|
||
|
||
## 核心功能
|
||
|
||
- 命令式入口:Message.success/error/warning/info(content, options);Notification.open(options);均返回可关闭的实例句柄。
|
||
- 消息类型:info / success / warning / error 四种,复用 lucide 图标与现有主题 CSS 变量配色。
|
||
- 自动关闭:Message 默认 3000ms,Notification 默认 4500ms;duration 为 0 时不自动关闭。
|
||
- 手动关闭:Notification 提供关闭按钮;Message 在 hover 时可常驻并提供关闭按钮(可选)。
|
||
- 堆叠与重排:多条消息纵向堆叠(Message 顶部居中、Notification 右上角),关闭后后续项平滑上移。
|
||
- App.vue 演示区块:提供按钮触发各类型,便于人工与 Playwright 验证。
|
||
- 严格遵循现有项目规范(scoped SCSS + @use 模式、无 placeholder 逻辑、复用 Teleport/Transition 模式)。
|
||
|
||
## 技术栈选择
|
||
|
||
- 框架:Vue 3(SFC + `<script setup>`),与现有组件一致
|
||
- 样式:SCSS(`scoped` + `@use './index.scss'`),复用现有 CSS 变量与主题体系
|
||
- 图标:`@lucide/vue`(已引入),复用 CheckCircle2 / AlertCircle / Info / X 等
|
||
- 浮层挂载:`Teleport to="body"` + `Transition`,参考 Popover 模式但采用 `fixed` 固定定位(不跟随触发器)
|
||
|
||
## 实现方案
|
||
|
||
### 总体策略
|
||
|
||
采用「单例容器 + 程序化挂载」的命令式方案:每个管理器(message-manager / notification-manager)在首次调用时创建一个挂在 `document.body` 的容器组件(用 `createVNode` + `render`),容器内部用响应式数组维护当前活跃条目,新增时 push、关闭时移除并播放退场动画后卸载。组件本身(`message.vue` / `notification.vue`)作为单条目渲染单元,既被管理器内部使用,也可被外部声明式引用。
|
||
|
||
### 关键技术决策
|
||
|
||
1. **单例容器 vs 每次新建**:单例避免重复创建 DOM 与监听器,降低开销;容器组件统一管理 Transition 与堆叠计算。
|
||
2. **fixed 定位而非 Popover 定位逻辑**:Message/Notification 不依赖触发元素,使用 CSS `position: fixed` + 居中/右上角偏移即可,无需引入 position.js 计算,减少依赖与复杂度。
|
||
3. **id 句柄关闭**:每条目生成唯一 id,命令式调用返回 `{ close }`,`Notification.close(id)` / `closeAll` 通过 id 过滤数组实现。
|
||
4. **自动关闭计时器**:在条目组件内用 `setTimeout`,`onBeforeUnmount` 清理;duration<=0 不启用。Hover 暂停(Notification 可选)提升可用性。
|
||
5. **堆叠重排**:依赖 Vue `<TransitionGroup>` 的 move 过渡实现关闭后其余项平滑位移,避免手动计算 top。
|
||
|
||
### 性能与可靠性
|
||
|
||
- 单例容器,全局仅 1 个监听器集合;条目数量受控(可设 maxCount 限制,超出时移除最早项)。
|
||
- 计时器在卸载时清理,防止内存泄漏;`render(null)` 在容器无条目且长时间空闲时可销毁(可选,初版保留单例)。
|
||
- 命令式 API 与组件 props 共用同一套类型定义,保证一致性。
|
||
|
||
## 实现注意事项
|
||
|
||
- 严格沿用现有组件 SFC 结构:`<style scoped lang="scss"> @use './index.scss'`,不写内联 style。
|
||
- 配色复用现有 CSS 变量(如 `--fms-text-secondary`、主色变量),接入 ColorThemePicker 主题体系,不硬编码颜色。
|
||
- **不得引入任何 placeholder 相关逻辑**(遵循近期规范清理结果)。
|
||
- 图标复用 `@lucide/vue`,不新增图标依赖。
|
||
- 过渡动画命名约定风格与 `popover` transition 一致(如 `message-fade`、`notification-slide`)。
|
||
- 容器设置 `pointer-events: none`,子项 `pointer-events: auto`,避免遮挡页面交互。
|
||
|
||
## 架构设计
|
||
|
||
### 组件关系
|
||
|
||
```mermaid
|
||
graph TD
|
||
A[命令式 API] --> B[message-manager.js]
|
||
A --> C[notification-manager.js]
|
||
B --> D[MessageContainer 内部]
|
||
C --> E[NotificationContainer 内部]
|
||
D --> F[message.vue 单条]
|
||
E --> G[notification.vue 单条]
|
||
F --> H[(document.body 单例容器)]
|
||
G --> H
|
||
```
|
||
|
||
管理器负责创建/复用 body 上的单例容器,容器内用 `TransitionGroup` 渲染多个条目组件。
|
||
|
||
## 目录结构
|
||
|
||
```
|
||
src/components/ui/
|
||
├── message/
|
||
│ ├── message.vue # [NEW] 单条消息组件。props: type/content/duration/closable/onClose;渲染图标+文案+关闭按钮;内置自动关闭计时与淡出;可被声明式使用
|
||
│ ├── message-manager.js # [NEW] 命令式入口。单例容器 createVNode+render 挂 body;导出 success/error/warning/info/close;维护活跃列表与堆叠
|
||
│ └── index.scss # [NEW] 消息样式。fixed 顶部居中、pointer-events 处理、type 配色、message-fade 过渡
|
||
├── notification/
|
||
│ ├── notification.vue # [NEW] 单条通知组件。props: type/title/description/duration/closable/onClose;图标+标题+描述+关闭按钮;自动关闭+滑动退场
|
||
│ ├── notification-manager.js# [NEW] 命令式入口。open/close(id)/closeAll;右上角堆叠、TransitionGroup 重排
|
||
│ └── index.scss # [NEW] 通知样式。右侧卡片、阴影、type 配色、notification-slide 进场/退场
|
||
└── (导出) 若项目存在 barrel 文件则补充导出,否则 App.vue 直接按路径 import
|
||
src/App.vue # [MODIFY] 新增演示区块:按钮组触发各类型 Message/Notification,沿用现有演示布局风格
|
||
```
|
||
|
||
## 关键代码结构
|
||
|
||
管理器导出口(message-manager.js):
|
||
|
||
```js
|
||
export const Message = {
|
||
success: (content, opts) => open({ type: 'success', content, ...opts }),
|
||
error: (content, opts) => open({ type: 'error', content, ...opts }),
|
||
warning: (content, opts) => open({ type: 'warning', content, ...opts }),
|
||
info: (content, opts) => open({ type: 'info', content, ...opts }),
|
||
close: (id) => remove(id),
|
||
}
|
||
```
|
||
|
||
通知管理器导出口(notification-manager.js):
|
||
|
||
```js
|
||
export const Notification = {
|
||
open: (options) => open({ ...options }),
|
||
close: (id) => remove(id),
|
||
closeAll: () => clear(),
|
||
}
|
||
```
|
||
|
||
## 设计风格
|
||
|
||
沿用现有 fms-vue 组件库的简洁卡片风格,与 Button/Select 视觉体系保持一致。Message 为顶部居中的轻量胶囊/卡片提示,带左侧类型图标与柔和阴影;Notification 为右上角白色卡片,左侧类型色条+图标,标题加粗、描述次要色,右上角关闭按钮。整体采用现有主题 CSS 变量配色,支持明暗主题切换,过渡平滑(淡入下滑 / 滑出上移)。
|
||
|
||
## 页面区块(App.vue 演示)
|
||
|
||
- 顶部标题区块:说明 Message 与 Notification 演示区
|
||
- Message 触发区:四枚按钮(info/success/warning/error)触发对应轻提示
|
||
- Notification 触发区:按钮触发通知,并含「关闭全部」按钮
|
||
- 底部说明:调用方式代码示例(纯文本展示)
|
||
|
||
## Agent Extensions
|
||
|
||
### Skill
|
||
|
||
- **playwright-cli**
|
||
- Purpose: 在端口 5082 启动/复用 dev server 后,通过 Playwright 实测 Message/Notification 的显示、自动消失、手动关闭与多条堆叠顺序
|
||
- Expected outcome: 验证各类型元素出现、文案与 type class 正确、duration 后自动移除、关闭按钮可移除、连续触发堆叠顺序正确,输出断言结果
|
||
|
||
### SubAgent
|
||
|
||
- **code-explorer**
|
||
- Purpose: 在生成计划前确认 src/components/ui 是否存在 barrel 导出文件及 App.vue 现有演示区块结构,避免路径与风格冲突
|
||
- Expected outcome: 明确导出方式与 App.vue 插入位置,保证新增演示与现有布局一致 |