20260823210241
This commit is contained in:
1 parent
5ff4583aeb
commit
f4c7413dc6
2766 files changed
+1836409
-94689
No files matched your search
@@ -0,0 +1,446 @@
|
||||
# UI基础组件
|
||||
|
||||
<cite>
|
||||
**本文引用的文件**
|
||||
- [Button.vue](file://fms-vue/src/components/ui/button/Button.vue)
|
||||
- [Input.vue](file://fms-vue/src/components/ui/input/Input.vue)
|
||||
- [Form.vue](file://fms-vue/src/components/ui/form/Form.vue)
|
||||
- [Checkbox.vue](file://fms-vue/src/components/ui/checkbox/Checkbox.vue)
|
||||
- [Select.vue](file://fms-vue/src/components/ui/select/Select.vue)
|
||||
- [date-picker.vue](file://fms-vue/src/components/ui/date/date-picker.vue)
|
||||
- [Modal.vue](file://fms-vue/src/components/ui/modal/Modal.vue)
|
||||
- [Drawer.vue](file://fms-vue/src/components/ui/drawer/Drawer.vue)
|
||||
- [index.js](file://fms-vue/src/theme/index.js)
|
||||
- [tokens.css](file://fms-vue/src/theme/tokens.css)
|
||||
- [package.json](file://fms-vue/package.json)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
3. [核心组件](#核心组件)
|
||||
4. [架构总览](#架构总览)
|
||||
5. [详细组件分析](#详细组件分析)
|
||||
6. [依赖分析](#依赖分析)
|
||||
7. [性能考虑](#性能考虑)
|
||||
8. [故障排查指南](#故障排查指南)
|
||||
9. [结论](#结论)
|
||||
10. [附录](#附录)
|
||||
|
||||
## 简介
|
||||
本文件为 FMS Vue UI 基础组件库的权威文档,覆盖 Button、Input、Form、Checkbox、Select、DatePicker、Modal、Drawer 等核心组件。内容包含设计原则、API 属性、事件与插槽、可访问性(a11y)、响应式与主题适配、组合使用模式、最佳实践、测试策略与性能优化建议。目标是帮助开发者快速理解并高质量地使用这些组件。
|
||||
|
||||
## 项目结构
|
||||
FMS Vue 的基础组件位于 fms-vue/src/components/ui 下,按功能模块划分目录;主题系统通过 CSS 变量与 JS 工具函数在运行时切换主色与深浅模式;表单体系由 Form 提供上下文与校验能力,子项通过 provide/inject 协作。
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "UI 组件"
|
||||
B["Button"]
|
||||
I["Input"]
|
||||
Cb["Checkbox"]
|
||||
S["Select"]
|
||||
Dp["DatePicker"]
|
||||
M["Modal"]
|
||||
Dr["Drawer"]
|
||||
F["Form"]
|
||||
end
|
||||
subgraph "主题系统"
|
||||
TJS["theme/index.js"]
|
||||
TTOK["theme/tokens.css"]
|
||||
end
|
||||
subgraph "通用能力"
|
||||
Pop["Popover(浮层)"]
|
||||
Drag["拖拽/缩放工具"]
|
||||
Focus["焦点管理"]
|
||||
Scroll["滚动锁定"]
|
||||
end
|
||||
S --> Pop
|
||||
Dp --> Pop
|
||||
M --> Drag
|
||||
M --> Focus
|
||||
M --> Scroll
|
||||
Dr --> Drag
|
||||
Dr --> Focus
|
||||
Dr --> Scroll
|
||||
F --> |provide/inject| 各FormItem
|
||||
B --> |"样式类名"| TTOK
|
||||
I --> |"样式类名"| TTOK
|
||||
Cb --> |"样式类名"| TTOK
|
||||
S --> |"样式类名"| TTOK
|
||||
Dp --> |"样式类名"| TTOK
|
||||
M --> |"样式类名"| TTOK
|
||||
Dr --> |"样式类名"| TTOK
|
||||
TJS --> TTOK
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [Button.vue:1-69](file://fms-vue/src/components/ui/button/Button.vue#L1-L69)
|
||||
- [Input.vue:1-370](file://fms-vue/src/components/ui/input/Input.vue#L1-L370)
|
||||
- [Checkbox.vue:1-91](file://fms-vue/src/components/ui/checkbox/Checkbox.vue#L1-L91)
|
||||
- [Select.vue:1-526](file://fms-vue/src/components/ui/select/Select.vue#L1-L526)
|
||||
- [date-picker.vue:1-187](file://fms-vue/src/components/ui/date/date-picker.vue#L1-L187)
|
||||
- [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)
|
||||
- [index.js:1-16](file://fms-vue/src/theme/index.js#L1-L16)
|
||||
- [tokens.css:1-152](file://fms-vue/src/theme/tokens.css#L1-L152)
|
||||
|
||||
章节来源
|
||||
- [package.json:1-48](file://fms-vue/package.json#L1-L48)
|
||||
|
||||
## 核心组件
|
||||
- Button:提供多种视觉变体、禁用/加载态、块级按钮与原生 type 支持,具备无障碍提示。
|
||||
- Input:统一输入控件,支持密码可见切换、数字输入、字数统计、清除、前/后缀插槽、文本域自适应高度与拖拽调整。
|
||||
- Checkbox:支持半选状态、名称与值提交、聚焦/失焦事件。
|
||||
- Select:下拉选择器,支持本地/远程筛选、键盘导航、自由输入、无匹配文案、清除与加载态。
|
||||
- DatePicker:日期/时间选择器,支持格式解析、值格式化、禁用日期、清空与键盘交互。
|
||||
- Modal:对话框,支持受控/非受控打开、遮罩、Esc关闭、全屏、拖拽与四边缩放、焦点陷阱与滚动锁定。
|
||||
- Drawer:抽屉面板,支持多方向滑出、尺寸调整、遮罩与键盘交互、焦点与滚动管理。
|
||||
- Form:表单容器,提供布局、网格列数、标签宽度、必填标记、校验时机与全量校验,并通过 provide/inject 向子项下发上下文。
|
||||
|
||||
章节来源
|
||||
- [Button.vue:1-69](file://fms-vue/src/components/ui/button/Button.vue#L1-L69)
|
||||
- [Input.vue:1-370](file://fms-vue/src/components/ui/input/Input.vue#L1-L370)
|
||||
- [Checkbox.vue:1-91](file://fms-vue/src/components/ui/checkbox/Checkbox.vue#L1-L91)
|
||||
- [Select.vue:1-526](file://fms-vue/src/components/ui/select/Select.vue#L1-L526)
|
||||
- [date-picker.vue:1-187](file://fms-vue/src/components/ui/date/date-picker.vue#L1-L187)
|
||||
- [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)
|
||||
- [Form.vue:1-128](file://fms-vue/src/components/ui/form/Form.vue#L1-L128)
|
||||
|
||||
## 架构总览
|
||||
组件间通过“轻量原子 + 组合”的方式构建复杂交互:
|
||||
- 浮层能力由 Popover 抽象,Select 与 DatePicker 复用其触发与定位。
|
||||
- 弹窗/抽屉共享焦点陷阱、滚动锁定与拖拽/缩放工具,保证一致的可访问性与交互体验。
|
||||
- 主题系统以 CSS 变量为核心,JS 仅负责写入主色与切换深色 class,组件通过语义化类名与变量实现风格统一。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant U as "用户"
|
||||
participant Sel as "Select"
|
||||
participant Pop as "Popover"
|
||||
participant List as "选项列表"
|
||||
U->>Sel : 点击/聚焦触发器
|
||||
Sel->>Pop : 打开浮层(open=true)
|
||||
Pop-->>Sel : 更新open状态
|
||||
Sel->>List : 渲染可见选项(过滤/远程)
|
||||
U->>List : 键盘/鼠标选择
|
||||
List-->>Sel : 选中回调(update : modelValue, change)
|
||||
Sel->>Pop : 关闭浮层
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [Select.vue:1-526](file://fms-vue/src/components/ui/select/Select.vue#L1-L526)
|
||||
|
||||
章节来源
|
||||
- [Select.vue:1-526](file://fms-vue/src/components/ui/select/Select.vue#L1-L526)
|
||||
- [date-picker.vue:1-187](file://fms-vue/src/components/ui/date/date-picker.vue#L1-L187)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### Button
|
||||
- 设计要点
|
||||
- 视觉变体:primary/secondary/outline/ghost/danger/link,通过类名注入样式。
|
||||
- 状态:disabled/loading/block,loading 时禁用交互并显示加载图标。
|
||||
- 可访问性:aria-busy 指示加载状态。
|
||||
- API
|
||||
- 属性:type、disabled、loading、block、htmlType
|
||||
- 事件:透传原生 button 事件
|
||||
- 插槽:默认插槽用于按钮内容
|
||||
- 样式定制
|
||||
- 通过类名 button/button-{type}/button-block/button-loading 控制外观
|
||||
- 主题变量影响颜色与尺寸
|
||||
- 示例路径
|
||||
- [Button.vue:11-41](file://fms-vue/src/components/ui/button/Button.vue#L11-L41)
|
||||
- [Button.vue:43-63](file://fms-vue/src/components/ui/button/Button.vue#L43-L63)
|
||||
|
||||
章节来源
|
||||
- [Button.vue:1-69](file://fms-vue/src/components/ui/button/Button.vue#L1-L69)
|
||||
- [tokens.css:1-152](file://fms-vue/src/theme/tokens.css#L1-L152)
|
||||
|
||||
### Input
|
||||
- 设计要点
|
||||
- 多模式:default/password/number/textarea,统一交互与样式。
|
||||
- 辅助能力:allowClear、showCount、maxlength、rows、autocomplete。
|
||||
- 文本域:自动测量初始高度、拖拽调整高度、键盘微调、防抖刷新。
|
||||
- 数字输入:中间态保留小数点,提交时转为 Number,空值保留为空字符串。
|
||||
- API
|
||||
- 属性:modelValue、type、disabled、readonly、status、allowClear、showCount、maxlength、rows、autocomplete
|
||||
- 事件:update:modelValue、change、blur、focus、clear
|
||||
- 插槽:prefix、suffix
|
||||
- 可访问性
|
||||
- aria-invalid 根据 status 设置;密码切换按钮具备 aria-label 与 aria-pressed。
|
||||
- 示例路径
|
||||
- [Input.vue:6-28](file://fms-vue/src/components/ui/input/Input.vue#L6-L28)
|
||||
- [Input.vue:76-97](file://fms-vue/src/components/ui/input/Input.vue#L76-L97)
|
||||
- [Input.vue:107-150](file://fms-vue/src/components/ui/input/Input.vue#L107-L150)
|
||||
- [Input.vue:152-277](file://fms-vue/src/components/ui/input/Input.vue#L152-L277)
|
||||
- [Input.vue:280-364](file://fms-vue/src/components/ui/input/Input.vue#L280-L364)
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start(["输入事件"]) --> Mode{"是否数字模式?"}
|
||||
Mode -- 否 --> UpdateText["更新 modelValue"]
|
||||
Mode -- 是 --> Normalize["规范化输入<br/>保留中间态小数点"]
|
||||
Normalize --> Commit{"失焦或确认?"}
|
||||
Commit -- 是 --> ToNumber["转换为 Number<br/>空值保持空串"]
|
||||
Commit -- 否 --> Wait["等待继续输入"]
|
||||
ToNumber --> UpdateNum["更新 modelValue"]
|
||||
UpdateText --> End(["结束"])
|
||||
UpdateNum --> End
|
||||
Wait --> End
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [Input.vue:107-150](file://fms-vue/src/components/ui/input/Input.vue#L107-L150)
|
||||
- [Input.vue:76-97](file://fms-vue/src/components/ui/input/Input.vue#L76-L97)
|
||||
|
||||
章节来源
|
||||
- [Input.vue:1-370](file://fms-vue/src/components/ui/input/Input.vue#L1-L370)
|
||||
|
||||
### Checkbox
|
||||
- 设计要点
|
||||
- 支持 indeterminate 半选,勾选优先于半选显示。
|
||||
- 原生 name/value 便于表单提交分组与取值。
|
||||
- API
|
||||
- 属性:modelValue、indeterminate、disabled、name、value
|
||||
- 事件:update:modelValue、change、focus、blur
|
||||
- 插槽:默认插槽作为标签文本
|
||||
- 可访问性
|
||||
- 内部 input 类型 checkbox,配合 label 包裹提升可访问性。
|
||||
- 示例路径
|
||||
- [Checkbox.vue:6-17](file://fms-vue/src/components/ui/checkbox/Checkbox.vue#L6-L17)
|
||||
- [Checkbox.vue:21-63](file://fms-vue/src/components/ui/checkbox/Checkbox.vue#L21-L63)
|
||||
- [Checkbox.vue:65-85](file://fms-vue/src/components/ui/checkbox/Checkbox.vue#L65-L85)
|
||||
|
||||
章节来源
|
||||
- [Checkbox.vue:1-91](file://fms-vue/src/components/ui/checkbox/Checkbox.vue#L1-L91)
|
||||
|
||||
### Select
|
||||
- 设计要点
|
||||
- 本地/远程筛选:filterable/filterOption/remote/search。
|
||||
- 键盘导航:上下移动、Home/End、Enter 选择、Esc 取消。
|
||||
- 自由输入:allowFreeInput 允许将当前文本作为值提交。
|
||||
- 缓存显示:selectedCache 避免选项替换后显示丢失。
|
||||
- API
|
||||
- 属性:modelValue、options、disabled、clearable、filterable、filterOption、remote、loading、notFoundText、allowFreeInput、labelKey、valueKey
|
||||
- 事件:update:modelValue、change、search
|
||||
- 插槽:默认插槽用于自定义选项,暴露 select/close 方法
|
||||
- 可访问性
|
||||
- role="combobox"/role="listbox"/role="option",aria-expanded、aria-controls、aria-activedescendant、aria-selected、aria-disabled、aria-busy。
|
||||
- 示例路径
|
||||
- [Select.vue:7-35](file://fms-vue/src/components/ui/select/Select.vue#L7-L35)
|
||||
- [Select.vue:52-144](file://fms-vue/src/components/ui/select/Select.vue#L52-L144)
|
||||
- [Select.vue:160-205](file://fms-vue/src/components/ui/select/Select.vue#L160-L205)
|
||||
- [Select.vue:207-407](file://fms-vue/src/components/ui/select/Select.vue#L207-L407)
|
||||
- [Select.vue:410-526](file://fms-vue/src/components/ui/select/Select.vue#L410-L526)
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant U as "用户"
|
||||
participant Sel as "Select"
|
||||
participant Opt as "选项集合"
|
||||
U->>Sel : 键入筛选词
|
||||
Sel->>Sel : 更新 filterQuery
|
||||
alt 远程模式
|
||||
Sel-->>U : 触发 search(query)
|
||||
U-->>Sel : 父层更新 options
|
||||
else 本地模式
|
||||
Sel->>Opt : 计算 visibleOptions
|
||||
end
|
||||
U->>Sel : 方向键/Enter 选择
|
||||
Sel-->>U : update : modelValue / change
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [Select.vue:253-290](file://fms-vue/src/components/ui/select/Select.vue#L253-L290)
|
||||
- [Select.vue:326-407](file://fms-vue/src/components/ui/select/Select.vue#L326-L407)
|
||||
|
||||
章节来源
|
||||
- [Select.vue:1-526](file://fms-vue/src/components/ui/select/Select.vue#L1-L526)
|
||||
|
||||
### DatePicker
|
||||
- 设计要点
|
||||
- format/valueFormat 分离展示与绑定值格式,自动解析精度。
|
||||
- 支持 disabledDate、clearable、键盘打开/关闭、回车/空格切换。
|
||||
- 基于 Popover 弹出 CalendarPanel,支持时间/日期/混合模式。
|
||||
- API
|
||||
- 属性:modelValue、format、valueFormat、clearable、disabled、disabledDate
|
||||
- 事件:update:modelValue、change
|
||||
- 可访问性
|
||||
- 输入框 readonly,具备 aria-haspopup/dialog、aria-expanded。
|
||||
- 示例路径
|
||||
- [date-picker.vue:16-27](file://fms-vue/src/components/ui/date/date-picker.vue#L16-L27)
|
||||
- [date-picker.vue:46-74](file://fms-vue/src/components/ui/date/date-picker.vue#L46-L74)
|
||||
- [date-picker.vue:76-129](file://fms-vue/src/components/ui/date/date-picker.vue#L76-L129)
|
||||
- [date-picker.vue:132-187](file://fms-vue/src/components/ui/date/date-picker.vue#L132-L187)
|
||||
|
||||
章节来源
|
||||
- [date-picker.vue:1-187](file://fms-vue/src/components/ui/date/date-picker.vue#L1-L187)
|
||||
|
||||
### Modal
|
||||
- 设计要点
|
||||
- 受控/非受控 open,支持 maskClosable、keyboard、closable、fullscreen、resizable。
|
||||
- 打开时记录触发元素、锁定滚动、焦点陷阱、拖拽标题栏、四边缩放手柄。
|
||||
- 关闭时恢复焦点、清理监听与句柄。
|
||||
- API
|
||||
- 属性:open/defaultOpen、title、width、centered、mask、maskClosable、keyboard、closable、fullscreen、resizable、footer、okText、cancelText、confirmLoading
|
||||
- 事件:update:open、ok、cancel
|
||||
- 插槽:默认内容区、footer 自定义底部按钮
|
||||
- 可访问性
|
||||
- role="dialog"、aria-modal、aria-labelledby/aria-label、Tab 循环。
|
||||
- 示例路径
|
||||
- [Modal.vue:10-43](file://fms-vue/src/components/ui/modal/Modal.vue#L10-L43)
|
||||
- [Modal.vue:66-116](file://fms-vue/src/components/ui/modal/Modal.vue#L66-L116)
|
||||
- [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)
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant U as "用户"
|
||||
participant M as "Modal"
|
||||
participant F as "焦点/滚动工具"
|
||||
U->>M : 触发打开
|
||||
M->>F : lockScroll()
|
||||
M->>M : 记录触发元素
|
||||
M->>F : focusFirst(panel)
|
||||
M->>M : 绑定拖拽/缩放句柄
|
||||
U->>M : Esc/遮罩/取消
|
||||
M->>F : unlockScroll()
|
||||
M->>M : 恢复焦点到触发元素
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [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)
|
||||
|
||||
### Drawer
|
||||
- 设计要点
|
||||
- placement 支持 left/right/top/bottom,对应不同方向与尺寸轴。
|
||||
- resizable 支持边缘拖拽调整尺寸,限制不超过视口。
|
||||
- 打开/关闭生命周期与 Modal 类似:焦点陷阱、滚动锁定、句柄清理。
|
||||
- API
|
||||
- 属性:open/defaultOpen、title、placement、width/height、mask、maskClosable、keyboard、closable、resizable
|
||||
- 事件:update:open、cancel
|
||||
- 插槽:extra、footer
|
||||
- 可访问性
|
||||
- role="dialog"、aria-modal、aria-labelledby/aria-label。
|
||||
- 示例路径
|
||||
- [Drawer.vue:9-38](file://fms-vue/src/components/ui/drawer/Drawer.vue#L9-L38)
|
||||
- [Drawer.vue:53-113](file://fms-vue/src/components/ui/drawer/Drawer.vue#L53-L113)
|
||||
- [Drawer.vue:115-154](file://fms-vue/src/components/ui/drawer/Drawer.vue#L115-L154)
|
||||
- [Drawer.vue:157-213](file://fms-vue/src/components/ui/drawer/Drawer.vue#L157-L213)
|
||||
|
||||
章节来源
|
||||
- [Drawer.vue:1-219](file://fms-vue/src/components/ui/drawer/Drawer.vue#L1-L219)
|
||||
|
||||
### Form
|
||||
- 设计要点
|
||||
- 布局:horizontal/vertical,columns>1 启用网格布局。
|
||||
- 字段注册:registerField/unregisterField 维护字段校验能力。
|
||||
- 全量校验:validateAll 并行校验所有已注册字段,返回错误字段列表。
|
||||
- 提交/重置:submit/submitFailed/reset 事件,重置时同步清除校验状态。
|
||||
- API
|
||||
- 属性:model、rules、layout、labelAlign、labelWidth、columns、maxWidth、requiredMark、validateTrigger
|
||||
- 事件:submit、submitFailed、reset
|
||||
- 方法:validateAll(defineExpose)
|
||||
- 示例路径
|
||||
- [Form.vue:5-38](file://fms-vue/src/components/ui/form/Form.vue#L5-L38)
|
||||
- [Form.vue:40-92](file://fms-vue/src/components/ui/form/Form.vue#L40-L92)
|
||||
- [Form.vue:94-110](file://fms-vue/src/components/ui/form/Form.vue#L94-L110)
|
||||
- [Form.vue:113-123](file://fms-vue/src/components/ui/form/Form.vue#L113-L123)
|
||||
|
||||
章节来源
|
||||
- [Form.vue:1-128](file://fms-vue/src/components/ui/form/Form.vue#L1-L128)
|
||||
|
||||
## 依赖分析
|
||||
- 外部依赖
|
||||
- Vue 3、@lucide/vue 图标、dayjs(日期处理)、pinia(状态)、axios(网络)等。
|
||||
- 组件内依赖
|
||||
- Select/DatePicker 依赖 Popover 进行浮层展示。
|
||||
- Modal/Drawer 依赖焦点管理、滚动锁定、拖拽/缩放工具。
|
||||
- 所有组件通过 tokens.css 的 CSS 变量实现主题一致性。
|
||||
- 主题系统
|
||||
- index.js 提供 applyPrimaryColor 与 applyDarkMode,操作 <html> 上的 class 与 CSS 变量。
|
||||
- tokens.css 定义浅色/深色两套变量,主色通过 JS 动态写入。
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
Pkg["package.json"] --> Vue["Vue 3"]
|
||||
Pkg --> Icons["@lucide/vue"]
|
||||
Pkg --> Dayjs["dayjs"]
|
||||
Pkg --> Pinia["pinia"]
|
||||
Pkg --> Axios["axios"]
|
||||
Comp["UI 组件"] --> Tokens["tokens.css"]
|
||||
Theme["theme/index.js"] --> Tokens
|
||||
Comp --> Tools["焦点/滚动/拖拽工具"]
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [package.json:1-48](file://fms-vue/package.json#L1-L48)
|
||||
- [index.js:1-16](file://fms-vue/src/theme/index.js#L1-L16)
|
||||
- [tokens.css:1-152](file://fms-vue/src/theme/tokens.css#L1-L152)
|
||||
|
||||
章节来源
|
||||
- [package.json:1-48](file://fms-vue/package.json#L1-L48)
|
||||
- [index.js:1-16](file://fms-vue/src/theme/index.js#L1-L16)
|
||||
- [tokens.css:1-152](file://fms-vue/src/theme/tokens.css#L1-L152)
|
||||
|
||||
## 性能考虑
|
||||
- 列表渲染优化
|
||||
- Select 使用 v-memo 对选项列表进行稳定渲染,减少重绘。
|
||||
- 高频交互节流
|
||||
- Input 文本域拖拽高度时使用 requestAnimationFrame 合并更新,避免频繁重排。
|
||||
- 事件与监听
|
||||
- Modal/Drawer 在打开时绑定键盘事件,关闭时及时移除,防止内存泄漏。
|
||||
- 浮层与滚动
|
||||
- 弹窗/抽屉打开时锁定页面滚动,避免背景滚动带来的抖动与重绘。
|
||||
- 远程搜索
|
||||
- Select 开启 remote 时由父层控制数据源,避免前端大数据集筛选开销。
|
||||
|
||||
[本节为通用指导,不直接分析具体文件]
|
||||
|
||||
## 故障排查指南
|
||||
- 表单校验未生效
|
||||
- 检查 Form 是否正确 provide 上下文,FormItem 是否完成 registerField。
|
||||
- validateTrigger 为 blur 时,确保在失焦后再触发校验。
|
||||
- 数字输入异常
|
||||
- Input number 模式会保留中间态小数点,提交时才转 Number;如需严格整数,请在父层做二次校验。
|
||||
- 选择器显示值丢失
|
||||
- Select 在 options 被替换时会清空 selectedCache,需确保 valueKey 指向正确且值稳定。
|
||||
- 弹窗/抽屉焦点丢失
|
||||
- 确认组件处于打开状态,焦点陷阱已绑定;关闭后会自动恢复触发元素焦点。
|
||||
- 主题色不生效
|
||||
- 调用 applyPrimaryColor 写入 --fms-primary,并确保 tokens.css 已被引入。
|
||||
|
||||
章节来源
|
||||
- [Form.vue:94-110](file://fms-vue/src/components/ui/form/Form.vue#L94-L110)
|
||||
- [Input.vue:107-150](file://fms-vue/src/components/ui/input/Input.vue#L107-L150)
|
||||
- [Select.vue:146-158](file://fms-vue/src/components/ui/select/Select.vue#L146-L158)
|
||||
- [Modal.vue:118-198](file://fms-vue/src/components/ui/modal/Modal.vue#L118-L198)
|
||||
- [Drawer.vue:115-154](file://fms-vue/src/components/ui/drawer/Drawer.vue#L115-L154)
|
||||
- [index.js:1-16](file://fms-vue/src/theme/index.js#L1-L16)
|
||||
|
||||
## 结论
|
||||
FMS UI 基础组件以一致的 API 设计、完善的可访问性、灵活的样式与主题机制,以及健壮的交互逻辑,为业务应用提供了可靠的前端基石。通过 Form 的组合能力与 Select/DatePicker 的灵活扩展,能够覆盖大多数常见场景。建议在项目中统一采用该组件库,并结合主题系统与测试策略,持续提升用户体验与开发效率。
|
||||
|
||||
## 附录
|
||||
- 主题与样式
|
||||
- 通过 theme/index.js 的 applyPrimaryColor 与 applyDarkMode 控制主色与深浅模式。
|
||||
- 所有组件通过 tokens.css 中的 CSS 变量保持一致的视觉语言。
|
||||
- 组合使用模式
|
||||
- Form + Input/Select/DatePicker/Checkbox 构建复杂表单,利用 validateTrigger 与 rules 实现精细化校验。
|
||||
- Modal/Drawer 承载表单或详情,结合 confirmLoading 与异步流程控制。
|
||||
- 测试策略
|
||||
- 单元测试:验证 props/emits/插槽行为,如 Input 的数字模式、Select 的键盘导航。
|
||||
- 集成测试:模拟用户交互(点击、键盘),断言 DOM 状态与事件触发。
|
||||
- 可访问性测试:检查 role/aria 属性与键盘可达性。
|
||||
- 最佳实践
|
||||
- 使用受控模式管理 open/modelValue,避免状态不一致。
|
||||
- 合理使用远程搜索与分页,避免大数据集在前端筛选。
|
||||
- 通过 slots 与 CSS 变量进行最小侵入的样式定制。
|
||||
|
||||
[本节为通用指导,不直接分析具体文件]
|
||||
@@ -0,0 +1,365 @@
|
||||
# 业务组件
|
||||
|
||||
<cite>
|
||||
**本文引用的文件**
|
||||
- [FmsTable.vue](file://fms-vue/src/components/fms-table/FmsTable.vue)
|
||||
- [createCellRenderer.js](file://fms-vue/src/components/fms-table/utils/createCellRenderer.js)
|
||||
- [createEditableCellRenderer.js](file://fms-vue/src/components/fms-table/utils/createEditableCellRenderer.js)
|
||||
- [createSelectionCellRenderers.js](file://fms-vue/src/components/fms-table/utils/createSelectionCellRenderers.js)
|
||||
- [FmsFile.vue](file://fms-vue/src/components/fms-file/FmsFile.vue)
|
||||
- [FileListPanel.vue](file://fms-vue/src/components/fms-file/FileListPanel.vue)
|
||||
- [FileCard.vue](file://fms-vue/src/components/fms-file/FileCard.vue)
|
||||
- [FilePreviewPanel.vue](file://fms-vue/src/components/fms-file/FilePreviewPanel.vue)
|
||||
- [useFileCategory.js](file://fms-vue/src/components/fms-file/composables/useFileCategory.js)
|
||||
- [fileService.js](file://fms-vue/src/services/fileService.js)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
3. [核心组件](#核心组件)
|
||||
4. [架构总览](#架构总览)
|
||||
5. [详细组件分析](#详细组件分析)
|
||||
6. [依赖关系分析](#依赖关系分析)
|
||||
7. [性能考量](#性能考量)
|
||||
8. [故障排查指南](#故障排查指南)
|
||||
9. [结论](#结论)
|
||||
10. [附录:使用示例与配置方案](#附录使用示例与配置方案)
|
||||
|
||||
## 简介
|
||||
本文件面向 FMS 业务组件,重点围绕以下能力展开:
|
||||
- FmsTable 高性能表格:虚拟滚动、行内编辑、列配置、数据绑定、选择与拖拽排序等。
|
||||
- FmsFile 文件管理:上传(本地/OSS)、预览、分类树、批量操作(多选/删除/下载)。
|
||||
- 与 UI 基础组件的集成模式,以及与后端服务的交互方式。
|
||||
- 复杂场景下的配置与最佳实践,以及性能优化与错误处理策略。
|
||||
|
||||
## 项目结构
|
||||
FmsTable 位于 fms-vue/src/components/fms-table,核心由主组件与工具函数组成;FmsFile 位于 fms-vue/src/components/fms-file,包含三栏布局(分类树、文件列表、预览)及组合式逻辑。
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "表格组件"
|
||||
A["FmsTable.vue"]
|
||||
B["createCellRenderer.js"]
|
||||
C["createEditableCellRenderer.js"]
|
||||
D["createSelectionCellRenderers.js"]
|
||||
end
|
||||
subgraph "文件组件"
|
||||
E["FmsFile.vue"]
|
||||
F["FileListPanel.vue"]
|
||||
G["FileCard.vue"]
|
||||
H["FilePreviewPanel.vue"]
|
||||
I["useFileCategory.js"]
|
||||
end
|
||||
J["fileService.js"]
|
||||
K["UI 基础组件<br/>Button/Modal/Dropdown/Input/Select..."]
|
||||
A --> B
|
||||
A --> C
|
||||
A --> D
|
||||
E --> F
|
||||
E --> H
|
||||
E --> I
|
||||
F --> G
|
||||
F --> J
|
||||
H --> J
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [FmsTable.vue:1-800](file://fms-vue/src/components/fms-table/FmsTable.vue#L1-L800)
|
||||
- [createCellRenderer.js:1-229](file://fms-vue/src/components/fms-table/utils/createCellRenderer.js#L1-L229)
|
||||
- [createEditableCellRenderer.js:1-212](file://fms-vue/src/components/fms-table/utils/createEditableCellRenderer.js#L1-L212)
|
||||
- [createSelectionCellRenderers.js:1-135](file://fms-vue/src/components/fms-table/utils/createSelectionCellRenderers.js#L1-L135)
|
||||
- [FmsFile.vue:1-262](file://fms-vue/src/components/fms-file/FmsFile.vue#L1-L262)
|
||||
- [FileListPanel.vue:1-800](file://fms-vue/src/components/fms-file/FileListPanel.vue#L1-L800)
|
||||
- [FileCard.vue:1-296](file://fms-vue/src/components/fms-file/FileCard.vue#L1-L296)
|
||||
- [FilePreviewPanel.vue:1-247](file://fms-vue/src/components/fms-file/FilePreviewPanel.vue#L1-L247)
|
||||
- [useFileCategory.js:1-77](file://fms-vue/src/components/fms-file/composables/useFileCategory.js#L1-L77)
|
||||
- [fileService.js:1-149](file://fms-vue/src/services/fileService.js#L1-L149)
|
||||
|
||||
章节来源
|
||||
- [FmsTable.vue:1-800](file://fms-vue/src/components/fms-table/FmsTable.vue#L1-L800)
|
||||
- [FmsFile.vue:1-262](file://fms-vue/src/components/fms-file/FmsFile.vue#L1-L262)
|
||||
|
||||
## 核心组件
|
||||
- FmsTable:基于 StkTable 的高性能表格封装,提供虚拟滚动、行内编辑、列头拖拽、选择列、拖拽排序、主题切换、键盘导航与编辑激活优化等。
|
||||
- FmsFile:三栏文件管理器,支持分类树、文件列表(网格/列表视图)、预览面板、批量操作、上传(本地/OSS)、分页与粘贴/拖拽上传。
|
||||
|
||||
章节来源
|
||||
- [FmsTable.vue:10-37](file://fms-vue/src/components/fms-table/FmsTable.vue#L10-L37)
|
||||
- [FmsFile.vue:12-20](file://fms-vue/src/components/fms-file/FmsFile.vue#L12-L20)
|
||||
|
||||
## 架构总览
|
||||
FmsTable 通过 props 暴露行为开关(如 virtual、editable、rowSelection),内部将列配置标准化并注入自定义渲染器(actions、可编辑单元格、选择列),再交给底层表格库渲染。FmsFile 通过 Splitter 组织三栏,左侧分类树由 useFileCategory 驱动,中间 FileListPanel 负责数据加载与批量操作,右侧 FilePreviewPanel 负责预览。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant U as "父组件"
|
||||
participant FT as "FmsTable.vue"
|
||||
participant CR as "createCellRenderer.js"
|
||||
participant EC as "createEditableCellRenderer.js"
|
||||
participant SC as "createSelectionCellRenderers.js"
|
||||
participant ST as "StkTable(底层)"
|
||||
U->>FT : 传入 columns/dataSource/props
|
||||
FT->>CR : resolveCustomCell(col, ctx, editingActive)
|
||||
alt 有 actions
|
||||
CR-->>ST : 注入 actions 自定义单元格
|
||||
else 可编辑列且处于编辑态或特殊类型
|
||||
CR->>EC : createEditableCell(...)
|
||||
EC-->>ST : 返回输入/选择/复选框渲染
|
||||
end
|
||||
FT->>SC : createSelectionColumn(...)
|
||||
SC-->>ST : 注入选择列
|
||||
FT->>ST : 渲染 displayColumns + dataSource
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [FmsTable.vue:273-334](file://fms-vue/src/components/fms-table/FmsTable.vue#L273-L334)
|
||||
- [createCellRenderer.js:208-229](file://fms-vue/src/components/fms-table/utils/createCellRenderer.js#L208-L229)
|
||||
- [createEditableCellRenderer.js:195-212](file://fms-vue/src/components/fms-table/utils/createEditableCellRenderer.js#L195-L212)
|
||||
- [createSelectionCellRenderers.js:18-129](file://fms-vue/src/components/fms-table/utils/createSelectionCellRenderers.js#L18-L129)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### FmsTable 高性能表格
|
||||
- 虚拟滚动
|
||||
- 当数据行数超过阈值时启用虚拟滚动,避免大表渲染开销;宽度变化仅重算 X 方向以提升性能。
|
||||
- 尺寸变更防抖合并 ResizeObserver 通知,减少重复计算。
|
||||
- 行内编辑
|
||||
- 通过 WeakMap 维护每行的编辑状态,仅在活动编辑行存在时注入编辑器渲染,降低滚动时的组件创建成本。
|
||||
- 键盘导航期间延迟激活编辑器,合并连续按键,避免频繁挂载/卸载导致的掉帧。
|
||||
- 支持 Input、Select、Checkbox 三种编辑器,统一焦点管理与值变更回调。
|
||||
- 列配置
|
||||
- 自动注入序号列、选择列、拖拽列;支持列头拖拽排序与列宽调整。
|
||||
- actions 列支持按钮与“更多”下拉菜单,内置确认弹窗。
|
||||
- 数据绑定
|
||||
- rowKey 支持字符串或函数;activeRowKey 控制高亮行;change 事件回传行、列与新值。
|
||||
- 其他特性
|
||||
- 主题跟随应用深浅色;区域选择用于编辑态;导出 scrollToRow/editRow/getSelectedArea 等方法供外部调用。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start(["进入编辑流程"]) --> CheckNav{"是否键盘导航中?"}
|
||||
CheckNav --> |是| Repeat{"是否按住方向键 repeat?"}
|
||||
Repeat --> |是| Defer["延迟激活编辑器<br/>等待松手后提交"]
|
||||
Repeat --> |否| Fast{"快速连按?"}
|
||||
Fast --> |是| Debounce["防抖合并激活"]
|
||||
Fast --> |否| Activate["立即激活编辑器"]
|
||||
CheckNav --> |否| Activate
|
||||
Defer --> Commit["松手后提交目标行"]
|
||||
Debounce --> Commit
|
||||
Activate --> Focus["聚焦并选中内容"]
|
||||
Commit --> Focus
|
||||
Focus --> End(["完成"])
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [FmsTable.vue:373-505](file://fms-vue/src/components/fms-table/FmsTable.vue#L373-L505)
|
||||
|
||||
章节来源
|
||||
- [FmsTable.vue:41-47](file://fms-vue/src/components/fms-table/FmsTable.vue#L41-L47)
|
||||
- [FmsTable.vue:70-96](file://fms-vue/src/components/fms-table/FmsTable.vue#L70-L96)
|
||||
- [FmsTable.vue:98-126](file://fms-vue/src/components/fms-table/FmsTable.vue#L98-L126)
|
||||
- [FmsTable.vue:176-220](file://fms-vue/src/components/fms-table/FmsTable.vue#L176-L220)
|
||||
- [FmsTable.vue:273-334](file://fms-vue/src/components/fms-table/FmsTable.vue#L273-L334)
|
||||
- [createEditableCellRenderer.js:17-49](file://fms-vue/src/components/fms-table/utils/createEditableCellRenderer.js#L17-L49)
|
||||
- [createEditableCellRenderer.js:78-127](file://fms-vue/src/components/fms-table/utils/createEditableCellRenderer.js#L78-L127)
|
||||
- [createEditableCellRenderer.js:129-193](file://fms-vue/src/components/fms-table/utils/createEditableCellRenderer.js#L129-L193)
|
||||
- [createCellRenderer.js:9-43](file://fms-vue/src/components/fms-table/utils/createCellRenderer.js#L9-L43)
|
||||
- [createCellRenderer.js:102-206](file://fms-vue/src/components/fms-table/utils/createCellRenderer.js#L102-L206)
|
||||
- [createSelectionCellRenderers.js:18-129](file://fms-vue/src/components/fms-table/utils/createSelectionCellRenderers.js#L18-L129)
|
||||
|
||||
### FmsFile 文件管理组件
|
||||
- 功能特性
|
||||
- 分类管理:加载 bf_files_cateid 扁平数据并转换为树形结构,支持“全部分类”根节点。
|
||||
- 文件列表:网格/列表双视图,支持全选、批量删除/下载、分页、拖拽/粘贴上传。
|
||||
- 预览面板:图片直显,非图片显示类型标签与元信息,支持前后翻页。
|
||||
- 上传机制:根据后端配置选择本地直传或阿里云 OSS 直传;OSS 凭证缓存与过期刷新。
|
||||
- 交互流程
|
||||
- 选择分类 → 加载对应文件 → 选择文件 → 右侧预览 → 批量操作。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant P as "父组件"
|
||||
participant FF as "FmsFile.vue"
|
||||
participant FC as "useFileCategory.js"
|
||||
participant FL as "FileListPanel.vue"
|
||||
participant FS as "fileService.js"
|
||||
participant FP as "FilePreviewPanel.vue"
|
||||
P->>FF : 传入 moduleCode/father/initialCateId
|
||||
FF->>FC : loadCategories()
|
||||
FC-->>FF : treeData/selectedKey
|
||||
FF->>FL : 传递 moduleId/cateId/readonly
|
||||
FL->>FS : pageDataApi / upload / removeFile
|
||||
FS-->>FL : 文件列表/上传结果
|
||||
FL->>FP : selectedFile
|
||||
FP-->>P : 预览/上下页事件
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [FmsFile.vue:22-80](file://fms-vue/src/components/fms-file/FmsFile.vue#L22-L80)
|
||||
- [useFileCategory.js:15-64](file://fms-vue/src/components/fms-file/composables/useFileCategory.js#L15-L64)
|
||||
- [FileListPanel.vue:90-133](file://fms-vue/src/components/fms-file/FileListPanel.vue#L90-L133)
|
||||
- [fileService.js:25-85](file://fms-vue/src/services/fileService.js#L25-L85)
|
||||
- [FilePreviewPanel.vue:15-39](file://fms-vue/src/components/fms-file/FilePreviewPanel.vue#L15-L39)
|
||||
|
||||
章节来源
|
||||
- [FmsFile.vue:22-133](file://fms-vue/src/components/fms-file/FmsFile.vue#L22-L133)
|
||||
- [FileListPanel.vue:45-133](file://fms-vue/src/components/fms-file/FileListPanel.vue#L45-L133)
|
||||
- [FileListPanel.vue:155-258](file://fms-vue/src/components/fms-file/FileListPanel.vue#L155-L258)
|
||||
- [FileListPanel.vue:280-364](file://fms-vue/src/components/fms-file/FileListPanel.vue#L280-L364)
|
||||
- [FilePreviewPanel.vue:15-39](file://fms-vue/src/components/fms-file/FilePreviewPanel.vue#L15-L39)
|
||||
- [useFileCategory.js:15-64](file://fms-vue/src/components/fms-file/composables/useFileCategory.js#L15-L64)
|
||||
- [fileService.js:25-143](file://fms-vue/src/services/fileService.js#L25-L143)
|
||||
|
||||
### 对象模型与关系(代码级)
|
||||
```mermaid
|
||||
classDiagram
|
||||
class FmsTable {
|
||||
+props : virtual/virtualX/colResizable/bordered/noDataFull/showOverflow/columns/seq/columnDraggable/rowSelection/dataSource/rowKey/activeRowKey/rowDraggable/editable/theme
|
||||
+emit : update : columns/change/row-order-change
|
||||
+methods : scrollToRow/editRow/getSelectedArea/clearSelectedArea/setRowExpand/initVirtualScroll
|
||||
}
|
||||
class CreateCellRenderer {
|
||||
+resolveCustomCell(col, ctx, editingActive)
|
||||
}
|
||||
class EditableCellRenderer {
|
||||
+createEditableCell(col, ctx)
|
||||
}
|
||||
class SelectionCellRenderer {
|
||||
+createSelectionColumn(options)
|
||||
+isSelectionColumn(col)
|
||||
}
|
||||
class FmsFile {
|
||||
+props : moduleCode/father/showTree/readonly/initialCateId
|
||||
+emit : uploaded/deleted/selected
|
||||
}
|
||||
class FileListPanel {
|
||||
+props : moduleCode/moduleId/father/cateId/readonly
|
||||
+emit : preview/uploaded/deleted
|
||||
}
|
||||
class FilePreviewPanel {
|
||||
+props : file/fileList
|
||||
+emit : prev/next
|
||||
}
|
||||
class UseFileCategory {
|
||||
+treeData/loading/error/selectedKey
|
||||
+loadCategories/selectCategory/findCategory
|
||||
}
|
||||
class FileService {
|
||||
+upload(opts)
|
||||
+getPreviewUrl(fileRow)
|
||||
+removeFile(subid)
|
||||
}
|
||||
FmsTable --> CreateCellRenderer : "生成列渲染"
|
||||
FmsTable --> EditableCellRenderer : "行内编辑"
|
||||
FmsTable --> SelectionCellRenderer : "选择列"
|
||||
FmsFile --> UseFileCategory : "分类树"
|
||||
FmsFile --> FileListPanel : "列表/上传/批量"
|
||||
FmsFile --> FilePreviewPanel : "预览"
|
||||
FileListPanel --> FileService : "上传/删除/预览URL"
|
||||
FilePreviewPanel --> FileService : "预览URL"
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [FmsTable.vue:10-37](file://fms-vue/src/components/fms-table/FmsTable.vue#L10-L37)
|
||||
- [createCellRenderer.js:208-229](file://fms-vue/src/components/fms-table/utils/createCellRenderer.js#L208-L229)
|
||||
- [createEditableCellRenderer.js:195-212](file://fms-vue/src/components/fms-table/utils/createEditableCellRenderer.js#L195-L212)
|
||||
- [createSelectionCellRenderers.js:18-135](file://fms-vue/src/components/fms-table/utils/createSelectionCellRenderers.js#L18-L135)
|
||||
- [FmsFile.vue:12-20](file://fms-vue/src/components/fms-file/FmsFile.vue#L12-L20)
|
||||
- [FileListPanel.vue:35-43](file://fms-vue/src/components/fms-file/FileListPanel.vue#L35-L43)
|
||||
- [FilePreviewPanel.vue:8-13](file://fms-vue/src/components/fms-file/FilePreviewPanel.vue#L8-L13)
|
||||
- [useFileCategory.js:9-75](file://fms-vue/src/components/fms-file/composables/useFileCategory.js#L9-L75)
|
||||
- [fileService.js:25-143](file://fms-vue/src/services/fileService.js#L25-L143)
|
||||
|
||||
## 依赖关系分析
|
||||
- FmsTable 依赖 StkTable 进行虚拟化与渲染,并通过 utils 中的三个模块分别处理 actions、可编辑单元格、选择列。
|
||||
- FmsFile 依赖 Splitter 布局组件与 UI 基础组件(Button/Modal/Dropdown/Input/Select/Checkbox/Pagination/Spin/Tag/Tooltip),并通过 services 层与后端交互。
|
||||
- 文件服务 fileService.js 抽象了本地与 OSS 两种上传路径,并提供凭证缓存与预览 URL 获取。
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
FT["FmsTable.vue"] --> STK["stk-table-vue"]
|
||||
FT --> U1["createCellRenderer.js"]
|
||||
FT --> U2["createEditableCellRenderer.js"]
|
||||
FT --> U3["createSelectionCellRenderers.js"]
|
||||
FF["FmsFile.vue"] --> SPLIT["Splitter"]
|
||||
FF --> UI["UI 基础组件"]
|
||||
FF --> SVC["fileService.js"]
|
||||
FL["FileListPanel.vue"] --> SVC
|
||||
FP["FilePreviewPanel.vue"] --> SVC
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [FmsTable.vue:1-8](file://fms-vue/src/components/fms-table/FmsTable.vue#L1-L8)
|
||||
- [FmsFile.vue:1-10](file://fms-vue/src/components/fms-file/FmsFile.vue#L1-L10)
|
||||
- [fileService.js:1-149](file://fms-vue/src/services/fileService.js#L1-L149)
|
||||
|
||||
章节来源
|
||||
- [FmsTable.vue:1-8](file://fms-vue/src/components/fms-table/FmsTable.vue#L1-L8)
|
||||
- [FmsFile.vue:1-10](file://fms-vue/src/components/fms-file/FmsFile.vue#L1-L10)
|
||||
- [fileService.js:1-149](file://fms-vue/src/services/fileService.js#L1-L149)
|
||||
|
||||
## 性能考量
|
||||
- 表格虚拟滚动
|
||||
- 数据量大于阈值才开启虚拟滚动,避免小数据量的额外开销。
|
||||
- 尺寸变化时仅重算 X 方向(高度未变),减少 Y 方向重排。
|
||||
- ResizeObserver 防抖合并,动画期间不频繁触发 initVirtualScroll。
|
||||
- 编辑态优化
|
||||
- 仅在存在活动编辑行时注入 customCell,非编辑态走原生 td,减少函数式组件数量。
|
||||
- 键盘导航期间延迟激活编辑器,合并连续按键,避免频繁挂载/卸载。
|
||||
- 使用 WeakMap 存储草稿值,卸载前兜底写入,避免整表更新。
|
||||
- 文件列表
|
||||
- 网格/列表双视图,避免引入重型表格库;分页加载减少首屏压力。
|
||||
- 图片缩略图使用 Blob URL 并适时释放,防止内存泄漏。
|
||||
- OSS 直传凭证缓存,减少鉴权请求频率。
|
||||
|
||||
[本节为通用性能建议,不直接分析具体文件]
|
||||
|
||||
## 故障排查指南
|
||||
- 表格编辑异常
|
||||
- 检查 editable 与 column.editor 配置是否正确;确认 editingActive 与活动行状态迁移逻辑。
|
||||
- 关注键盘导航期间的延迟激活与防抖逻辑,避免误判 repeat 导致编辑器未激活。
|
||||
- 选择列状态不一致
|
||||
- 确认 getSelectedRowKeys 与 onChange 回调是否同步更新;过滤禁用行后的全选统计是否正确。
|
||||
- 文件上传失败
|
||||
- 检查 storageType 初始化与凭证缓存是否过期;OSS 直传需确保 host/policy/signature 正确。
|
||||
- 本地上传需确保 FormData 字段名与后端一致;Content-Type 不应被覆盖。
|
||||
- 预览不可用
|
||||
- 确认 mx_mapfilename 是否存在;图片类型判断是否匹配扩展名。
|
||||
|
||||
章节来源
|
||||
- [FmsTable.vue:176-220](file://fms-vue/src/components/fms-table/FmsTable.vue#L176-L220)
|
||||
- [createSelectionCellRenderers.js:26-56](file://fms-vue/src/components/fms-table/utils/createSelectionCellRenderers.js#L26-L56)
|
||||
- [fileService.js:8-32](file://fms-vue/src/services/fileService.js#L8-L32)
|
||||
- [fileService.js:87-108](file://fms-vue/src/services/fileService.js#L87-L108)
|
||||
- [FilePreviewPanel.vue:27-39](file://fms-vue/src/components/fms-file/FilePreviewPanel.vue#L27-L39)
|
||||
|
||||
## 结论
|
||||
FmsTable 与 FmsFile 在 FMS 业务中承担数据展示与文件管理的核心职责。前者通过精细化的虚拟滚动与编辑态优化实现高性能表格体验;后者以模块化拆分与组合式逻辑提供完整的文件生命周期管理能力。两者均与 UI 基础组件与服务层解耦,便于复用与扩展。
|
||||
|
||||
[本节为总结性内容,不直接分析具体文件]
|
||||
|
||||
## 附录:使用示例与配置方案
|
||||
- FmsTable 常用配置
|
||||
- 虚拟滚动:virtual=true(默认),数据量大时自动生效;可通过 effectiveVirtual 逻辑控制。
|
||||
- 行内编辑:editable=true(默认),列定义 editor={type:'input'|'select'|'checkbox'}。
|
||||
- 选择列:传入 rowSelection={selectedRowKeys, onChange, getCheckboxProps}。
|
||||
- 拖拽排序:rowDraggable=true,监听 row-order-change 事件。
|
||||
- 列头拖拽:columnDraggable=true(默认),可配置 disabled 函数限制特定列。
|
||||
- 主题:theme='light'|'dark',默认跟随应用深浅色。
|
||||
- FmsFile 常用配置
|
||||
- 模块解析:moduleCode 必填,组件会自动查询模块 ID。
|
||||
- 初始分类:initialCateId 指定默认选中分类。
|
||||
- 只读模式:readonly=true 隐藏上传/删除等操作。
|
||||
- 事件:uploaded/deleted/selected 用于与父组件联动。
|
||||
- 复杂场景
|
||||
- 大数据表格:结合分页或懒加载数据源,启用虚拟滚动;避免同时大量编辑。
|
||||
- 多文件批量操作:使用 FileListPanel 的多选与批量删除/下载;注意 pending 文件的本地状态清理。
|
||||
- 混合编辑器:同一表格混用 input/select/checkbox,注意 select 的 label 映射与空值处理。
|
||||
|
||||
章节来源
|
||||
- [FmsTable.vue:10-37](file://fms-vue/src/components/fms-table/FmsTable.vue#L10-L37)
|
||||
- [FmsTable.vue:273-334](file://fms-vue/src/components/fms-table/FmsTable.vue#L273-L334)
|
||||
- [createEditableCellRenderer.js:97-147](file://fms-vue/src/components/fms-table/utils/createEditableCellRenderer.js#L97-L147)
|
||||
- [FmsFile.vue:12-20](file://fms-vue/src/components/fms-file/FmsFile.vue#L12-L20)
|
||||
- [FileListPanel.vue:393-636](file://fms-vue/src/components/fms-file/FileListPanel.vue#L393-L636)
|
||||
@@ -0,0 +1,375 @@
|
||||
# 组件系统
|
||||
|
||||
<cite>
|
||||
**本文引用的文件**
|
||||
- [fms-vue/src/components/ui/button/Button.vue](file://fms-vue/src/components/ui/button/Button.vue)
|
||||
- [fms-vue/src/components/ui/form/Form.vue](file://fms-vue/src/components/ui/form/Form.vue)
|
||||
- [fms-vue/src/components/fms-table/FmsTable.vue](file://fms-vue/src/components/fms-table/FmsTable.vue)
|
||||
- [fms-vue/src/components/fms-file/FmsFile.vue](file://fms-vue/src/components/fms-file/FmsFile.vue)
|
||||
- [fms-vue/src/components/fms-table/utils/createCellRenderer.js](file://fms-vue/src/components/fms-table/utils/createCellRenderer.js)
|
||||
- [fms-vue/src/components/fms-file/composables/useFileCategory.js](file://fms-vue/src/components/fms-file/composables/useFileCategory.js)
|
||||
- [fms-vue/src/theme/index.js](file://fms-vue/src/theme/index.js)
|
||||
- [fms-vue/package.json](file://fms-vue/package.json)
|
||||
- [fms-vue/tests/components/basic.spec.js](file://fms-vue/tests/components/basic.spec.js)
|
||||
- [fms-vue/tests/components/form.spec.js](file://fms-vue/tests/components/form.spec.js)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
3. [核心组件](#核心组件)
|
||||
4. [架构总览](#架构总览)
|
||||
5. [详细组件分析](#详细组件分析)
|
||||
6. [依赖关系分析](#依赖关系分析)
|
||||
7. [性能考量](#性能考量)
|
||||
8. [故障排查指南](#故障排查指南)
|
||||
9. [结论](#结论)
|
||||
10. [附录](#附录)
|
||||
|
||||
## 简介
|
||||
本文件面向 FMS 前端组件系统的工程化文档,聚焦于组件分层、职责分离与复用策略;系统化阐述 UI 基础组件(如 Button、Form)的设计模式与实现规范;深入解析业务级复杂组件(FmsTable、FmsFile)的架构设计;说明组件间通信机制(props、事件、状态共享);给出样式组织与主题定制方案;并提供组件测试策略与文档生成方法建议。
|
||||
|
||||
## 项目结构
|
||||
FMS Vue 应用采用“UI 基础组件 + 业务组件 + 布局/服务/状态”的分层组织方式:
|
||||
- UI 基础组件位于 components/ui,提供通用原子能力(按钮、表单、选择器、消息等)。
|
||||
- 业务组件位于 components/fms-*,封装领域场景(表格、文件管理等)。
|
||||
- 主题与样式集中在 theme 与 styles,通过 CSS 变量驱动深浅色与品牌色。
|
||||
- 服务与状态在 services 与 stores,统一数据访问与全局状态。
|
||||
- 测试位于 tests,基于 Vitest 与 @vue/test-utils。
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "UI 基础组件"
|
||||
B["Button"]
|
||||
Fm["Form"]
|
||||
end
|
||||
subgraph "业务组件"
|
||||
T["FmsTable"]
|
||||
FF["FmsFile"]
|
||||
end
|
||||
subgraph "主题与样式"
|
||||
TH["theme/index.js"]
|
||||
end
|
||||
subgraph "服务与状态"
|
||||
API["services/api.js"]
|
||||
STORE["stores/app.js"]
|
||||
end
|
||||
T --> B
|
||||
T --> TH
|
||||
T --> STORE
|
||||
FF --> API
|
||||
FF --> TH
|
||||
Fm --> TH
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [fms-vue/src/components/ui/button/Button.vue:1-69](file://fms-vue/src/components/ui/button/Button.vue#L1-L69)
|
||||
- [fms-vue/src/components/ui/form/Form.vue:1-128](file://fms-vue/src/components/ui/form/Form.vue#L1-L128)
|
||||
- [fms-vue/src/components/fms-table/FmsTable.vue:1-800](file://fms-vue/src/components/fms-table/FmsTable.vue#L1-L800)
|
||||
- [fms-vue/src/components/fms-file/FmsFile.vue:1-262](file://fms-vue/src/components/fms-file/FmsFile.vue#L1-L262)
|
||||
- [fms-vue/src/theme/index.js:1-16](file://fms-vue/src/theme/index.js#L1-L16)
|
||||
- [fms-vue/src/stores/app.js](file://fms-vue/src/stores/app.js)
|
||||
|
||||
章节来源
|
||||
- [fms-vue/package.json:1-48](file://fms-vue/package.json#L1-L48)
|
||||
|
||||
## 核心组件
|
||||
- Button:统一的视觉变体、加载态、禁用态与原生类型透传,保证交互一致性与可访问性。
|
||||
- Form:提供 model/rules 驱动的校验、多列网格布局、提交/重置事件与字段注册表,支撑复杂表单场景。
|
||||
- FmsTable:基于 stk-table-vue 的高性能表格,支持虚拟滚动、行编辑、多选、拖拽排序、列头拖拽、主题跟随与应用状态。
|
||||
- FmsFile:三栏分割式文件管理(分类树、列表、预览),封装模块解析、分类加载、预览导航与上传/删除事件。
|
||||
|
||||
章节来源
|
||||
- [fms-vue/src/components/ui/button/Button.vue:1-69](file://fms-vue/src/components/ui/button/Button.vue#L1-L69)
|
||||
- [fms-vue/src/components/ui/form/Form.vue:1-128](file://fms-vue/src/components/ui/form/Form.vue#L1-L128)
|
||||
- [fms-vue/src/components/fms-table/FmsTable.vue:1-800](file://fms-vue/src/components/fms-table/FmsTable.vue#L1-L800)
|
||||
- [fms-vue/src/components/fms-file/FmsFile.vue:1-262](file://fms-vue/src/components/fms-file/FmsFile.vue#L1-L262)
|
||||
|
||||
## 架构总览
|
||||
组件系统遵循以下原则:
|
||||
- 分层清晰:UI 基础组件不感知业务上下文;业务组件组合基础组件并封装领域逻辑。
|
||||
- 职责单一:每个组件只负责一个明确职责(如 Form 负责校验与布局,FmsTable 负责表格渲染与交互)。
|
||||
- 配置优先:通过 props 暴露能力边界,避免内部硬编码;插槽与自定义渲染函数扩展展示。
|
||||
- 主题解耦:通过 CSS 变量与主题工具函数切换深浅色与主色,组件仅消费变量。
|
||||
- 通信契约:以 props 向下传递、事件向上冒泡、provide/inject 或 store 进行跨层级状态共享。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Parent as "父组件"
|
||||
participant Form as "Form"
|
||||
participant Item as "FormItem"
|
||||
participant API as "API/Store"
|
||||
Parent->>Form : 传入 model/rules/layout
|
||||
Form->>Item : provide(fms-form)
|
||||
Item-->>Form : registerField(name, field)
|
||||
Parent->>Form : 触发 submit
|
||||
Form->>Form : validateAll()
|
||||
Form->>Item : 调用 field.validate()
|
||||
Item-->>Form : errors[]
|
||||
alt 无错误
|
||||
Form-->>Parent : emit('submit', values)
|
||||
else 有错误
|
||||
Form-->>Parent : emit('submitFailed', {values, errorFields})
|
||||
end
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [fms-vue/src/components/ui/form/Form.vue:52-110](file://fms-vue/src/components/ui/form/Form.vue#L52-L110)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### Button 组件
|
||||
- 设计要点
|
||||
- 视觉变体:primary/secondary/outline/ghost/danger/link,通过 class 映射。
|
||||
- 状态控制:disabled/loading/block,loading 时禁用并显示加载图标。
|
||||
- 原生兼容:htmlType 透传 button/submit/reset,便于表单集成。
|
||||
- 可访问性:aria-busy 随 loading 动态设置。
|
||||
- 使用建议
|
||||
- 表单内提交/重置按钮使用 htmlType="submit"/"reset"。
|
||||
- 异步操作时使用 loading,避免重复提交。
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class Button {
|
||||
+type : string
|
||||
+disabled : boolean
|
||||
+loading : boolean
|
||||
+block : boolean
|
||||
+htmlType : string
|
||||
+render()
|
||||
}
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [fms-vue/src/components/ui/button/Button.vue:11-63](file://fms-vue/src/components/ui/button/Button.vue#L11-L63)
|
||||
|
||||
章节来源
|
||||
- [fms-vue/src/components/ui/button/Button.vue:1-69](file://fms-vue/src/components/ui/button/Button.vue#L1-L69)
|
||||
|
||||
### Form 组件
|
||||
- 设计要点
|
||||
- 表单模型:model 为对象,rules 为按字段名组织的规则集合。
|
||||
- 布局:horizontal/vertical,columns 启用网格布局,maxWidth 限制最大宽度。
|
||||
- 校验:validateTrigger 支持 change/blur;validateAll 并行校验所有已注册字段。
|
||||
- 事件:submit/submitFailed/reset,提交失败返回 errorFields。
|
||||
- 上下文:provide fms-form,供子项读取布局、对齐、label 宽度等。
|
||||
- 使用建议
|
||||
- 将复杂表单拆分为多个 FormItem,集中维护 rules。
|
||||
- 需要程序化校验时通过 expose 的 validateAll 获取错误字段。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start(["提交"]) --> Prevent["阻止默认提交"]
|
||||
Prevent --> Validate["并行校验所有字段"]
|
||||
Validate --> HasError{"存在错误?"}
|
||||
HasError -- 是 --> EmitFail["emit('submitFailed', {values, errorFields})"]
|
||||
HasError -- 否 --> EmitSubmit["emit('submit', values)"]
|
||||
EmitFail --> End(["结束"])
|
||||
EmitSubmit --> End
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [fms-vue/src/components/ui/form/Form.vue:64-92](file://fms-vue/src/components/ui/form/Form.vue#L64-L92)
|
||||
|
||||
章节来源
|
||||
- [fms-vue/src/components/ui/form/Form.vue:1-128](file://fms-vue/src/components/ui/form/Form.vue#L1-L128)
|
||||
|
||||
### FmsTable 组件
|
||||
- 设计要点
|
||||
- 虚拟滚动:行数超过阈值时启用虚拟滚动,ResizeObserver + rAF 防抖刷新布局,减少重排。
|
||||
- 行编辑:WeakMap 存储每行编辑态,editingActive 控制是否注入编辑器渲染,避免整表重建。
|
||||
- 键盘导航:捕获方向键与 Tab,合并长按与快速连按,延迟激活编辑器以提升流畅度。
|
||||
- 列处理:根据 editor/actions 动态注入 customCell;序号列、选择列、拖拽列自动插入。
|
||||
- 主题:跟随 appStore.darkMode,或通过 theme prop 覆盖。
|
||||
- 事件:change、row-order-change、update:columns,暴露 scrollToRow/editRow/getSelectedArea 等方法。
|
||||
- 使用建议
|
||||
- 大列表务必开启 virtual/virtualX;合理设置 rowKey。
|
||||
- 编辑列仅在需要时启用,减少渲染开销。
|
||||
- 通过 actions 配置行内操作,支持确认弹窗与更多菜单。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant User as "用户"
|
||||
participant Table as "FmsTable"
|
||||
participant Stk as "StkTable"
|
||||
participant Utils as "createCellRenderer"
|
||||
User->>Table : 点击/键盘导航
|
||||
Table->>Table : 计算 displayColumns / editingActive
|
||||
Table->>Utils : resolveCustomCell(col, ctx)
|
||||
Utils-->>Table : 返回 customCell(可选)
|
||||
Table->>Stk : 渲染 columns/data-source
|
||||
Stk-->>Table : area-selection-change / row-order-change
|
||||
Table-->>User : change / row-order-change
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [fms-vue/src/components/fms-table/FmsTable.vue:273-314](file://fms-vue/src/components/fms-table/FmsTable.vue#L273-L314)
|
||||
- [fms-vue/src/components/fms-table/utils/createCellRenderer.js:208-229](file://fms-vue/src/components/fms-table/utils/createCellRenderer.js#L208-L229)
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["尺寸变化 ResizeObserver"] --> B["记录宽高 lastSize"]
|
||||
B --> C{"高度未变且宽度变化?"}
|
||||
C -- 是 --> D["仅刷新 X 方向虚拟滚动"]
|
||||
C -- 否 --> E["刷新全量虚拟滚动"]
|
||||
D --> F["等待稳定后执行一次"]
|
||||
E --> F
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [fms-vue/src/components/fms-table/FmsTable.vue:70-96](file://fms-vue/src/components/fms-table/FmsTable.vue#L70-L96)
|
||||
|
||||
章节来源
|
||||
- [fms-vue/src/components/fms-table/FmsTable.vue:1-800](file://fms-vue/src/components/fms-table/FmsTable.vue#L1-L800)
|
||||
- [fms-vue/src/components/fms-table/utils/createCellRenderer.js:1-229](file://fms-vue/src/components/fms-table/utils/createCellRenderer.js#L1-L229)
|
||||
|
||||
### FmsFile 组件
|
||||
- 设计要点
|
||||
- 模块解析:根据 moduleCode 查询模块信息,失败时提示错误。
|
||||
- 分类树:useFileCategory 拉取分类并转换为树形数据,支持全选根节点。
|
||||
- 三栏布局:Splitter 分隔分类、列表、预览面板,支持最小/默认尺寸。
|
||||
- 预览导航:上一份/下一份切换,选中文件通过 selected 事件上报。
|
||||
- 事件代理:uploaded/deleted 透传给父组件。
|
||||
- 使用建议
|
||||
- initialCateId 可用于初始化展开与选中。
|
||||
- readonly 模式下隐藏上传/删除等操作。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Parent as "父组件"
|
||||
participant File as "FmsFile"
|
||||
participant Cat as "useFileCategory"
|
||||
participant List as "FileListPanel"
|
||||
participant Prev as "FilePreviewPanel"
|
||||
Parent->>File : moduleCode/father/showTree/readonly
|
||||
File->>Cat : loadCategories()
|
||||
Cat-->>File : treeData/loading/selectedKey
|
||||
File->>List : 传入 moduleCode/moduleId/cateId/readonly
|
||||
List-->>File : preview/uploaded/deleted
|
||||
File-->>Prev : 选中文件 prev/next
|
||||
File-->>Parent : uploaded/deleted/selected
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [fms-vue/src/components/fms-file/FmsFile.vue:22-133](file://fms-vue/src/components/fms-file/FmsFile.vue#L22-L133)
|
||||
- [fms-vue/src/components/fms-file/composables/useFileCategory.js:1-77](file://fms-vue/src/components/fms-file/composables/useFileCategory.js#L1-L77)
|
||||
|
||||
章节来源
|
||||
- [fms-vue/src/components/fms-file/FmsFile.vue:1-262](file://fms-vue/src/components/fms-file/FmsFile.vue#L1-L262)
|
||||
- [fms-vue/src/components/fms-file/composables/useFileCategory.js:1-77](file://fms-vue/src/components/fms-file/composables/useFileCategory.js#L1-L77)
|
||||
|
||||
## 依赖关系分析
|
||||
- 外部依赖
|
||||
- stk-table-vue:高性能表格内核,提供虚拟滚动、区域选择、拖拽排序等能力。
|
||||
- lucide/vue:图标库,用于按钮加载态等。
|
||||
- axios:HTTP 请求。
|
||||
- pinia:状态管理。
|
||||
- sortablejs/vuedraggable:拖拽相关。
|
||||
- 内部依赖
|
||||
- FmsTable 依赖 createCellRenderer 动态生成单元格渲染逻辑。
|
||||
- FmsFile 依赖 useFileCategory 管理分类数据与树结构。
|
||||
- 主题通过 theme/index.js 写入 CSS 变量与 dark class,被各组件消费。
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
Btn["Button"] --> Theme["theme/index.js"]
|
||||
Form["Form"] --> Theme
|
||||
Table["FmsTable"] --> Cell["createCellRenderer.js"]
|
||||
Table --> Store["stores/app.js"]
|
||||
File["FmsFile"] --> Cat["useFileCategory.js"]
|
||||
File --> Theme
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [fms-vue/src/theme/index.js:1-16](file://fms-vue/src/theme/index.js#L1-L16)
|
||||
- [fms-vue/src/components/fms-table/utils/createCellRenderer.js:1-229](file://fms-vue/src/components/fms-table/utils/createCellRenderer.js#L1-L229)
|
||||
- [fms-vue/src/components/fms-file/composables/useFileCategory.js:1-77](file://fms-vue/src/components/fms-file/composables/useFileCategory.js#L1-L77)
|
||||
|
||||
章节来源
|
||||
- [fms-vue/package.json:21-34](file://fms-vue/package.json#L21-L34)
|
||||
|
||||
## 性能考量
|
||||
- 表格虚拟滚动
|
||||
- 行数超过阈值才启用虚拟滚动,避免小数据量下的额外开销。
|
||||
- 使用 requestAnimationFrame 合并多次尺寸变化,避免动画期间频繁重排。
|
||||
- 仅宽度变化时只刷新 X 方向虚拟滚动,降低 Y 方向重算成本。
|
||||
- 编辑态优化
|
||||
- 使用 WeakMap 存储行编辑态,editingActive 控制是否注入编辑器,减少非编辑态的函数式组件数量。
|
||||
- 键盘导航期间延迟激活编辑器,合并连续按键,避免频繁挂载/卸载导致掉帧。
|
||||
- 选择列渲染
|
||||
- 选择列使用纯 CSS checkbox 模拟,避免每行创建 Checkbox 组件实例,提升滚动性能。
|
||||
- 表单校验
|
||||
- validateAll 并行校验,缩短整体校验耗时。
|
||||
|
||||
[本节为通用性能指导,无需特定文件引用]
|
||||
|
||||
## 故障排查指南
|
||||
- 表单校验不生效
|
||||
- 检查 Form 是否正确 provide fms-form,FormItem 是否注册字段。
|
||||
- 确认 rules 结构与 name 对应,validateTrigger 是否符合预期。
|
||||
- 表格编辑卡顿
|
||||
- 确认 large data 场景下 virtual/virtualX 已开启。
|
||||
- 检查是否频繁更新 columns 或 dataSource 导致整表重建。
|
||||
- 文件模块解析失败
|
||||
- 检查 moduleCode 是否存在且可用,查看 moduleError 提示信息。
|
||||
- 主题不生效
|
||||
- 确认 applyDarkMode 与 applyPrimaryColor 已调用,CSS 变量已写入 :root。
|
||||
|
||||
章节来源
|
||||
- [fms-vue/src/components/ui/form/Form.vue:94-110](file://fms-vue/src/components/ui/form/Form.vue#L94-L110)
|
||||
- [fms-vue/src/components/fms-table/FmsTable.vue:41-96](file://fms-vue/src/components/fms-table/FmsTable.vue#L41-L96)
|
||||
- [fms-vue/src/components/fms-file/FmsFile.vue:27-54](file://fms-vue/src/components/fms-file/FmsFile.vue#L27-L54)
|
||||
- [fms-vue/src/theme/index.js:1-16](file://fms-vue/src/theme/index.js#L1-L16)
|
||||
|
||||
## 结论
|
||||
FMS 组件系统通过清晰的层次划分、严格的职责边界与完善的通信契约,实现了高内聚、低耦合的可复用组件体系。UI 基础组件提供一致的交互与样式基线,业务组件在此基础上封装领域能力;主题与样式通过 CSS 变量统一管理,便于深浅色与品牌定制;性能优化贯穿关键路径,保障大数据量场景下的流畅体验。配合完善的单元测试与可扩展的文档策略,组件系统具备良好的可维护性与演进能力。
|
||||
|
||||
## 附录
|
||||
|
||||
### 组件间通信机制
|
||||
- Props 传递:从父到子的配置型数据(如 type、layout、columns、moduleCode)。
|
||||
- 事件发射:从子到父的状态变更与用户动作(如 submit、change、uploaded、selected)。
|
||||
- 状态共享:
|
||||
- provide/inject:Form 向 FormItem 下发布局与校验上下文。
|
||||
- Store:FmsTable 读取应用主题状态(darkMode)。
|
||||
- Composable:useFileCategory 封装分类数据与树转换逻辑。
|
||||
|
||||
章节来源
|
||||
- [fms-vue/src/components/ui/form/Form.vue:94-110](file://fms-vue/src/components/ui/form/Form.vue#L94-L110)
|
||||
- [fms-vue/src/components/fms-table/FmsTable.vue:52-53](file://fms-vue/src/components/fms-table/FmsTable.vue#L52-L53)
|
||||
- [fms-vue/src/components/fms-file/composables/useFileCategory.js:1-77](file://fms-vue/src/components/fms-file/composables/useFileCategory.js#L1-L77)
|
||||
|
||||
### 样式组织与主题定制
|
||||
- 样式组织
|
||||
- 组件级样式使用 scoped SCSS,局部作用域隔离。
|
||||
- 表格边框与选择框样式通过非 scoped 样式精准覆盖第三方库默认样式。
|
||||
- 主题定制
|
||||
- 通过 theme/index.js 的 applyPrimaryColor 与 applyDarkMode 修改 CSS 变量与 dark class。
|
||||
- 组件消费 --fms-primary、--fms-border、--fms-card 等变量,确保主题一致性。
|
||||
|
||||
章节来源
|
||||
- [fms-vue/src/theme/index.js:1-16](file://fms-vue/src/theme/index.js#L1-L16)
|
||||
- [fms-vue/src/components/fms-table/FmsTable.vue:600-800](file://fms-vue/src/components/fms-table/FmsTable.vue#L600-L800)
|
||||
|
||||
### 组件测试策略
|
||||
- 框架与工具
|
||||
- 使用 Vitest 作为测试运行器,@vue/test-utils 进行组件挂载与断言。
|
||||
- 测试范围
|
||||
- UI 基础组件:验证 props 映射、事件发射、可访问性属性。
|
||||
- 表单组件:验证网格布局、span 跨列、必填校验与错误展示。
|
||||
- 实践建议
|
||||
- 对交互类组件编写行为测试(点击、输入、键盘)。
|
||||
- 对渲染类组件断言 class、文本与 DOM 结构。
|
||||
- 对异步流程使用 flushPromises 与 nextTick 同步状态。
|
||||
|
||||
章节来源
|
||||
- [fms-vue/tests/components/basic.spec.js:1-150](file://fms-vue/tests/components/basic.spec.js#L1-L150)
|
||||
- [fms-vue/tests/components/form.spec.js:1-128](file://fms-vue/tests/components/form.spec.js#L1-L128)
|
||||
|
||||
### 文档生成方法
|
||||
- 当前仓库未内置自动化文档站点(如 Storybook/VuePress),建议在开发过程中:
|
||||
- 为每个组件编写 README 或使用 JSDoc 注释描述 props/emits/slots。
|
||||
- 结合 demo 页面与示例代码,形成可视化文档。
|
||||
- 参考参考组件库中的文档构建思路,逐步引入文档站点与示例渲染管线。
|
||||
|
||||
[本节为通用建议,无需特定文件引用]
|
||||
Reference in new issue
Block a user