# @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 -->
