base/CAPABILITY.md

373 lines
20 KiB
Markdown
Raw 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.

# @apigo.cc/base 能力清单 (Capability Specification)
<!-- section: header -->
## 一、 全局导出与生命周期行为
### 1. 导出与全局挂载
- **模块导出**`index.js` 重新导出了 `http.js`, `ui.js`, `form.js`, `controls.js`, `list.js`, `nav.js`, `interaction.js` 中的所有对象,以及来自 `@apigo.cc/state``State`
- **全局命名空间挂载**:在 `window/globalThis` 上挂载了 `HTTP`, `UI`, `AutoForm`, `MouseMover`, `VirtualScroll`, `ApigoBase`
- **初始化自动刷新**:页面加载时(`DOMContentLoaded` 或立即执行),对 `document.documentElement` 执行 `__RefreshState_Internal_Force_Full_Scan_Only_In_Extreme_Performance_Scenarios()`
### 2. 退出拦截逻辑
- **拦截触发条件**:当 `State.exitBlocks > 0` 时,通过 `window.addEventListener('beforeunload')` 拦截页面刷新或关闭(调用 `event.preventDefault()`)。
### 3. 主题自动适配
- **逻辑行为**:若 `<html>` 元素上既没有 `data-bs-theme` 也没有 `$data-bs-theme`,则自动注入属性:
`$data-bs-theme="LocalStorage.darkMode?'dark':'light'"`
<!-- endsection: header -->
---
<!-- section: http -->
## 二、 HTTP 请求引擎 (`HTTP`)
### 1. 核心方法
- **`HTTP.request(options)`** (异步)
- **参数类型**`options: Object`
- `url` (String, 必填): 请求地址。
- `method` (String, 可选): 默认 `'POST'`。会内部自动转为大写。
- `data` (Any, 可选): 请求载荷。
- `headers` (Object, 可选): 默认 `{}`
- `responseType` (String, 可选): `'json' | 'binary' | 'text'`。若未提供,将根据响应头 `Content-Type` 自动解析(含 `application/json` 解析为 `'json'`,匹配图片/音视频/zip/pdf等解析为 `'binary'`,其余解析为 `'text'`)。
- `timeout` (Number, 可选): 默认 `10000` (ms)。基于 `AbortSignal.timeout` 实现。
- **请求载荷 (`data`) 自动处理逻辑**
-`data``HTMLFormElement`,内部自动转换为 `FormData`
-`data` 为普通对象,且其属性中包含 `File`, `Blob`, `FileList` 实例,内部自动转换为 `FormData`。其中,`FileList``Array` 属性会依次 append 到相同 key 下,排除 `undefined` / `null`
- 若数据最终为 `FormData`,则 **自动删除** `headers['Content-Type']`(由浏览器自动设置 boundary
- 若数据为普通对象且非二进制,且 `headers` 中无 `Content-Type`,则序列化为 JSON 字符串并自动添加 `headers['Content-Type'] = 'application/json'`
- **返回值**`Promise<ResponseObject>`,其结构为:
```javascript
{
ok: Boolean, // 请求是否成功 (status 在 200-299)
status: Number, // HTTP 状态码
headers: Object, // 响应头键值对
responseType: String, // 实际解析后的响应类型 ('json' | 'binary' | 'text')
result: Any, // 响应数据主体
error: String | null // 错误信息 (若请求失败或 ok === false)
}
```
- **快捷方法** (内部包装 `HTTP.request`)
- `HTTP.get({ url, ...opt })`
- `HTTP.post({ url, data, ...opt })`
- `HTTP.put({ url, data, ...opt })`
- `HTTP.delete({ url, ...opt })`
- `HTTP.head({ url, ...opt })`
<!-- endsection: http -->
---
<!-- section: api -->
## 三、 声明式数据组件 (`<API>`)
### 1. 响应式状态模型 (`State`)
- **`request`** (读写): 映射请求参数。结构与 `HTTP.request` 参数一致:
`{ url: '', method: 'GET', headers: {}, data: null, timeout: 10000, responseType: '' }`
- **`response`** (读写): 包含当前请求执行结果。结构为:
`{ loading: false, ok: null, status: null, error: null, headers: {}, responseType: '', result: null }`
- **`result`** (读写): 响应结果快捷引用。当 `response.result` 为对象时,底层通过 `Object.assign` 合并更新;否则直接覆盖。
### 2. 编程接口方法 (`Methods`)
- **`do(opt = {})`**
- **用途**:手动执行请求。
- **参数**`opt` 对象的字段(如 `headers`, `data` 等)会与 `request` 属性合并。
- **控制参数**`opt.noui` (Boolean)。若为 `true`,则在请求失败时不自动调用 `UI.toast` 弹窗。
- **返回值**`Promise<ResponseObject>`。若请求失败或接口返回 `{ error: ... }`Promise 会抛出异常reject
### 3. 特殊逻辑行为
- **`auto` (Attribute)**
若组件含有 `auto` 属性,且 `request.url` 非空,则深度监听 `request` 对象的变化。一旦变化会在下一微任务队列Promise.resolve())自动、异步触发 `do()`。有防抖机制,避免同一周期多次触发。
### 4. 事件派发
- **`response`**:请求成功时触发。
- `bubbles`: `false`
- `cancelable`: `false`
- `detail`: 完整的 `ResponseObject` 对象。
- **`error`**请求失败网络错误、非2xx状态码、或返回数据中含 `error` 字段)时触发。
- `bubbles`: `true`
- `cancelable`: `false`
- `detail`: Error 对象。
<!-- endsection: api -->
---
<!-- section: form -->
## 四、 万能表单系统 (`<AutoForm>`)
### 1. 容器属性 (Attributes)
- **`vertical`** (Boolean): 开启垂直表单布局。
- **`inline`** (Boolean): 开启无边框的流式行内布局(常用于顶部工具栏)。
- **`nobutton`** (Boolean): 隐藏底部的默认提交/保存按钮。
- **`api`** (String / Element): 绑定页面中 `<API>` 组件的 ID或直接为组件实例引用以便在提交时自动对接。
- **`submitlabel`** (String): 自定义提交按钮的文本内容。默认为 `"{#Submit#}"`。
### 2. 实例编程接口
- **`data`** (读写): 表单内部数据的响应式 Proxy 模型(映射至 `state.data`)。可直接通过 `Object.assign(form.data, newData)` 或逐个属性赋值来修改表单中的值。
- **`request`** (读写): 默认提交配置,默认为 `{ method: 'POST' }`。
- **`response`** (只读): 提交请求返回的完整响应对象。
- **`result`** (只读): 提交请求返回的 `response.result`。
- **`submit(opt = {})`**
- **用途**:手动触发表单校验与提交。
- **校验逻辑**:通过原生 `form.reportValidity()` 校验。若失败,调用 `UI.toast` 提示 `"{#verify failed#}"` 并退出。
- **提交逻辑**:如果绑定了 `api` 属性,则调用 `api.do(req)`(其中 `req.data` 自动绑定为表单 `data`);否则,如果配置了 `request.url`,则直接调用 `HTTP.request(req)`;两者皆无则在控制台抛出警告。
### 3. Schema 项目 (`FormItem`) 结构定义
`state.schema` 数组中每一项可配置的字段:
- **`name`** (String, 必填): 数据字段键名,与 `form.data` 中的属性双向绑定。
- **`label`** (String, 可选): 表单项标签名称(仅在非 `inline` 模式下展示)。
- **`type`** (String, 必填): 表单控件类型。
- 原生支持:`'text'`, `'password'`, `'email'`, `'number'`, `'date'`, `'datetime'`, `'file'`, `'select'`, `'checkbox'`, `'radio'`, `'switch'`, `'textarea'`。
- 扩展注册支持:如 `'DatePicker'`, `'ColorPicker'`, `'IconPicker'`, `'TagsInput'`。
- **`if`** (String, 可选): 控制是否显示该表单项的条件表达式字符串。使用双重计算渲染(`$$if`),其执行上下文中 `this` 指向 AutoForm 组件实例,可以通过 `this.data` 引用其他字段值。
- **`setting`** (Object, 可选): 原生属性透传对象,会通过 `$.="item.setting || {}"` 绑定到控件上。
- **`options`** (Array, 可选): 针对 `select`, `checkbox`, `radio` 类型。
- 格式可以为扁平字符串数组:`['Option1', 'Option2']`
- 也可以为键值对数组:`[{ label: '选项1', value: 'val1' }]`
- **`placeholder`** (String, 可选): 仅对 `select` 类型有效,表示未选中时的禁用占位选项。
- **`vertical`** (Boolean, 可选): 仅对 `checkbox` 或 `radio` 类型有效。若为 `true`,各选项纵向排列;默认为 `false`(横向排列)。
- **`text` / `label`** (String, 可选): 当 `checkbox` 或 `radio` 未提供 `options` 选项时,使用此值作为单选项的标签,其选中时的值是 `'on'`。
### 4. 插槽 (Slots)
- **`actions`**:在表单底部提交按钮左侧的区域插槽(仅在非 `inline` 且非 `nobutton` 模式下渲染)。
### 5. 事件派发
- **`submit`**:在开始提交数据前触发。
- `bubbles`: `false`
- `cancelable`: `true`(调用 `event.preventDefault()` 可彻底终止提交动作)
- `detail`: 当前表单的数据对象 `container.data`。
- **`response`**:表单自动提交成功并得到接口响应后触发。
- `bubbles`: `false`
- `cancelable`: `false`
- `detail`: 完整的响应对象 `resp`。
- **`error`**:提交失败(网络错、校验错或返回的 json 带有 error 字段)时触发。
- `bubbles`: `true`
- `cancelable`: `false`
- `detail`: Error 对象。
### 6. 表单控件扩展机制 (`AutoForm.register`)
- **`AutoForm.register(name, typeName)`**
- **用途**:将第三方/自定义 Web Component 注册为表单的自定义控件类型。
- **参数**
- `name` (String): 组件标签名(如 `'DatePicker'`)。
- `typeName` (String, 可选): schema 中对应的 `type` 字符串。不传则默认等同于 `name`。
- **实现逻辑**:当在 AutoForm 的 `schema` 中匹配到对应 `type` 时,自动在 DOM 树中插入该自定义组件,并将其属性 `$.` 绑定为 `item.setting`,其值 `bind` 双向绑定到 AutoForm 的对应数据字段。
<!-- endsection: form -->
---
<!-- section: extension-controls -->
## 五、 表单自定义扩展组件
### 1. 日期选择器 (`<DatePicker>`)
- **核心能力**:支持单日期选择,或双日期范围选择(主字段 + 影子字段模式)。
- **启用范围选择**:在 AutoForm 的对应 Schema 项目中,配置 `setting.rangeEnd: "endFieldName"`;或在组件上直接配置 `rangeEnd` 属性。
- **内部状态 (`state`)**
- `start` (String): 开始日期。
- `end` (String): 结束日期。
- **实例属性**
- `value` (读写): 映射至 `state.start`。
- `isRange` (只读): 根据是否配置了 `rangeEnd` 返回 `Boolean` 值。
- **操作方法**
- `updateStart(val)`: 更新 `state.start` 并分发 `change` 事件。
- `updateEnd(val)`: 更新 `state.end`,若处于 AutoForm 容器中,将该值同步写入到表单数据的 `rangeEnd` 对应字段中。
- **事件派发**
- `'change'`:当主字段/开始日期发生改变时触发。
- `bubbles`: `true`
- `detail`: 改变后的开始日期字符串(`state.start`)。
### 2. 颜色选择器 (`<ColorPicker>`)
- **核心能力**:提供颜色取色器(`type="color"`)与十六进制文本输入框的双向联动。
- **内部状态 (`state`)**
- `value` (String): 颜色值,默认为 `'#000000'`。
- **实例属性**
- `value` (读写): 映射至 `state.value`。
- **方法**
- `updateValue(val)`: 更新颜色状态并分发事件。
- **事件派发**
- `'change'`:当值发生改变时触发。
- `bubbles`: `true`
- `detail`: 改变后的十六进制颜色字符串。
### 3. 图标选择器 (`<IconPicker>`)
- **核心能力**:基于 Bootstrap Icons 的可视化下拉搜索选择器。
- **内部状态 (`state`)**
- `value` (String): 当前选中的图标名。
- `search` (String): 图标搜索关键字。
- `open` (Boolean): 下拉菜单的展开状态。
- **实例属性**
- `value` (读写): 映射至 `state.value`。
- `filteredIcons` (只读): 经过 `search` 关键字过滤后的图标名称列表。
- **方法**
- `selectIcon(icon)`: 选中指定图标,收起下拉框并派发 `change` 事件。
- `toggle()`: 切换下拉框展开状态。若展开,会自动延时聚焦在搜索输入框中。
- **事件派发**
- `'change'`:当选中图标发生改变时触发。
- `bubbles`: `true`
- `detail`: 选中的图标类名。
- *点击外部收起*:监听全局 `click` 事件,点击外部自动收起下拉框;组件被移除 DOM 时自动注销该监听。
### 4. 标签输入框 (`<TagsInput>`)
- **核心能力**:可视化添加和删除标签。
- **添加交互**:在输入框中输入内容后,按 `Enter`, `,` (逗号) 或 ` ` (空格) 会自动将标签加入。
- **删除交互**:点击标签聚焦后,按 `Backspace` 或 `Delete` 键可将其移除,并自动聚焦到前一个标签。
- **内部状态 (`state`)**
- `tags` (Array): 存储标签字符串的数组。
- **实例属性**
- `value` (读写): 映射至 `state.tags`。
- **事件派发**
- `'change'`:当标签数组发生增删改变时触发。
- `bubbles`: `true`
- `detail`: 最新标签的字符串数组。
<!-- endsection: extension-controls -->
---
<!-- section: list -->
## 六、 增强列表组件 (`<List>`)
### 1. 列表布局模式 (`mode` Attribute)
- **`normal`** (默认): 扁平列表模式。
- **`group`** (分组):
- 关联逻辑:通过 `list` 中成员的 `groupfield` 匹配 `groups` 数组中项的 `groupidfield`。
- **`tree`** (树形):
- 关联逻辑:扁平化数组,通过每一项的 `parentfield` 匹配父项的 `idfield`。根项的值为空字符串 `''`。
### 2. 字段映射配置属性 (可重写默认值)
在组件初始化时,会调用 `Util.updateDefaults` 将以下属性更新为默认值:
- `idfield`: 项的主键字段名,默认 `'id'`。
- `labelfield`: 项展示文本字段名,默认 `'label'`。
- `summaryfield`: 项辅助文本字段名,默认 `'summary'`。
- `groupidfield`: 分组的主键字段名,默认 `'id'`。
- `grouplabelfield`: 分组展示文本字段名,默认 `'label'`。
- `groupsummaryfield`: 分组辅助文本字段名,默认 `'summary'`。
- `groupfield`: 项关联分组的字段名,默认 `'group'`。
- `parentfield`: 树形下关联父节点的字段名,默认 `'parent'`。
- `groupicon`: 组/父节点的图标类,默认 `'folder'` (对应 Bootstrap Icons 的类名)。
- `itemicon`: 项/叶子节点的图标类,默认 `'file'`。
### 3. 功能属性 (Attributes)
- **`fast`** (Boolean): 启用虚拟滚动。
- **重要约束**`<List>` 容器必须包含 Bootstrap 的 `overflow-auto` 类,且内置 `style="overflow-anchor:none"`(模板自带)。
- **`collapsible`** (Boolean): 仅在 `tree` 模式下有效,开启树形节点的展开/收起能力。
- **`auto-select`** (Boolean): 开启后,点击列表项时自动将该项的 `id` 记录至 `state.selectedItem`,如果重复点击则会置空。
- **`auto-select-group`** (Boolean): 开启后,点击分组时自动将分组的 `id` 记录至 `state.selectedGroup`。
### 4. 内部状态模型 (`State`)
- `list` (读写): 原始列表数据数组。
- `groups` (读写): 仅在 `group` 模式下使用,分组定义数组。
- `collapsed` (读写): 仅在 `tree` 且 `collapsible` 时使用,存储节点 ID 折叠状态的 Map Proxy。
- `selectedItem` (读写): 当前选中的列表项 ID。
- `selectedGroup` (读写): 当前选中的分组 ID。
- `_flatList` (只读): 列表核心逻辑处理后的扁平化数组。
- `_renderedList` (只读): 实际在 DOM 中遍历渲染的数组片段(若开启虚拟滚动,则只包含可视区切片)。
### 5. 插槽 (Slots)
- **`item`**:列表单项渲染模板插槽。在自定义模板中,可以访问当前行数据 `item` 和索引 `index`。
- **`item-actions`**:行数据右侧按钮工具栏区域。
- **`group-actions`**:分组数据行右侧按钮工具栏区域。
### 6. 虚拟滚动运行参数
- **高度优先规则**
若列表数据的某一项上配置了数字属性 `_itemHeight`,虚拟滚动引擎会将其作为该项的测量高度,直接跳过 DOM 的高度测量。
### 7. 事件派发
- **`itemclick`**:点击列表项(非分组)时触发。
- `bubbles`: `false`
- `detail`: `{ item, index }` (其中 `index` 为考虑虚拟滚动偏移量后的 **绝对全局索引**)。
- **`groupclick`**:点击分组行时触发。
- `bubbles`: `false`
- `detail`: `{ item, index }`。
<!-- endsection: list -->
---
<!-- section: nav -->
## 七、 导航组件 (`<Nav>`)
### 1. 结构与属性
- **`vertical`** (Attribute, Boolean): 决定导航为垂直面板布局(带有右侧分割线)或水平导航栏布局(带底部阴影)。
### 2. 响应式数据模型 (`State`)
- **`brand`** (Object, 可选): `{ image, icon, label }`,控制左上角/顶部的 Logo、图标及品牌文本。
- **`list`** (Array, 必填): 导航栏项的数组。
### 3. 导航项结构(`list` 成员)
- **`type`**: 决定导航项的渲染模式:
- `'button'`: 导航按钮。
- `'dropdown'`: 下拉菜单导航。含有 `list` (子项数组),子项类型可为:
- `'button'`: 子项按钮。
- `'switch'`: 状态开关。需要配置 `bind` (状态Proxy引用) 和 `name` (要绑定的字段名)。
- 水平布局下可以通过 `width` (Number) 控制下拉菜单宽度,默认 `250`。
- `'fill'`: 弹性填充块(`flex-fill`),用于实现右对齐等布局。
- **`name`** (String): 导航标识。当点击导航按钮时,该 `name` 会自动被写入 `Hash.nav` 以同步 URL 哈希。
- **`label`** (String): 文本展示。
- **`icon`** (String): 图标类名(基于 Bootstrap Icons
- **`noselect`** (Boolean, 可选): 若为 `true`,点击该项仅派发点击事件,**不会** 修改 `Hash.nav`。
### 4. 事件派发
- **`nav`**:点击任何菜单项或下拉子菜单项时触发。
- `bubbles`: `false`
- `detail`: `{ item }` (被点击的导航项数据定义)。
<!-- endsection: nav -->
---
<!-- section: resizer -->
## 八、 拖拽改变大小组件 (`<Resizer>`)
### 1. 组件属性
- **`vertical`** (Attribute, Boolean): 为 `true` 时,鼠标为 `row-resize`,调整高度;默认调整宽度。
- **`min`** (Attribute, Number): 像素下限,默认 `10`。
- **`max`** (Attribute, Number): 像素上限,默认 `1000`。
- **`target`** (Element): 要调整大小的目标 DOM 元素。默认是组件的前一个兄弟节点 (`container.previousElementSibling`)。
### 2. 事件与双向绑定
- **`bind`** (输入拦截): 支持通过绑定表达式传入像素值(数字),自动设置为 target 的 `width`/`height`。
- **`resizing`**:拖动调整大小的过程中持续触发。
- `bubbles`: `false`
- `detail`: `{ oldSize, newSize }`
- **`resize`**:拖动结束时触发。
- `bubbles`: `false`
- `detail`: `{ oldSize, newSize }`
- **`change`**:拖动结束时触发,输出最终的大小数值。常用于将新尺寸写回全局 `State`。
- `bubbles`: `false`
- `detail`: `newSize` (Number)
<!-- endsection: resizer -->
---
<!-- section: ui -->
## 九、 编程交互工具集 (`UI`)
### 1. 核心对话框方法 (`UI.showDialog`)
- **`UI.showDialog({ title, message, buttons, type })`**
- **参数**
- `title` (String, 可选): 对话框标题。
- `message` (String, 必填): 提示消息,支持 HTML 标记(`$html` 渲染)。
- `buttons` (Array, 可选): 按钮文字数组,默认 `['{#Close#}']`。
- `type` (String, 可选): 主题类型 `'primary' | 'danger' | 'warning' | 'success'` 等,控制边框、标题及最后一个主按钮的颜色。
- **返回值**`Promise<Number>`。
- 点击按钮返回其索引值 (从 `1` 开始)。
- 点击关闭图标或按 ESC 取消返回 `0`。
### 2. 快捷对话框
- **`UI.alert(message, options)`**:包装 `UI.showDialog`。
- **`UI.confirm(message, options)`**:确认框。
- 默认按钮:`['{#Cancel#}', '{#Confirm#}']`。
- 返回值:`Promise<Boolean>` (选中确认按钮为 `true`,取消为 `false`)。
### 3. 轻提示方法 (`UI.toast`)
- **`UI.toast(message, options)`**
- **参数**
- `message` (String, 必填): 消息文本。
- `options` (Object, 可选)
- `delay` (Number): 自动关闭延迟时间(毫秒),默认 `5000`。若传入 `0` 则永久不消失。
- `type` (String): 主题背景色 `'primary' | 'success' | 'danger' | 'warning'` 等。
- `buttons` (Array): 自定义 Toast 内嵌按钮,点击会设置 `result = index + 1` 并在点击后自动 dismiss。
- `container` (String): 目标 Toast 容器 ID默认 `'default'`。
### 4. 快捷 Toast 确认
- **`UI.toastConfirm(message, options)`**
- 弹出带有一个 `Confirm` 按钮的 Toast。
- 返回值:`Promise<Boolean>`(点击确认按钮返回 `true`,其余情况返回 `false`)。
<!-- endsection: ui -->