# @apigo.cc/base `@apigo.cc/base` 是基于 `@apigo.cc/state` 和 Bootstrap 5.3 的同步组件层。页面只需要按顺序引入脚本,就能在首屏完成 DOM 处理和组件渲染。 ## 目录 - [依赖加载](#依赖加载) - 同步加载顺序和来源说明 - [全局变量](#全局变量) - 本包直接挂到 `window` 的变量 - [HTTP](#http) - 请求工具 - [API](#api) - 声明式请求节点 - [AutoForm](#autoform) - 自动表单节点 - [表单扩展控件](#表单扩展控件) - `DatePicker` / `ColorPicker` / `IconPicker` / `TagsInput` - [List](#list) - 普通、分组、树形和虚拟滚动列表 - [Nav](#nav) - 水平导航栏或垂直侧边栏 - [Modal / Dialog](#modal--dialog) - 弹窗容器和确认弹窗 - [Resizer](#resizer) - 拖拽分隔条 - [UI](#ui) - toast 和对话框工具 - [VirtualScroll / MouseMover](#virtualscroll--mousemover) - 虚拟滚动和鼠标拖拽辅助 ## 依赖加载 按顺序同步加载: `@apigo.cc/state` -> `@apigo.cc/bootstrap` -> `@apigo.cc/base` `base` 会直接使用来自 `@apigo.cc/state` 的全局对象 `State`、`Hash`、`LocalStorage`。 - [state 文档](https://apigo.cc/web/state) ### 推荐加载顺序 ```html ``` ### 全局变量 | 变量 | 说明 | |---|---| | `HTTP` | 请求工具 | | `UI` | 提示、确认、对话框工具 | | `AutoForm` | 自动表单容器和扩展注册器 | | `VirtualScroll` | 虚拟滚动工具 | | `MouseMover` | 鼠标拖拽位移工具 | ## HTTP `HTTP` 只处理请求,不处理 UI。 ### 方法 | 方法 | 写法示例 | 说明 | |---|---|---| | `HTTP.request(options)` | `await HTTP.request({ url: '/api/user', method: 'POST', data: { id: 1 } })` | 通用请求入口 | | `HTTP.get(...)` | `await HTTP.get({ url: '/api/user/1' })` | `GET` | | `HTTP.post(...)` | `await HTTP.post({ url: '/api/user', data: form })` | `POST` | | `HTTP.put(...)` | `await HTTP.put({ url: '/api/user/1', data: patch })` | `PUT` | | `HTTP.delete(...)` | `await HTTP.delete({ url: '/api/user/1' })` | `DELETE` | | `HTTP.head(...)` | `await HTTP.head({ url: '/api/user/1' })` | `HEAD` | ### `HTTP.request` 参数 | 参数 | 类型 | 写法示例 | 说明 | |---|---|---|---| | `url` | `string` | `url: '/api/user'` | 必填 | | `method` | `string` | `method: 'POST'` | 默认 `POST`,内部会转大写 | | `data` | `any` | `data: { name: 'Alice' }` | 请求体 | | `headers` | `object` | `headers: { Authorization: 'Bearer xxx' }` | 请求头 | | `responseType` | `string` | `responseType: 'json'` | 可手动指定 | | `timeout` | `number` | `timeout: 5000` | 默认 `10000` ms | ### `HTTP` 对象属性 | 属性 | 写法示例 | 说明 | |---|---|---| | `keepHeaders` | `HTTP.keepHeaders = ['Session-Id']` | 需要跨请求保留的响应头名 | ### Content-Type 规则 - `data` 是普通对象时,默认按 JSON 发送,并自动补 `Content-Type: application/json` - `data` 是 `FormData` 时,不手动设置 `Content-Type`,让浏览器生成带 boundary 的 multipart 请求头 - 如果你在 `headers` 里手动传了 `Content-Type`,普通对象请求会按你的设置发送;`FormData` 仍然以浏览器生成的请求头为准 ### 返回值 ```js { ok, status, headers, responseType, result, error } ``` ### 推荐示例 ```html ``` ## API `` 是把请求封装成页面节点的方式。 ### 属性和状态 | 名称 | 写法示例 | 说明 | |---|---|---| | `auto` | `` | 监听 `request` 变化后自动请求 | | `request` | `$.request="window.userRequest"` | 请求配置对象 | | `response` | `$.response="window.apiResponse"` | 最近一次请求状态 | | `result` | `$.result="window.apiResult"` | 响应结果缓存 | ### `request` 默认结构 ```js { url: '', method: 'GET', headers: {}, data: null, timeout: 10000, responseType: '' } ``` ### `response` 默认结构 ```js { loading: false, ok: null, status: null, error: null, headers: {}, responseType: '', result: null } ``` ### 方法 | 方法 | 写法示例 | 说明 | |---|---|---| | `do(opt = {})` | `await userApi.do()` | 手动请求 | | `opt.noui` | `await userApi.do({ noui: true })` | 失败时不弹 toast | ### 事件 | 事件 | 触发时机 | `detail` | |---|---|---| | `response` | 请求成功 | 完整响应对象 | | `error` | 请求失败或返回错误 | `Error` 对象 | ### 备注 - `auto` 只在 `request.url` 存在时生效 - `request` 深度变化会在微任务里触发一次请求,避免同一轮重复请求 ## AutoForm `` 通过 `schema` 生成表单,适合和 `API`、`window` 上的页面数据直接联动。 ### 属性 | 名称 | 写法示例 | 说明 | |---|---|---| | `vertical` | `` | 垂直布局 | | `horizontal` | `` | 强制左右两列布局 | | `inline` | `` | 行内紧凑布局 | | `nobutton` | `` | 隐藏底部提交按钮 | | `api` | `$.api="saveApi"` | 绑定 `` 实例或其引用 | | `submitlabel` | `submitlabel="Search"` | 提交按钮文案,默认 `{#Submit#}` | ### 状态和方法 | 名称 | 写法示例 | 说明 | |---|---|---| | `data` | `$.state.data="window.profile"` | 表单数据,建议用 `Object.assign` 更新 | | `schema` | `$.state.schema="window.profileSchema"` | 表单定义 | | `request` | `$.request="{ method: 'POST' }"` | 默认提交配置 | | `response` | `$.response="window.formResponse"` | 最近一次提交结果 | | `result` | `$.result="window.formResult"` | 最近一次提交的 `response.result` | | `submit(opt = {})` | `form.submit()` | 主动提交 | ### `schema` 字段 | 字段 | 写法示例 | 说明 | |---|---|---| | `name` | `name: 'role'` | 必填,数据键名 | | `label` | `label: 'Role'` | 表单项标题 | | `type` | `type: 'select'` | 控件类型 | | `setting` | `setting: { required: true }` | 透传给控件的属性 | | `options` | `options: ['A', 'B']` | `select` / `checkbox` / `radio` 选项 | | `placeholder` | `placeholder: 'Please choose'` | `select` 的空值占位文案 | | `if` | `if: 'this.data.enable'` | 条件渲染表达式 | ### `if` 说明 - `if` 不是字符串模板拼接,而是表达式 - 表达式执行时可直接访问 `this`、`State`、`Hash`、`LocalStorage`、`item`、`data` - 这类条件是表单级动态渲染,适合做联动显隐 ### 支持的 `type` | `type` | 用途 | |---|---| | `text` | 单行文本 | | `password` | 密码 | | `email` | 邮箱 | | `number` | 数字 | | `date` | 日期 | | `datetime` | 日期时间 | | `file` | 文件 | | `select` | 下拉单选 | | `checkbox` | 多选 | | `radio` | 单选按钮组 | | `switch` | 开关 | | `textarea` | 多行文本 | | `DatePicker` | 扩展日期控件 | | `ColorPicker` | 扩展颜色控件 | | `IconPicker` | 扩展图标控件 | | `TagsInput` | 扩展标签控件 | ### `options` 写法 ```js ['Admin', 'Editor'] [{ label: 'Admin', value: 'admin' }] ``` ### 事件 | 事件 | 触发时机 | `detail` | |---|---|---| | `submit` | 表单校验通过、提交前 | 当前表单数据 | | `response` | 提交成功 | 完整响应对象 | | `error` | 提交失败 | `Error` 对象 | ### 插槽 | 插槽 | 位置 | 用途 | |---|---|---| | `actions` | 默认提交按钮左侧 | 自定义动作按钮 | ### 推荐示例 ```html ``` ### 编程注意 - 不要直接整体覆盖 `form.data` 或 `form.state.data` - 需要更新时,优先用 `Object.assign(form.data, nextData)` ### `AutoForm.register(name, typeName = '')` 注册可被 `schema.type` 识别的自定义控件。 | 参数 | 写法示例 | 说明 | |---|---|---| | `name` | `AutoForm.register('MyPicker')` | 组件标签名 | | `typeName` | `AutoForm.register('MyPicker', 'picker')` | 默认 `''`。只有当标签名和 `schema.type` 不同,或需要复用同一个标签名匹配另一个 `type` 时才传 | ### 什么时候传 `typeName` - 你想让 `` 处理 `schema.type === 'picker'` - 你想把一个标签名映射成不同的 `type` - 如果 `schema.type` 和标签名一致,直接省略第二个参数 ## 表单扩展控件 这些控件既可以在 `AutoForm` 里作为 `schema.type` 使用,也可以单独放到页面上。单独使用时,直接绑定 `value`,再监听 `change` 即可。 ### `` | 项目 | 说明 | |---|---| | `state.start` | 起始日期 | | `state.end` | 结束日期 | | `value` | 映射到 `state.start` | | `isRange` | 是否启用范围模式 | | `setting.rangeEnd` | 范围结束字段名 | | `rangeEnd` | 组件属性形式的范围结束字段名 | | `change` | 开始日期变化时触发,`detail` 为开始日期字符串 | ### `` 示例 ```html ``` ### `` 单独使用 ```html ``` ### `` | 项目 | 说明 | |---|---| | `state.value` | 颜色值,默认 `#000000` | | `value` | 可读写,映射到 `state.value` | | `change` | 颜色变化时触发,`detail` 为颜色字符串 | ### `` 示例 ```html ``` ### `` | 项目 | 说明 | |---|---| | `state.value` | 当前图标名 | | `state.search` | 搜索词 | | `state.open` | 下拉是否展开 | | `filteredIcons` | 过滤后的图标列表 | | `value` | 可读写,映射到 `state.value` | | `change` | 选择图标时触发,`detail` 为图标名 | ### `` 示例 ```html ``` ### `` | 项目 | 说明 | |---|---| | `state.tags` | 标签数组 | | `change` | 标签变更时触发,`detail` 为最新数组 | ### `` 示例 ```html ``` ### `` 单独使用 ```html ``` ## List `` 支持普通、分组、树形和虚拟滚动。它的重点不是“能渲染”,而是“能直接拿来绑定状态”。 ### 属性 | 名称 | 写法示例 | 说明 | |---|---|---| | `mode` | `` | `normal` / `group` / `tree`,默认 `normal` | | `fast` | `` | 开启虚拟滚动。任意模式都能用 | | `collapsible` | `` | 树形模式下允许折叠 | | `auto-select` | `` | 点击项后把当前项 id 写回 `selectedItem` | | `auto-select-group` | `` | 点击分组后把当前分组 id 写回 `selectedGroup` | ### 状态 | 名称 | 说明 | |---|---| | `list` | 原始列表 | | `groups` | 分组列表,`group` 模式使用 | | `filter` | 字符串或对象筛选条件 | | `order` | 排序规则,例如 `name`、`-name`、`name desc` | | `selectedItem` | 当前选中的项 id | | `selectedGroup` | 当前选中的分组 id | | `renderedList` | 当前实际渲染的列表片段 | | `flatList` | 逻辑处理后的扁平列表 | | `collapsed` | 树形折叠状态 | ### 实例属性 | 名称 | 写法示例 | 说明 | |---|---|---| | `filterFunc` | `list.filterFunc = item => item.active` | 自定义过滤函数 | | `orderFunc` | `list.orderFunc = (a, b) => a.name.localeCompare(b.name)` | 自定义排序函数 | ### 事件 | 事件 | 触发时机 | `detail` | |---|---|---| | `change` | 选中项变化 | `selectedItem` | | `itemclick` | 点击普通项 | `{ item, index }` | | `groupclick` | 点击分组项 | `{ item, index }` | ### 绑定习惯 - 推荐配合 `$bind` 保存当前选中 id,比如 `$bind="window.currentUserId"` - 如果你只关心点击事件,也可以不绑,直接监听 `itemclick` / `groupclick` ### 插槽 | 插槽 | 说明 | |---|---| | `item` | 单项自定义内容 | | `item-actions` | 单项右侧动作区 | | `group-actions` | 分组右侧动作区 | ### 字段默认映射 不写映射属性时,默认字段名就是这些: | 字段 | 默认值 | |---|---| | `idfield` | `id` | | `labelfield` | `label` | | `summaryfield` | `summary` | | `groupidfield` | `id` | | `grouplabelfield` | `label` | | `groupsummaryfield` | `summary` | | `groupfield` | `group` | | `parentfield` | `parent` | | `groupicon` | `folder` | | `itemicon` | `file` | ### 推荐示例 #### 普通列表 + `$bind` ```html ``` #### 分组列表 ```html ``` #### 树形列表 ```html ``` #### 虚拟滚动 ```html ``` ### 行为说明 - `filter` 是字符串时,同时匹配 `label` 和 `summary` - `filter` 是对象时,按字段模糊匹配 - `tree` 模式会自动保留命中的祖先链 - `fast` 模式要求外层容器有 `overflow-auto` - 数据项可加 `_itemHeight` 优化虚拟滚动测量 ## Nav `