From 3d72fc0dcbac884bec464a7058c83ebaa1d0b815 Mon Sep 17 00:00:00 2001
From: Tevin <tingquanren@163.com>
Date: Mon, 13 Apr 2026 12:22:48 +0800
Subject: [PATCH] chore: 完成 implement-c-side-menu 归档的目录移动

---
 openspec/specs/side-menu/spec.md |   91 +++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 91 insertions(+), 0 deletions(-)

diff --git a/openspec/specs/side-menu/spec.md b/openspec/specs/side-menu/spec.md
new file mode 100644
index 0000000..d60069f
--- /dev/null
+++ b/openspec/specs/side-menu/spec.md
@@ -0,0 +1,91 @@
+# CSideMenu 组件规格说明
+
+## 1. 概述与范围
+
+本规格描述 `CSideMenu` 组件的技术契约:数据树、三级菜单、全局手风琴、响应式侧栏、antd `Layout.Sider` / `Menu` 的组合。
+
+- **依赖**:React、antd v6、`@ant-design/icons`
+- **范围**:侧栏容器、菜单渲染、遮罩
+- **非目标**:路由与子页实现、自定义滚动条
+
+---
+
+## 2. 数据模型
+
+### MenuTree(宿主传入)
+
+```typescript
+interface MenuItem {
+  key: string | number;      // 唯一标识
+  label: string;              // 显示文本
+  children?: MenuItem[];      // 子菜单
+  path?: string;              // 页面路径
+  pageName?: string;         // 页面名称
+  type?: 'chart' | 'setting' | 'folder' | 'file';  // 图标类型
+}
+
+interface MenuTree extends MenuItem {}
+```
+
+### 组件 Props
+
+```typescript
+interface CSideMenuProps {
+  title: string;                           // 顶区标题
+  tree?: MenuTree;                         // 合并后的菜单树
+  collapsed: boolean;                      // 是否收起
+  curActivePaneKey?: string | number;     // 当前选中键
+  panesOnShelf?: Array<{ key: string }>; // 已打开页签列表
+  onClickMenuItem: (item: MenuItem) => void;
+  onSetMenuCollapse: (collapsed: boolean | void) => void;
+}
+```
+
+---
+
+## 3. 组件行为
+
+### Requirement: 三级菜单树渲染
+组件 SHALL 从注入的 `tree` 数据结构渲染三级菜单树。结构为 `key > label > children > key > label > children`。每个节点 SHALL 包含 `id`、`name`、可选 `type` 字段。当节点包含非空 `children` 时,SHALL 渲染为 SubMenu;否则为叶子项。
+
+### Requirement: 全局手风琴展开
+当用户展开一个节点时,组件 SHALL 关闭之前展开的节点。全局最多同时只有一个展开分支。
+
+### Requirement: 响应式固定模式
+当视口宽度低于 `lg` 断点时(移动端),侧边栏 SHALL 进入固定模式,以 `position: fixed` 悬浮覆盖在内容之上。当菜单展开时 SHALL 显示背景遮罩,点击遮罩 SHALL 触发收起。PC 端不启用覆盖模式。
+
+### Requirement: 固定模式延迟导航
+在固定模式下,当用户点击叶子项时,组件 SHALL 先触发收起(`onSetMenuCollapse(true)`),然后在约 300ms 延迟后调用 `onClickMenuItem`,以避免动画闪烁。
+
+### Requirement: 菜单项点击回调
+当用户点击叶子菜单项时,组件 SHALL 调用 `onClickMenuItem`,传入完整的菜单项对象,至少包含 `id`、`name`、`path`、`pageName` 字段。
+
+### Requirement: 折叠状态回调
+组件 SHALL 支持 `onSetMenuCollapse` 的两种调用模式:boolean 参数(设置精确折叠状态)和无参调用(切换)。宿主应用 SHALL 处理这两种模式。
+
+### Requirement: 空树处理
+当注入的 `tree` 为空或 undefined 时,组件 SHALL 渲染标题区域和空菜单区域,且不抛出错误。
+
+### Requirement: 当前选中键高亮
+当 `curActivePaneKey` 与菜单节点的 `id` 或 `key` 匹配时,该节点 SHALL 显示选中样式。当叶子项被选中时,其所属 SubMenu SHALL 显示子树选中样式。
+
+### Requirement: 已打开标签指示器
+当 `panesOnShelf` 中的某个条目的 `key` 与叶子节点的 `id` 匹配时,该叶子 SHALL 显示"已打开"指示器样式。
+
+---
+
+## 4. 图标映射
+
+| type 值 | 图标 |
+|---------|------|
+| chart | PieChartOutlined |
+| setting | SettingOutlined |
+| folder | FolderOutlined |
+| file (默认) | FileOutlined |
+
+---
+
+## 5. 响应式断点
+
+- **PC 端**:`breakpoint="lg"` (992px) 以上,使用 antd Layout.Sider
+- **移动端**:992px 及以下,使用固定定位覆盖层 + 遮罩

--
Gitblit v1.9.1