# SinleUI
> SinleUI 是一个基于 uni-app x 的移动端 UI 框架,提供 100+ 组件与配套 API。
# AI 开发
SinleUI 为 Vibe Coding Harness(Claude Code、Codex、ZCode、DeepSeek Harness、Cursor、WorkBuddy、Trae等)提供了可安装的 Skill,以提供插件附带的组件与 API 能力清单。AI 可以据此查找框架已有能力,按框架规范生成页面和功能,减少重复实现和属性误用。
## 为什么需要这些资料
SinleUI 基于 uni-app x 框架开发,使用本插件时与普通 Vue 项目有不少差异,AI 按通用 Vue 项目的写法生成代码时,容易忽略以下几点:
- 组件名、props 和事件由框架定义,需要查阅后再使用;
- 页面根节点必须是 `sn-page`,否则主题变量会失效;
- 尺寸和颜色使用 `$` 动态值与 `--sn-*` 变量,不能都按固定 `px` 与十六进制色值处理;
- 原生端需要自定义基座,生成方案时也要考虑这一前提。
在开始任务前提供能力清单和这些约定,可以减少因框架用法不符而产生的返工。
## 本栏目内容
- [Skill](/ai/skill):下载并安装 `sinleui-app-dev`,供 AI 查阅框架规范。
- [适配指南](/ai/setup):安装后如何描述需求、检查结果。
- [实践经验](/ai/practices):使用 AI 开发页面时的任务安排与检查建议。
## 能力清单
能力清单有两个入口,按是否联网选择:
- **联网时**:文档站提供 [llms.txt](https://sinleui.pages.dev/llms.txt) 分组索引与逐页 `.md`(如 `https://sinleui.pages.dev/components/sn-button.md`),AI 可直接抓取,无需解析 HTML;也可用 [llms-full.txt](https://sinleui.pages.dev/llms-full.txt) 一次读完全部页面。
- **离线时**:插件内的 `uni_modules/sinle-ui/ai-reference.md` 是单文件索引,覆盖同样的组件与 API,每一项都带文档站链接。
`ai-reference.md` 是**自动生成的派生产物**(源是 Skill 的 `references/` 索引),随插件一起分发:
| 部分 | 内容 |
| :--- | :--- |
| 开工前必读 | 页面根节点、easycom、`$` 动态值等硬约束 |
| 框架核心能力 | 全部 hooks 的用途与导入方式 |
| 组件清单 | 全部组件的分类、用途简述与文档链接 |
| API | `$snui`、`snu`、核心库、导出常量与类型的概述 |
| 组合速记 | 列表项、弹层、页面骨架、主题色、尺寸的常见写法 |
文件位置:`uni_modules/sinle-ui/ai-reference.md`。
::: warning 保持同步
能力清单随框架代码维护。新增、修改或删除组件与 API 时,会同步更新清单。**请勿直接编辑 `ai-reference.md`**——它由 Skill 的索引生成,改动应落到 Skill,再重新生成并校验。
使用旧版插件时,请结合当前代码和文档站核对用法。
:::
# Skill
sinleui-app-dev 是供 AI 编码助手使用的 SinleUI Skill。安装后,AI 可以查阅框架规范,减少每次对话中重复说明的内容。
## 下载
[下载 sinleui-app-dev.zip](/skills/sinleui-app-dev.zip)
压缩包内是一个标准 Skill 目录:
```
sinleui-app-dev/
├── SKILL.md 技能入口:工作流、五条硬约束、按任务查
└── references/
├── component-index.md 全部组件:能干什么 + 文档链接
├── api-index.md 全部 API 与 hooks:能干什么 + 文档链接
├── page-structure.md 页面结构规则 + 相关文档链接
├── style-rules.md 尺寸与颜色规则 + 相关文档链接
├── recipes.md 常见组合速记(列表项 / 骨架 / 弹层 / 尺寸颜色)
└── checklist.md 交付前自查清单
```
## 内容与文档的分工
Skill 主要提供以下三类信息,组件和 API 的具体用法仍需查阅文档:
1. 框架提供的能力,以及各自的用途和文档链接;
2. 必须遵守的要求(`sn-page` 根节点、`$` 动态值、`--sn-*` 变量、easycom、不改 `uni_modules/`);
3. 交付前需要检查的项目。
框架有一百多个组件,如果把 props 表全部放进 Skill,文件会很长,维护时也容易遗漏。因此,具体用法统一链接到文档站,Skill 用来帮助 AI 找到相关页面。
::: tip 使用流程
AI 接到任务后,先通过索引选择组件,再阅读对应文档页的属性表,最后按规则写代码、对照清单自查。这样能减少凭记忆编写代码的情况,也能控制上下文的长度。
:::
## 安装
不同工具的技能目录有所区别,下表列出了一些常见位置:
| 工具 | 常见位置 |
| :--- | :--- |
| Claude Code | `~/.claude/skills/`(全局)或项目内 `.claude/skills/` |
| CodeBuddy / Trae / Qoder | 各工具技能目录(如 `.codebuddy/skills/`、`.trae/skills/`) |
| 支持 AGENTS.md 类约定但不支持 Skill 的工具 | 见下方「不支持 Skill 时」 |
解压后,将整个 `sinleui-app-dev/` 目录放入技能目录,并保留内部目录结构。`SKILL.md` 通过相对路径引用 `references/` 下的文件。
::: tip 确认安装
不清楚技能目录时,可以在工具中询问,或查阅该工具的文档。安装后,新建对话让 AI 写一个 SinleUI 页面,检查它是否读取了组件索引,并使用 `sn-page` 作为根节点。
:::
## 不支持 Skill 时
不支持 Skill 的工具也可以使用压缩包中的 Markdown 文件:
- 支持在对话开头注入上下文时,将 `SKILL.md` 贴入上下文;
- 支持自定义指令 / 自定义 prompt 的工具,可以将 `SKILL.md` 作为指令内容;
- 不支持上述方式时,在任务开头要求 AI「先读 `<解压路径>/sinleui-app-dev/SKILL.md`,按里面的规范写」。
`SKILL.md` 内容较短,也便于通过这种方式加入对话上下文。
## 使用范围
Skill 会引导 AI 优先选择框架已有组件、按 `sn-page` 组织页面、使用 `$` 与 CSS 变量处理尺寸和颜色、查阅文档,并在交付前对照清单检查。查不到所需能力时,应明确说明「框架未提供」。
不得编造组件与属性、修改 `uni_modules/` 下的框架代码,或将未验证的结果写成已验证。编译与真机验证是否执行,仍以当前环境和项目规则为准。
## 让 AI 直接抓取文档
除 Skill 之外,文档站还按 [llms.txt](https://llmstxt.org) 约定提供了可直接抓取的索引,便于 AI 在不下载 Skill 时也能拿到完整页面内容:
| 地址 | 内容 |
| :--- | :--- |
| [https://sinleui.pages.dev/llms.txt](https://sinleui.pages.dev/llms.txt) | 分组索引:每个组件 / API 页面的标题、一句话说明与 Markdown 链接 |
| [https://sinleui.pages.dev/llms-full.txt](https://sinleui.pages.dev/llms-full.txt) | 全部页面的 Markdown 合订本,可一次性读完 |
| `https://sinleui.pages.dev/components/sn-button.md` | 任取一页的 Markdown 版本(组件、API、核心库同理) |
也就是说,AI 既能用 Skill 查「框架有什么」,也能直接抓 `.md` 拿「这个组件怎么用」,无需解析 HTML。在提示词里可以直接写:
```text
先读 https://sinleui.pages.dev/llms.txt,再按需读取对应组件的 .md 页面。
```
::: info 生成方式
`llms.txt` / `llms-full.txt` / 逐页 `.md` 均为**自动生成的派生产物**,随文档站一起发布。请勿直接编辑这些文件,改动应落到对应的源文档上,再重新运行生成脚本。
:::
## 离线索引
插件中的 `uni_modules/sinle-ui/ai-reference.md` 也按索引形式列出了组件、hooks 与 API 的用途,每一项都带文档站链接。能联网时,Skill 会引导 AI 查阅文档站与 `llms.txt`;联网不便时,可以读取这份离线索引。
它是**自动生成的派生产物**:源是 Skill 目录下的 `references/`,由 `tools/gen-ai-reference.mjs` 生成,请勿手动编辑。需要更新时,先改 Skill 索引,再重新生成,并用 `--check` 校验两者是否一致。
## 更新
Skill 随框架一起维护,下载包与文档站同步发布。需要更新时,重新下载并覆盖原目录即可。
::: info 维护说明
下载包由 `tools/pack-skill.ps1` 从 `docs/public/skills/sinleui-app-dev/` 生成,`-Check` 可校验两者是否一致。
:::
# 适配指南
安装 SinleUI 的 Skill 后,就可以向 AI 描述需要开发的页面或功能。
## 一、安装 Skill
下载并解压 [sinleui-app-dev](/ai/skill),放入所用工具的技能目录。安装后,AI 可以查阅:
- 组件索引:组件的用途和对应文档;
- API 索引:`$snui`、`snu`、hooks、store、颜色与日期库的入口及文档链接;
- 页面结构与样式规则(`sn-page` 根节点、`$` 动态值、`--sn-*` 变量等);
- 交付前自查清单。
Skill 主要提供索引,具体用法需查阅对应文档,便于随框架更新,也能减少上下文占用。安装位置及不支持 Skill 时的用法见 [Skill 页](/ai/skill)。
## 二、按场景描述需求
描述任务时,先说明页面或功能需求。AI 可以通过 Skill 查阅框架规则和相关文档。
| 你要做的 | 可以这样描述 |
| :--- | :--- |
| 一个列表页 | 「做一个消息列表页,每条显示标题、时间和摘要,点击进详情」 |
| 一个表单页 | 「做一个新建地址的表单,姓名、手机号、地区三级选择,带校验」 |
| 一段长列表 | 「商品列表,支持下拉刷新和加载更多,卡片式」 |
| 一个设置页 | 「设置页,分通用/账号两组,含暗黑模式开关和退出登录」 |
| 一次操作确认 | 「删除前弹确认框,确认后调接口并提示结果」 |
| 一个页面底部导航 | 「首页加底部三个 Tab:首页、分类、我的」 |
| 一个详情页 | 「商品详情页,顶部图片,内容从导航栏背后滚过」 |
::: tip 补充数据与状态
说明数据来源、加载中和空列表时的表现,AI 更容易写出符合项目需求的代码。例如:「数据从 `api.getMessages()` 来,加载中用骨架屏,空列表显示提示」。
:::
## 三、验收时看什么
AI 交付时应对照 Skill 的清单说明检查结果。你可以再复核以下几项:
- [ ] 页面根节点是 `sn-page`,弹层都在它内部;
- [ ] 尺寸使用 `$` 动态值或 `calc(var(--ff) * 14px)`,没有大量写死的 `px`;
- [ ] 颜色使用 `$primary` / `var(--sn-*)`,没有写死的十六进制色值;
- [ ] 提示类调用使用 `snu.showToast`,没有混入 `uni.showToast`;
- [ ] 列表页有加载中 / 空态 / 正常三种状态。
## 四、补充说明
**框架安装**:框架本身的安装只需完成一次,步骤见[安装](/get-started/setup)与[注意事项](/get-started/notes)。
**能力清单**:插件内的 `uni_modules/sinle-ui/ai-reference.md` 是供 AI 查阅的离线索引,简述了组件、hooks 与 API 的用途。Skill 会引导 AI 查阅文档站;联网不便时,可以先查这份索引。
**项目约定**:目录结构、接口封装、状态管理、命名习惯等额外规范,可以写进项目的 `AGENTS.md` 或规则文件。Skill 负责框架用法,业务约定仍以项目规则为准。
# 实践经验
用 AI 编写 SinleUI 页面时,除了说明需求,还需要提供框架资料和项目约定。下面整理了一些任务安排和检查方法,供开发时参考。
## 一、先提供能力清单
AI 不了解框架组件时,可能会用原生 `view` 重复实现已有组件,也可能误用不存在的 `sn-xxx`,导致返工。
开始任务前,可以先安装 Skill,让 AI 读取能力清单;也可以让它直接读取 `uni_modules/sinle-ui/ai-reference.md`。有了清单,AI 能根据需求选择组件,不必在指令中逐个点名。比如需要徽标时,可以选用 `sn-badge`;需要骨架屏时,可以选用 `sn-skeleton`。
::: tip 先查再写
可以按「先查索引 → 理解需求 → 阅读文档 → 编写代码」的顺序推进。先确认组件选择,再开始写代码,可以减少在已有结构上反复打补丁的情况。
:::
::: info 索引与手册的分工
索引用于查找框架是否提供某项能力、对应文档在哪里,手册说明具体用法。先看索引,再按需阅读文档页,可以减少上下文占用,也方便查阅文档站上的最新用法。
:::
## 二、把约定写成可检查的规则
约定要具体到 AI 可以在交付前逐项检查。例如,「注意代码质量」很难直接核对,而「页面根节点必须是 `sn-page`」可以逐文件检查。
下面几种写法比较容易检查:
| 写法 | 示例 | 检查依据 |
| :--- | :--- | :--- |
| 明确规则 | 页面根节点必须是 `sn-page` | 可逐文件确认根节点 |
| 给出反例 | 不要用 `uni.showToast`,用 `snu.showToast` | 明确要避免的调用及替代方法 |
| 给出写法 | 尺寸写 `$14`,不要写裸数字 | 可直接对照代码核对 |
| 限定修改范围 | 不要改 `uni_modules/` | 明确依赖目录不在修改范围内 |
常用约束可以控制在一屏左右,便于一次读完。长篇规范中的细节按任务需要另行查阅,避免重点被大量说明淹没。
## 三、允许 AI 说明不确定之处
AI 不确定某项能力时,有时会补出一个看似合理的用法。可以在任务中写明:
> 不确定某个能力是否存在时,先查能力清单与文档站;查不到就说明「框架未提供该能力」,不要编造,也不要在未说明的情况下换成不可用的实现。
允许 AI 明确说明能力缺失,有助于及早发现问题,避免继续沿着错误方案开发。
## 四、留意尺寸和颜色的写法
样式代码有时语法正确,却不符合框架的写法。常见问题包括:
- 将 `$14` 写成 `14`,尺寸就不会随乘数缩放,用户调整字号时也不会跟着变化;
- 将颜色写死为 `#4d82ff`,切换暗色主题后仍保持原色;
- 在脚本中拼接样式,却没有放进 `computed`,乘数变化时界面不会刷新;
- 用 `calc(var(--af) * 200ms)`,`--af` 是纯数值乘数,放进 `calc()` 算时间不成立。
这类问题不容易仅靠阅读代码发现。把对应规则写进约束文件,并在交付前逐项检查,有助于减少遗漏。
## 五、按步骤完成任务
同时要求 AI 搭页面、接接口、加动画和适配暗色主题时,容易出现细节遗漏。可以把任务拆成几轮:
1. **结构**:先确定 `sn-page`、布局和组件选择,暂不处理样式细节;
2. **数据**:接入真实数据,补齐空态 / 加载态 / 错误态;
3. **样式**:使用 `$` 与 `calc(var(--xx) * Npx)`,统一尺寸与颜色的写法;
4. **交互**:补充加载、禁用、点击态和动效。
每轮完成后分别检查,发现问题时也更容易定位。
## 六、交付时逐项检查
生成完成后,让 AI 对照清单说明检查结果,便于确认哪些内容已完成、哪些还需要验证。可以使用以下清单:
- [ ] 根节点是 `sn-page`,弹层都在内部;
- [ ] 没有大量写死的 `px` 与十六进制颜色;
- [ ] 提示使用 `snu.showToast`,没有 `uni.showToast`;
- [ ] 组件的 `ref` 调用发生在渲染之后;
- [ ] 列表页有加载中 / 空态 / 正常三种状态;
- [ ] 明确列出需要人工确认的交互点。
## 七、描述问题时给出操作和现象
AI 可以根据代码和编译产物分析问题,但不一定能看到实际运行画面。抽屉滑动是否顺畅、交互是否符合预期,仍需要你在运行时确认。
反馈问题时,说明页面位置、操作步骤和实际表现,再附上相关代码,会比只说「不生效」更容易定位。仅说「样式错了」,往往不足以判断原因。
# 介绍
SinleUI
一个简洁、轻巧的现代移动应用UI框架
###
### :desktop_computer: 作者有话说
这个UI框架是作者苦于 uni-app x 插件市场缺失适合自己的UI库,在开发项目的过程中写的。我自己项目比较多,而且都是一些小型项目,资金不算太充裕。对于小型个人项目来说,较完美的UI框架授权费用相对较高,自我感觉非常不划算,其他免费的UI框架大多有点不合项目的风格,于是自己写了一个。
由于作者时常在校,因此更新频率视情况待定。**若没有满足您的需求,可以自己二次开发**。
**本UI框架适合小型项目开发,大型商业项目慎用**。当然,如果您愿意为项目贡献,也欢迎提供代码、指出 Bug 或打赏,这也是我创作的动力。😊
---
### :pizza: 项目声明
本UI框架作者为:Aaron Lan
采用MIT协议,允许二次开发和修改,以及对使用本UI框架的项目闭源处理。但必须在项目显著位置(包括但不限于项目发布页、项目声明文件、项目许可信息页面)进行使用声明。
---
### :fish_cake: 引用声明
本项目内置字体说明
- Remix Icon
---
### :book: MIT许可证
> Copyright (C) <2023-> <Singmy>
>
> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
>
> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# 安装
> [!warning]
> SinleUI 只支持通过 [DCloud 插件市场 ](https://ext.dcloud.net.cn/plugin?name=sinle-ui)下载安装
1. 进入插件下载页
2. 右上角选择 购买**源码授权版**(5.00 元)(务必选择**源码**授权版;本项目仅收费 5 元,不要选择普通授权版)
3. 付款
4. 导入对应项目即可
# 快速上手
本节将介绍如何在项目中使用 SinleUI。
## 使用方法
1. 首先,请[安装SinleUI](../get-started/setup.md)。
2. 在项目根目录下 `App.uvue` 中导入 `CSS` 文件。
```vue
```
3. 组件符合 [easycom](https://uniapp.dcloud.net.cn/collocation/pages?id=easycom) 规范,无需 import,直接在项目中使用。
4. SinleUI API 则需要 import 相应对象后使用。
```typescript
import { $snui } from '@/uni_modules/sinle-ui'
```
::: warning 注意
不可直接从插件内部任何 `ts` 文件导入对象或类型,大部分类型均从 `@/uni_modules/sinle-ui` 导入
组件专属类型同样从插件入口 `@/uni_modules/sinle-ui` 统一重导出,不再需要从组件目录导入。
**部分特殊类型**请参考 [类型](/api/types/index) 内容或按照其文档说明路径导入。
:::
5. 在 APP 端运行本框架必须**打包自定义基座**后运行,因为框架使用了第三方依赖。
# 注意事项
> [!important]
> 请仔细阅读此页内容,对于正确使用 SinleUI **非常重要**。
::: danger 必须放在 sn-page 下
- 页面内所有组件(含 sn-popup、sn-modal、sn-toast 等弹出层类组件)都必须放在 `sn-page` 下,务必让 `sn-page` 成为页面根节点,否则注入的 `--sn-*`、`--ani-time-*` CSS 变量无法作用到这些节点,颜色与动画时长会错乱
:::
1. 由于框架使用了第三方依赖,在 APP 端运行 SinleUI **必须打包自定义基座**后运行。
2. SinleUI 推荐**使用 `px` 作为基本长度单位**。SinleUI 部分组件涉及布局计算,现阶段对于其他单位如 `rpx` 、`%` 的支持并不太好(下期会改进)。因此,除非设置 css 或组件行内样式 `style`,否则不推荐在 SinleUI 组件中使用 `px` 外的长度单位。
3. SinleUI 推荐**使用 `ms` 作为基本时长单位**。SinleUI 部分组件涉及时长处理,默认以 `ms` 作为单位。因此,除非设置 css 或组件行内样式 `style`,否则不推荐在 SinleUI 组件中使用 `ms` 外的时长单位。
5. 获取组件 Ref 实例时,如果是选项式 API,使用 `this.$refs[xxxx]` 获取即可。
如果是组合式 API,必须设置一个**与组件 `ref` 属性同名**的、**组件实例类型**的响应式对象。例如:
```vue
```
6. 调用组件的方法需要通过 `ref` 获取组件实例,且**必须保证组件已渲染**。
例如:
```vue
```
# 框架设计
本页详细介绍 SinleUI 的整体架构、核心机制与设计理念,帮助您理解框架如何工作、为何这样设计。
## 概述
SinleUI 是一个面向 uni-app x 蒸汽模式(vapor)的轻量级移动端 UI 框架,以 `uni_modules` 形式分发,目标平台为 Android(Kotlin)、iOS(Swift)、HarmonyOS 与 Web(JavaScript)。
框架坚持以下设计原则:
- **简洁轻量**:核心无运行时依赖,按需打包
- **跨平台一致**:通过条件编译与平台目录(`utssdk/app-android`、`utssdk/app-ios` 等)隔离平台差异
- **主题化驱动**:风格(Style)与主题(Theme)双层体系,全局一处修改、处处生效
- **组合式 API**:向组件与开发者提供 `hooks` 复用框架能力
- **性能颜值平衡**:追求更优秀的 UI 设计,一切设计都在考虑性能的情况下尽可能优化 UI 设计。
---
## 目录结构
`uni_modules/sinle-ui/` 插件目录结构如下:
| 目录/文件 | 说明 |
| :--- | :--- |
| `components/` | 全部 `sn-*` 组件,每个组件一个独立目录(如 `sn-button/sn-button.uvue`) |
| `core/` | 框架核心模块 |
| `core/snui.ts` | `Snui` 单例类定义,`$snui` 全局实例 |
| `core/state.ts` | 全局响应式状态(主题、风格)、持久化与主题监听 |
| `core/types/index.ts` | 全部核心类型定义与导出(SnColorBase、SnStyle 等) |
| `core/theme/` | 内置风格文件(`default-style`、`ink-style`、`chinese-style` 等 6 套)与风格注册中心 |
| `core/utils/` | 工具库分组静态类(Random、Basic、Easing、ObjectUtils、System、Sort、Text、Ui、Perm、Verify) |
| `core/utils/index.ts` | `snu` 聚合门面 |
| `core/color/` | 颜色库(`ColorLib`、`TinyColor`) |
| `core/date/` | 日期库(`DateLib`、`Dayuts`、国际化) |
| `core/private/` | 内部钩子与机制(`use-theme`、`use-style`、`use-factors`、`use-hover`、`use-external-style`、`use-backtop`、`logger`、`dialog-store`) |
| `pages/popups/` | 全局弹窗页面(showModal、showActionsheet、showLoading) |
| `pages_init.json` | 注册插件内置弹窗页面 |
| `index.ts` | 插件入口,统一导出全部公开 API |
---
## 风格系统(Style)
一个应用可同时注册多套风格(皮肤),如现代、简约、古风、梦幻、科幻等。每套风格是一个 `SnStyle` 对象,包含:颜色集(亮/暗两套)、导航栏高度、亮/暗页面背景色,以及五个乘数与三个基础动画时长。
- **注册与切换**:`core/theme/index.ts` 在框架加载时执行 `initStyles()` 注册内置风格;`$snui.currentStyleId` 切换风格(`switchStyle` 会深拷贝目标风格再替换当前风格,避免互相污染)。
- **内置风格**:`default`(默认)、`ink`(水墨)、`chinese`(国风)、`new-year`(新年)、`morandi-green`(莫兰迪绿)、`orange`(活力橙)共 6 套。
- **持久化**:`switchStyle` 与各 setter 修改后调用 `persistCurrentStyle()`,将当前完整风格写入 storage(key:`sinleui_current_style`),风格 id 单独存储(key:`sinleui_current_style_id`)。应用重启自动恢复。
- **运行时微调**:开发者可直接修改 `$snui` 上的乘数与颜色等属性,改的是当前风格对象,随后自动持久化,覆盖预置值。
#### SnStyle
一套完整风格(皮肤)对象,即内置风格文件导出的结构。
| 字段 | 类型 | 描述 |
| :------------- | :---------------------------- | :-------------------------- |
| id | String | 风格唯一 id,如 `'default'` |
| colorBases | [SnColorBases](#sncolorbases) | 亮/暗两套颜色集 |
| topbarHeight | String | 导航栏高度(不含状态栏),默认 `48px` |
| lightBgColor | String | 亮色模式页面默认背景色 |
| darkBgColor | String | 暗色模式页面默认背景色 |
| marginFactor | Number | 外间距乘数 |
| paddingFactor | Number | 内间距乘数 |
| radiusFactor | Number | 圆角乘数 |
| fontsizeFactor | Number | 字号乘数 |
| aniTimeFactor | Number | 动画时长乘数 |
| aniTimeShort | Number | 基础短动画时长(ms) |
| aniTimeNormal | Number | 基础标准动画时长(ms) |
| aniTimeLong | Number | 基础长动画时长(ms) |
---
## 主题系统(Theme)
主题指亮色(`light`)与暗色(`dark`)两种颜色模式。一套风格的 `colorBases` 包含两套 `SnColorBase` 颜色集。
- **切换**:`$snui.theme = 'light' | 'dark'`;`autoTheme`(默认开启)跟随系统外观。两者都经 `uni.setAppTheme` 驱动框架应用主题,框架再回写 `currentTheme`(App 端 `uni.onAppThemeChange`、Web 端 `uni.onHostThemeChange`)。App 端建议在 `manifest.json` 配置 `app.defaultAppTheme: "auto"`,让冷启动首帧即与系统一致。
- **状态栏同步**:切换与初始化时会调用 `syncStatusBarColor()` 同步原生状态栏文字/背景色。
- **App 端原生主题**:通过 `uni.setAppTheme` 同步系统暗黑模式,保证 `window` 等系统 UI 与页面一致。
- **Web 端主题源**:Web 没有 `osTheme`(只有宿主 `hostTheme`),框架读取 `uni.getAppBaseInfo().hostTheme` 并监听 `uni.onHostThemeChange`,`autoTheme` 在浏览器中同样能正确跟随。手动切换主题时以**应用主题为准**,不受浏览器外观反向影响。
`core/state.ts` 中导出的响应式状态构成了框架状态的根基:`currentStyleId`、`currentStyle`、`currentTheme`、`autoTheme`、`cssPalette`(颜色变量是否回落到脚本内联写入),以及由 `currentStyle × currentTheme` 计算出的 `colors`(当前颜色集)。
---
## 颜色系统
`SnColorBase` 定义了完整的语义化颜色集,分为**功能色**与**特殊色**两类(字段明细见[核心类型](/api/types/api#sncolorbase))。
功能色共 5 种语义:`primary`(主色)、`info`(信息)、`success`(成功)、`error`(错误)、`warning`(警告)。每种功能色在亮/暗模式下各有 3 个深浅程度(原色 / `Light` 更浅 / `Dark` 更深),每个程度配套 `Active`(激活态)与 `Text`(该色背景上的文字前景色)。
> 注意:后缀带 `Dark` 的是比原色更深的颜色,并非暗黑主题专属;带 `Light` 的是更浅的颜色。暗黑主题与亮色主题各自拥有独立的 `SnColorBase` 对象。
- **颜色变量(应用主题优先,媒体查询兜底)**:`sn-page` 根节点始终带 `sn-theme-light` / `sn-theme-dark` 类,声明内置默认风格的全部 `--sn-*` 颜色变量,随 `$snui.theme` 切换;同样的色板另由 `@media (prefers-color-scheme: light)` / `@media (prefers-color-scheme: dark)` 声明,作为系统外观兜底(需 HBuilderX 5.25+ 蒸汽模式)。优先级为「内联 > `sn-theme-*` 类 > 媒体查询」,因此**手动切换主题后颜色不会被相反的系统外观覆盖**。页面内所有组件与弹出层(必须位于 `sn-page` 根节点下)通过 `var(--sn-xxx)` 引用即随主题自动切换;乘数与动画时长变量仍由 `sn-page` 差量写入。
- **自定义配色的回落**:调用 `$snui.setColor` / `setColorBase` 或切换到非默认内置风格后,颜色改由脚本写入内联变量(覆盖类色板与媒体查询色板)。该页面此后按完整色板的实际值差量更新,切回默认风格时直接写回默认色值,避免依赖删除变量后的 CSS 回退;连续修改颜色与切换亮暗主题同样同步。新创建的默认风格页面仍使用 CSS 色板。
- **`$` 简化语法**:颜色类 props 统一经 [useResolve](/api/hooks/use-resolve) 钩子的 `resolveColor` 处理,`$primaryTextDark` 自动转换为 `var(--sn-primary-text-dark)`,非 `$` 开头的值原样返回。
全部 `--sn-*` 颜色变量的命名规则、完整清单与用法示例,以及与它们等价的 JS 读写方式,见 [CSS 变量](/get-started/css-variables)。
## 大小乘数与动画时长
框架通过五个全局乘数控制 UI 的密度与动效节奏,均可在 `$snui` 上读写并持久化:
| 乘数属性 | 作用 |
| :--- | :--- |
| fontsizeFactor | 字号乘数 |
| radiusFactor | 圆角乘数 |
| marginFactor | 外间距乘数 |
| paddingFactor | 内间距乘数 |
| aniTimeFactor | 动画时长乘数 |
还提供了三个常用动画时长,以保持应用全局动画的一致性: `$snui.aniTimeShort(150ms)` / `$snui.aniTimeNormal(250ms)` / `$snui.aniTimeLong(400ms)`。这些常用动画时长会自动适配 `aniTimeFactor` 机制,无需您自行处理。脚本侧直接读 `$snui` 属性,样式侧引用 `sn-page` 注入的 `--ani-time-short` / `--ani-time-normal` / `--ani-time-long`,两套写法的对应关系见 [CSS 变量 · 动画时长变量](/get-started/css-variables#动画时长变量)。
### 乘数的三种用法
**① 组件 props 上的 `$` 语法**(页面开发最常用)
尺寸类 props 的值写成 `$16` 即跟随对应乘数缩放,写成 `16px` 则固定不变,详见下方 [`$` 动态尺寸语法](#动态尺寸语法)。
**② JS 中直接读写乘数**
五个乘数都可通过 `$snui` 直接读取或修改,修改后会持久化到当前风格:
```typescript
$snui.paddingFactor = 1.2
const padding = 12 * $snui.paddingFactor
const radius = 8 * $snui.radiusFactor
```
**③ CSS 中的乘数变量**
使用 HBuilderX Alpha 5.31 或更高版本时,`sn-page` 还会注入五个数值 CSS 变量:`--marginFactor`、`--paddingFactor`、`--radiusFactor`、`--fontsizeFactor`、`--aniTimeFactor`,并为每个乘数并列注入一个同值缩写变量:`--mf`、`--pf`、`--rf`、`--ff`、`--af`(缩写与全称是各自独立的字面值,不是 `var()` 引用)。它们适合直接用于 `calc()`,写起来更短:
```scss
.card {
padding: calc(var(--pf) * 12px);
border-radius: calc(var(--rf) * 8px);
font-size: calc(var(--ff) * 14px);
}
```
| 全称变量 | 缩写变量 | 对应乘数 |
| :--- | :--- | :--- |
| `--marginFactor` | `--mf` | 外间距乘数 |
| `--paddingFactor` | `--pf` | 内间距乘数 |
| `--radiusFactor` | `--rf` | 圆角乘数 |
| `--fontsizeFactor` | `--ff` | 字号乘数 |
| `--aniTimeFactor` | `--af` | 动画时长乘数(不可用于 `calc()`) |
CSS 变量的作用域是 `sn-page` 根节点及其后代。乘数变化时,`sn-page` 会差量更新变量;脱离 `sn-page` 的独立组件不会自动获得这些变量。框架内的三个弹窗页(`snu.showModal` / `snu.showActionsheet` / `snu.showLoading`)是 dialogPage,不在任何 `sn-page` 子树内,页面会自行把颜色、动画时长与五个乘数变量一并注入到自己的根节点,因此在这些弹窗的 `customStyle` 中写 `calc(var(--xxxFactor) * Npx)` 同样有效;而 `snu.showToast` 走原生弹层、不涉及 CSS 变量,尺寸只走 `$` 动态值。
三类变量的完整清单(含每个变量的用途与典型写法)与更多示例见 [CSS 变量](/get-started/css-variables)。
#### **`$` 动态尺寸语法**
`$` 是尺寸类 props 的"动态"标记:**带 `$` 的值随对应乘数缩放,不带 `$` 的值按固定值处理、不乘任何乘数**。想要跟随风格与用户调节整体缩放的尺寸(字号、圆角、间距、动画时长)就加 `$`,需要写死的尺寸就不加。不带 `$` 的纯数字字符串会自动补单位(`border-radius="10"` → `10px`,动画时长类补 `ms`),`16px`、`50%` 等已带单位的写法原样输出。
**一、写在组件 props 上**
尺寸类 props 的值直接写成 `$数值` 即可(单位可省略:动画时长为 `ms`,其余为 `px`,也可显式写 `$16px`):
```vue
```
每个 prop 用哪个乘数由组件内部指定,各组件属性表会标注该 prop 的 `$` 支持与对应乘数(形如「支持 `$` 前缀按 ✕✕ 乘数缩放」),使用时以属性表标注为准。五类解析类型与乘数的对应关系如下:
| 解析类型 | 对应乘数 | 适用 props 举例 | 写法 → 结果(乘数为 1 时) |
| :--- | :--- | :--- | :--- |
| `font` | fontsizeFactor | 字号类:`fontSize`(sn-text)、`textSize` / `iconSize`(sn-alert) | `font-size="$14"` → `14px` |
| `radius` | radiusFactor | 圆角类:`radius`(sn-button)、`borderRadius` | `radius="$8"` → `8px` |
| `margin` | marginFactor | 外间距类:`margin`(sn-card、sn-view)、`gap`(sn-pagination)、`spacing`(sn-avatar-group) | `margin="$12"` → `12px` |
| `padding` | paddingFactor | 内间距类:`padding`(sn-toast、sn-tooltip)、`size`(sn-avatar) | `padding="$16px $20px"` → `16px 20px` |
| `aniTime` | aniTimeFactor | 动画时长类:`aniTime`(sn-popup)、`hoverTransTime`(sn-button) | `ani-time="$250"` → `250ms` |
动画时长类 props 还接受三个命名值:`$short`、`$normal`、`$long`,分别对应 `$snui.aniTimeShort`(150ms)、`$snui.aniTimeNormal`(250ms)、`$snui.aniTimeLong`(400ms),同样随 `aniTimeFactor` 缩放,不带 `$` 的 `short` / `normal` / `long` 写法等价。
**二、在 JS 中自己拼样式**
自行拼接样式或开发自定义组件时,用 [useResolve](/api/hooks/use-resolve) 的 `resolveSize`(返回带单位字符串)/ `resolveSizeNum`(返回数值),第二个参数为解析类型(`font` / `radius` / `margin` / `padding` / `aniTime`)。**必须放在 `computed` 中求值**,否则乘数变化后不会重算:
```typescript
import { useResolve } from '@/uni_modules/sinle-ui'
const resolver = useResolve()
const cardStyleC = computed(() => {
return `padding:${resolver.resolveSize('$12', 'padding')};border-radius:${resolver.resolveSize('$8', 'radius')};`
})
const iconSizeC = computed(() => resolver.resolveSizeNum('$16', 'font'))
```
**三、完整示例**
带 `$` 与固定值混用、运行时调节乘数的完整页面:
```vue
```
点击「放大字号」调大 `fontsizeFactor` 后,带 `$` 的字号随之变大,固定 `14px` 的文本保持不变;头像尺寸由 `size` 决定、属间距类 props,跟随 `paddingFactor` 缩放,调大该乘数同样会变。demo 的「设计 → 大小乘数」页(`pages/design/factors`)提供字号、圆角、外间距、内间距、动画时长五个乘数滑块的完整可交互版本。
**使用要点**
- `$` 只在组件暴露的尺寸类 props 上生效:写在 `custom-style`、`style` 或 `
```
**更多演示请下载 demo 查看**
## 自定义样式
宽度默认铺满屏幕,可用 `width` 直接改(如 `width="94%"`);间距、圆角、背景、内边距建议直接写在插槽内容上,或通过 `customStyle` / `customClass` 定制根节点。
`offset` 用于在键盘顶部再让出一点距离(例如避开键盘自带的完成栏、候选词栏),支持 `$` 简写。
```vue
完成
```
## 过渡动画
键盘弹出时,区域从屏幕下方上滑并淡入;**取消显示(键盘收起、失去显示权或 `show` 为 false)时立即使节点不可见并移出屏幕,不做收起动画**,避免收起过程与键盘动画叠加产生残影。
`aniTime` 控制淡入时长(支持 `$` 简写,随 `aniTimeFactor` 缩放),为空时使用框架标准时长;传 `0` 则显隐都无过渡。
隐藏态位移按**实测像素高度**计算(组件挂载后与隐藏时测量自身高度),不使用百分比终点——uni-app x 的 `transition` 不支持结束属性值为百分比,用百分比会让 App 端动画退化为瞬跳。
```vue
…
```
## 多个实例
**建议同一时间只显示一个实例**。组件**不做多实例仲裁**——同一页面若同时显示多个 `sn-keyboard-top`,它们会重叠吸附在键盘上方(可用 `zIndex` 与 `offset` 自行错开,但不推荐)。需要多个面板切换时,用 `show` 控制只保留一个:
```vue
评论栏
回复框
…
```
## 插槽作用域
默认插槽会实时下发键盘高度与聚焦状态,方便在区域内部自行展示、布局与接管输入框焦点:
| 参数 | 类型 | 说明 |
| --- | --- | --- |
| keyboardHeight | Number | 当前键盘高度(px) |
| show | Boolean | 本实例当前是否显示中 |
| focus | Boolean | 是否应聚焦区域内输入框(由 `requestFocus` 驱动,初始为 `false`,避免组件显示时重复请求聚焦造成键盘闪动) |
| requestFocus | () => Void | 主动请求聚焦区域内输入框(走 `false` → `nextTick` → `true`,保证原生能识别到 focus 变化) |
区域内输入框建议这样绑定,焦点由 `requestFocus` 统一驱动,避免出现“输入框点不动、无占位文本”:
```vue
```
显示/切换面板时调用组件实例方法请求聚焦:`panelRef.value?.$callMethod('requestFocus')`。
> 注意不要在组件“显示中”时反复调用 `requestFocus`:`focus` 会先变 `false` 让原生输入框失焦、下一帧再变 `true` 重新聚焦,期间键盘会收起再弹出(肉眼可见闪动)。同一面板显示期间只需调用一次。
## 使用注意
### 推荐架构:页面内只读触发器 + 区域内的真实输入框
页面内的输入框设为 `readonly` 作为**触发器**(点击它不自己聚焦,而是让区域内的输入框获得焦点),两处用同一个 `v-model` 同步值。这样键盘始终属于区域内那一个输入框,能同时满足:
- 点击**区域内的空白处**不收起键盘(区域内输入框开启 `hold-keyboard`);
- 点击**页面其他位置**正常收起键盘;
- 切到二级面板(如回复框)时焦点自然转移,不会出现区域内输入框“点不动、无占位文本”的情况。
```vue
```
注意触发器的 `adjust-position` 要设为 `false`:触发器本身不承载输入,若保持默认 `true`,键盘弹出时原生会滚动页面上推该输入框,出现“打开键盘页面滚动、收起又滚回”的现象。
### 其它注意
- 区域内的输入框建议设置 `:hold-keyboard="true"`:uni-app x App-Android 平台下点击输入框以外的屏幕会自动收起软键盘;开启后点击区域内空白处键盘保留(**注意**:未采用上面的只读触发器方案时,`hold-keyboard` 也会让点击页面其他位置同样无法收起键盘,此时需自行调用 `uni.hideKeyboard()`)。
- 区域内的 `sn-input` / `sn-textarea` 建议设置 `:adjust-position="false"`,由组件自身负责吸附,避免原生页面二次上推导致位置抖动。
- 插槽内使用 `textarea` 时建议设置 `fixed`(`sn-textarea` 的 `fixed` 属性)以获得更好的原生表现。
- 需要“紧贴键盘”时 `offset` 保持默认 `0`;键盘自带完成栏/候选栏时可用 `offset` 让位。
- Android / iOS / 微信小程序依赖 `uni.onKeyboardHeightChange`(HBuilderX 4.71+,鸿蒙 5.08+);Web 端该 API 不支持,组件自动使用 `visualViewport` 降级测量,桌面浏览器无软键盘时区域不会显示。
- 组件为 `fixed` 定位不占文档流,页面最后一块内容可能被面板遮住;**预留空白必须放在滚动内容末尾**(如末尾加一个 `height:60px` 的占位 `view`),不要写成 `sn-page` 的 `custom-style="padding-bottom:..."`——`sn-page` 根节点包着 `scroll-view`,padding 落在滚动容器之外会形成一条永远存在的固定空白带。
## 实现原理
键盘高度采用全局监听,同一页面只注册一次,监听值归零即视为键盘收起。
## 属性
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
| --- | --- | --- | --- | --- |
| aniTime | 显隐过渡动画时长(支持 `$` 简写) | String \| Number | `$normal` | - |
| zIndex | 键盘上方区域的 `z-index` 层级 | Number | `990` | - |
| offset | 距离键盘顶部的额外偏移(支持 `$` 简写,用于避开键盘自带的完成栏等) | String \| Number | `0` | - |
| width | 键盘上方区域宽度(支持 `$` 简写) | String \| Number | `100%` | - |
| show | 是否允许显示,设为 `false` 时即使键盘打开也不显示 | Boolean | `true` | `true` \| `false` |
| customStyle | 自定义根节点样式 | SnStyleValue | `''` | - |
| customClass | 自定义根节点外部样式类 | String | `''` | - |
| externalStyle | 额外内联样式 | SnStyleValue | `''` | - |
| externalClass | 额外外部样式类 | String | `''` | - |
## 事件
| 名称 | 类型 | 说明 |
| --- | --- | --- |
| change | (visible: boolean) => Void | 键盘上方区域显示状态变化时触发(键盘弹出收起、`show` 变化时触发) |
## 插槽
| 名称 | 作用域参数 | 说明 |
| --- | --- | --- |
| default | `keyboardHeight`(键盘高度 px)、`show`(是否显示中)、`focus`(是否应聚焦输入框)、`requestFocus`(主动请求聚焦) | 区域内容 |
# Float Board 浮动面板
> [查看 sn-float-board 的 2.0 版本差异](/differences/components/sn-float-board)
## 基础用法
固定吸附在屏幕四边之一的浮动面板,始终显示。
- 通过手势拖拽在折叠与展开状态之间切换,松手后按滑动距离自动归位
- 组件为固定定位,不占据文档流空间
::: info 与 sn-drawer 的区别
`sn-drawer` 是弹出层,需要调用方法才能显示;`sn-float-board` 始终显示。可理解为:`sn-drawer` 是关闭的浮动面板,`sn-float-board` 是半开的浮动面板。
:::
::: info 预留空隙
组件不占据文档流空间,请在页面底部为面板折叠后的空隙预留位置(如使用 `sn-gap`)。
:::
```vue
```
**更多演示请下载 demo 查看**
## 属性
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
| --- | --- | --- | --- | --- |
| position | 浮动面板吸附的位置,非法值回退为 `bottom` | String | `bottom` | `top` \| `right` \| `bottom` \| `left` |
| showLine | 是否显示指示条 | Boolean | `true` | `true` \| `false` |
| maxWidth | 当 `position` 为 `left` \| `right` 且展开时浮动面板的宽度,支持 `$` 前缀按间距乘数缩放 | String | `300px` | - |
| minWidth | 当 `position` 为 `left` \| `right` 且折叠时浮动面板的宽度,支持 `$` 前缀按间距乘数缩放 | String | `50px` | - |
| maxHeight | 当 `position` 为 `top` \| `bottom` 且展开时浮动面板的高度,支持 `$` 前缀按间距乘数缩放 | String | `500px` | - |
| minHeight | 当 `position` 为 `top` \| `bottom` 且折叠时浮动面板的高度,支持 `$` 前缀按间距乘数缩放 | String | `50px` | - |
| slideHeight | 纵向滑动阈值,松手时滑动距离达到阈值则折叠或展开,支持 `$` 前缀按间距乘数缩放 | String | `100px` | - |
| slideWidth | 横向滑动阈值,松手时滑动距离达到阈值则折叠或展开,支持 `$` 前缀按间距乘数缩放 | String | `100px` | - |
| bgColor | 浮动面板背景颜色 | String | `$infoActive` | - |
| lineColor | 指示条颜色 | String | `$lineText` | - |
| padding | 面板内容区内边距(传给内部 sn-view) | String | `25px 15px 10px 15px` | - |
| borderRadius | 面板圆角大小,为随圆角乘数计算的默认圆角(四个直角侧自动贴合屏幕边缘) | String \| Number | - | - |
| aniTime | 展开/折叠动画时长,支持 `$` 动态时长语法 | String \| Number | `$long` | - |
| disabled | 是否禁用滑动手势 | Boolean | `false` | `true` \| `false` |
| zIndex | 面板层级 | Number | `999` | - |
| customStyle | 自定义浮动面板样式 | SnStyleValue | `''` | - |
## 事件
| 名称 | 类型 | 说明 |
| --- | --- | --- |
| unfold | () => Void | 展开浮动面板时触发 |
| fold | () => Void | 折叠浮动面板时触发 |
## 方法
| 名称 | 参数 | 返回值 | 描述 |
| --- | --- | --- | --- |
| unfold | - | - | 展开浮动面板 |
| fold | - | - | 折叠浮动面板 |
## 插槽
| 名称 | 说明 |
| --- | --- |
| default | 在浮动面板内部放置组件 |
# Float Button 浮动按钮
> [查看 sn-float-button 的 2.0 版本差异](/differences/components/sn-float-button)
## 基础用法
固定定位的悬浮按钮,可用于悬浮操作入口、回到顶部等场景。
- 支持八方位预设位置,也可自由拖动,松手后自动吸附至左右两侧
- 按钮当前位置支持双向绑定,位置变化时派发事件
- Web 端支持鼠标拖动,窗口尺寸变化时自动重新校正位置
```vue
```
**更多演示请下载 demo 查看**
## 属性
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
| --- | --- | --- | --- | --- |
| v-model | 按钮当前位置坐标,形如 `[x, y]` | `Array` | `[0, 0]` | - |
| position | 预设位置(`init` 为 true 时初始化定位至此) | String | `bottom` | `top-start` \| `top` \| `top-end` \| `right` \| `bottom-end` \| `bottom` \| `bottom-start` \| `left` |
| init | 是否在初始化时定位到 `position` 预设位置 | Boolean | `true` | `true` \| `false` |
| absorb | 松手后是否自动吸附至左右两侧 | Boolean | `true` | `true` \| `false` |
| disabled | 是否禁用(禁用后不可拖动、不响应点击) | Boolean | `false` | `true` \| `false` |
| bgColor | 背景颜色,支持 `$` 简写 | String | `$front` | - |
| size | 按钮尺寸(宽高相同) | String \| Number | `60px` | - |
| icon | 内置图标名称 | String | `''` | - |
| iconColor | 图标颜色,支持 `$` 简写,禁用时为禁用色 | String | `$text` | - |
| iconSize | 图标字体大小 | String \| Number | `$30` | - |
| margin | 处于预设位置或吸附时与屏幕边缘的边距 | Number | `20` | - |
| borderRadius | 圆角大小 | String \| Number | `$12000` | - |
| boxShadow | 阴影 | String | `0 0 15px -10px` | - |
| aniTime | 拖动松手 / 吸附时的过渡动画时长 | String \| Number | `$long` | - |
| customStyle | 根节点自定义样式 | SnStyleValue | `''` | - |
## 事件
| 名称 | 类型 | 说明 |
| --- | --- | --- |
| click | (event: UniPointerEvent) => Void | 点击按钮时触发(禁用时不触发) |
| change | `(position: Array) => Void` | 初始化定位或拖动结束时触发,携带当前位置坐标 |
## 插槽
| 名称 | 说明 |
| --- | --- |
| default | 替换按钮内部默认的图标 |
# Swipe Action 滑动操作
> [查看 sn-swipe-action 的 2.0 版本差异](/differences/components/sn-swipe-action)
## 基础用法
列表项的滑动操作组件:左滑露出右侧操作区,右滑露出左侧操作区。
- 操作区宽度由插槽内容自动决定,可放置任意自定义内容
- 左右操作区与主体内容自动等高(以主体内容高度为准),Web 端支持鼠标拖动
- 多个滑动操作自动联动:打开一个自动收起其他,点击内容区收起全部
::: danger 插槽布局注意
- 使用注意:请勿给 `left` / `right` 插槽的根节点设置 `height: 100%`,也无需为操作区指定高度,`align-self: stretch` 即可铺满
- 使用注意:插槽根节点请勿对 `height` / `width` 等布局属性开启过渡动画(`transition-property: all` 同样包含布局属性),布局变化时会触发异常的尺寸动画;如需过渡动画仅限 `background-color` 等非布局属性
:::
```vue
滑动显示操作
编辑
删除
```
**更多演示请下载 demo 查看**
## 异步确认关闭
设置 `before-close` 后,在展开状态下点击主体内容时会先调用该回调,Promise resolve `true` 才会收起操作区。
```vue
确认后才会收起操作区
删除
```
## 主动控制
通过实例方法 `open` / `close` 控制展开与收起,`open` 参数为露出的操作区方向。
```vue
可编程控制的操作项
删除
```
## 属性
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
| --- | --- | --- | --- | --- |
| disabled | 是否禁用滑动操作 | Boolean | `false` | `true` \| `false` |
| threshold | 默认打开阈值:松手时滑过操作区宽度的该比例即吸附打开(openThreshold 为空时生效) | Number | `0.4` | - |
| openThreshold | 自定义打开阈值,支持百分比(如 `20%`)、像素(如 `60px`)或数字(按 px 处理),跟随 `threshold` | String \| Number | - | - |
| beforeClose | 关闭前的确认回调,返回 Promise,resolve `true` 才会收起操作区;参数 direction 为当前露出的操作区方向 | (direction: string) => Promise<boolean> \| null | `null` | - |
| customStyle | 自定义根节点样式 | SnStyleValue | `''` | - |
| customClass | 自定义根节点样式类 | String | `''` | - |
## 事件
| 名称 | 类型 | 说明 |
| --- | --- | --- |
| open | (direction: string) => Void | 操作区打开时触发,direction 为露出的操作区方向:`left` 左侧(右滑)、`right` 右侧(左滑) |
| close | () => Void | 操作区关闭时触发 |
## 方法
| 名称 | 参数 | 返回值 | 描述 |
| --- | --- | --- | --- |
| open | direction: string | - | 打开指定方向的操作区(`left` 左侧 / `right` 右侧) |
| close | - | - | 关闭操作区 |
## 插槽
| 名称 | 说明 |
| --- | --- |
| default | 主体内容 |
| left | 左侧操作区(右滑露出) |
| right | 右侧操作区(左滑露出) |
# Loadmore 加载更多
> [查看 sn-loadmore 的 2.0 版本差异](/differences/components/sn-loadmore)
## 基础用法
用于标识页面底部加载数据时的状态。
- 提供加载更多、加载中、没有更多三种状态,加载更多状态可点击触发事件
- 两侧线条支持实线与虚线
::: info 平台差异
加载状态文案保留独立的文字节点,兼容 HarmonyOS 原生绘制。
:::
```vue
```
**更多演示请下载 demo 查看**
加载状态文案保留独立的文字节点,兼容 HarmonyOS 原生绘制。
## 加载状态切换
配合列表加载流程切换 `status`:点击加载更多后进入加载中,数据加载完毕后标记为没有更多。
```vue
```
## 属性
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
| --- | --- | --- | --- | --- |
| status | 加载状态 | String | `loadmore` | `loadmore` \| `loading` \| `nomore` |
| loadmoreText | loadmore 状态显示的文本 | String | `加载更多` | - |
| nomoreText | nomore 状态显示的文本 | String | `没有更多了` | - |
| loadingText | loading 状态显示的文本 | String | `加载中` | - |
| textSize | 文本字体大小 | String \| Number | `$13` | - |
| iconSize | 加载指示器大小,与文本字号一致 | String \| Number | - | - |
| iconColor | 加载指示器颜色 | String | `$primary` | - |
| textColor | 文本颜色 | String | `$lineText` | - |
| lineColor | 两侧线条颜色 | String | `$line` | - |
| lineHeight | 两侧线条粗细 | String \| Number | `0.5px` | - |
| disabled | 是否禁用,禁用时 loadmore 状态点击不触发事件 | Boolean | `false` | `true` \| `false` |
| dashed | 两侧线条是否为虚线 | Boolean | `false` | `true` \| `false` |
| loadingClass | 自定义 loading 指示器节点外部样式类 | String | - | - |
| loadingStyle | 自定义 loading 指示器节点内联样式 | SnStyleValue | `border-color: <主题线条文本色>` | - |
| customStyle | 自定义根节点样式 | SnStyleValue | - | - |
## 事件
| 名称 | 类型 | 说明 |
| --- | --- | --- |
| loadmore | () => Void | 点击加载更多时触发(仅 status 为 `loadmore` 且未禁用时响应) |
# Pagination 分页器
## 基础用法
分页器,用于列表内容的分页导航。
- 当前页码支持双向绑定,总页数可直接指定,也可由数据总条数自动计算
- 页码较多时自动显示省略号,实际展示的页码按钮数量可配置
- 支持整体禁用所有按钮与跳转输入框
```vue
```
**更多演示请下载 demo 查看**
## 快速跳转
开启 `showQuickJumper` 后显示跳转输入框,输入页码后回车或失焦生效,超出范围自动收敛。可通过 `goto` 插槽自定义输入框前的提示文字。
```vue
前往
```
## 简单模式
`simple` 设为 true 时仅显示“当前页 / 总页数”,配合 `showQuickJumper` 可直接输入页码跳转。
```vue
```
## 属性
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
| --- | --- | --- | --- | --- |
| v-model:page | 当前页码 | Number | `1` | - |
| v-model:page-size | 每页条数,与 `itemCount` 配合自动计算总页数 | Number | `10` | - |
| pageCount | 总页数;取值不大于 1 时若 `itemCount` 大于 0,则按 `itemCount` / `pageSize` 向上取整自动计算 | String \| Number | `1` | - |
| pageSlot | 页码按钮最大显示数量(含省略号占位) | String \| Number | `5` | - |
| itemCount | 数据总条数,用于自动计算总页数 | String \| Number | `-1` | - |
| simple | 简单模式,仅显示“当前页 / 总页数” | Boolean | `false` | `true` \| `false` |
| disabled | 是否禁用 | Boolean | `false` | `true` \| `false` |
| showQuickJumper | 是否显示快速跳转输入框(回车或失焦生效) | Boolean | `false` | `true` \| `false` |
| showPrevNext | 是否显示上一页 / 下一页按钮 | Boolean | `true` | `true` \| `false` |
| buttonType | 页码按钮与翻页按钮的功能色类型 | String | `info` | `primary` \| `info` \| `success` \| `error` \| `warning` |
| buttonLevel | 页码按钮与翻页按钮的等级 | String | `first` | `first` \| `second` \| `third` \| `least` |
| size | 页码按钮宽高(正方形),同时决定跳转输入框高度 | String \| Number | `$35` | - |
| gap | 按钮之间的间距 | String \| Number | `4` | - |
| customStyle | 根节点自定义样式 | SnStyleValue | `''` | - |
| customClass | 根节点自定义样式类 | String | `''` | - |
| pageClass | 页码按钮与翻页按钮的自定义样式类 | String | `''` | - |
| pageStyle | 页码按钮与翻页按钮的自定义样式 | SnStyleValue | `''` | - |
| activePageClass | 当前页码按钮的自定义样式类 | String | `''` | - |
| activePageStyle | 当前页码按钮的自定义样式 | SnStyleValue | `''` | - |
| buttonTextClass | 页码、省略号与翻页按钮文字的自定义样式类 | String | `''` | - |
| buttonTextStyle | 页码、省略号与翻页按钮文字的自定义样式 | SnStyleValue | `line-height: 1;` | - |
| simpleTextClass | 简单模式文字的自定义样式类 | String | `''` | - |
| simpleTextStyle | 简单模式文字的自定义样式 | SnStyleValue | `''` | - |
| jumperClass | 跳转区域的自定义样式类 | String | `''` | - |
| jumperStyle | 跳转区域的自定义样式 | SnStyleValue | `''` | - |
| jumperInputClass | 跳转输入框的自定义样式类 | String | `''` | - |
| jumperInputStyle | 跳转输入框的自定义样式 | SnStyleValue | `''` | - |
## 插槽
| 名称 | 说明 |
| --- | --- |
| prefix | 分页器最前部的附加内容 |
| suffix | 分页器最后部的附加内容 |
| prev | 替换上一页按钮内容(默认为左箭头图标) |
| next | 替换下一页按钮内容(默认为右箭头图标) |
| goto | 快速跳转输入框前的提示文字(默认为“跳至”),仅非简单模式生效 |
# Waterflow 瀑布流
> [查看 sn-waterflow 的 2.0 版本差异](/differences/components/sn-waterflow)
## 基础用法
数据驱动的瀑布流组件,按多列排布不定高条目,支持下拉刷新与滚动加载。
- 数据由数组传入,通过默认作用域插槽渲染每条内容
- 内置下拉刷新、加载更多与回到顶部按钮
- 支持自定义列数与行列间距,Web 端可按容器宽度自适应列数
::: danger type 保留值
App 端条目按数据项 `type` 字段分组复用,其中下拉刷新条目占用 `2`、加载更多条目占用 `6`,业务数据请避开这两个值。
:::
::: info 插槽 item 类型
插槽的 `item` 为 `any` 类型,对象的字段访问需在函数体内 `as` 强转后使用,不要直接在模板内访问属性。
:::
```vue
{{ flowTitle(slotProps.item) }}
```
**更多演示请下载 demo 查看**
## 实现原理
App 端基于官方 `waterflow` 组件,条目以 `flow-item` 复用回收;Web 端为自研虚拟滚动瀑布流,动态测量条目高度,仅渲染可视区域及 `overscan` 范围内的条目。内置的下拉刷新、加载更多与回到顶部按钮分别由 `sn-refresher`、`sn-loadmore`、`sn-backtop` 实现。
## 自定义列数与响应式断点
- `cross-axis-count` 控制基础列数(最小为 1)。
- Web 端支持两种自适应方式:`col-width` 大于 0 时按容器宽度与列宽计算实际列数(不超过 `cross-axis-count`);`breakpoints` 传入响应式断点数组(`minWidth` 容器最小宽度、`columns` 对应列数),取容器宽度匹配到的最后一项。
```vue
```
## 无限加载
- `loadmore` 开启后触底自动触发 `loadmore` 事件(App 端与 Web 端均为滚动接近底部时触发,触发距离由 `lower-threshold` 控制)。
- 无限滚动场景可将 `show-loadmore` 设为 `false` 隐藏底部加载状态条,加载逻辑照常生效。
```vue
```
## 属性
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
| --- | --- | --- | --- | --- |
| list | 列表数据数组,数据项可为任意对象,App 端支持 `type` 数字字段声明复用分组 | Array | `[]` | - |
| crossAxisCount | 列数 | Number | `2` | - |
| crossAxisGap | 列间距(支持 `$` 简写) | String \| Number | `10px` | - |
| mainAxisGap | 行间距(支持 `$` 简写) | String \| Number | `10px` | - |
| colWidth | 单列基准宽度(单位 px,Web 端生效;大于 0 时按容器宽度自适应实际列数,不超过 `crossAxisCount`) | Number | `0` | - |
| estimatedItemHeight | 条目预估高度(单位 px,Web 端虚拟滚动初始布局用,实际高度测量后自动修正) | Number | `280` | - |
| overscan | 虚拟滚动预渲染范围(单位 px,Web 端生效) | Number | `400` | - |
| breakpoints | 响应式断点数组(Web 端生效),每项含 `minWidth`(容器最小宽度)与 `columns`(对应列数) | SnWaterflowBreakpoint[] | `[]` | - |
| v-model:refresher-triggered | 绑定当前下拉刷新状态 | Boolean | `false` | `true` \| `false` |
| v-model:loadmore-status | 绑定加载更多组件状态,触底或点击加载更多时组件内部自动改写为 `loading`,由父组件在 `loadmore` 事件中更新加载结果 | String | `loadmore` | `loadmore` \| `loading` \| `nomore` |
| refresherEnabled | 是否开启下拉刷新 | Boolean | `false` | `true` \| `false` |
| refresherConfig | 下拉刷新组件配置(`refreshText`、`refreshingText`、`textSize`、`textColor`、`icon`、`iconSize`、`iconColor`) | `SnRefresherParams` | `{}` | - |
| refresherThreshold | 下拉刷新阈值(单位 px) | Number | `45` | - |
| refresherMaxDragDistance | 下拉最大拖拽距离(单位 px) | Number | `0` | - |
| refresherBackground | 下拉刷新区域背景颜色 | String | `transparent` | - |
| refresherDefaultStyle | 下拉刷新默认样式;开启下拉刷新时组件强制使用自定义刷新条 | String | `black` | `white` \| `black` \| `none` |
| loadmore | 是否开启加载更多 | Boolean | `true` | `true` \| `false` |
| showLoadmore | 是否显示底部加载状态条(为 `false` 时隐藏条目但加载逻辑照常生效) | Boolean | `true` | `true` \| `false` |
| loadmoreConfig | 加载更多组件配置(`loadmoreText`、`nomoreText`、`loadingText`、`textSize`、`textColor`、`iconSize`、`iconColor`、`lineHeight`、`lineColor`、`dashed`、`disabled`) | `SnLoadmoreParams` | `{}` | - |
| backtop | 是否内置回到顶部按钮 | Boolean | `false` | `true` \| `false` |
| backtopTarget | 内置回到顶部按钮的绑定目标(ref 名或元素 id) | String | `''` | - |
| backtopTop | 内置回到顶部按钮的显示阈值(滚动距离,单位 px) | Number | `400` | - |
| backtopRight | 内置回到顶部按钮距右边界距离(单位 px) | Number | `30` | - |
| backtopBottom | 内置回到顶部按钮距下边界距离(单位 px) | Number | `100` | - |
| bounces | 是否启用回弹效果(App 端) | Boolean | `true` | `true` \| `false` |
| associativeContainer | 关联的滚动容器(App 端嵌套滚动场景使用) | String | `''` | - |
| maxCrossAxisExtent | 单列最大宽度(单位 px,超过则自动增加列数;iOS / HarmonyOS 端生效) | String \| Number | `0` | - |
| upperThreshold | 距顶部多远时(单位 px)触发 `scrolltoupper` 事件 | Number | `50` | - |
| lowerThreshold | 距底部多远时(单位 px)触发 `scrolltolower` 事件并触发加载更多 | Number | `50` | - |
| scrollTop | 设置竖向滚动条位置 | Number | `0` | - |
| scrollLeft | 设置横向滚动条位置 | Number | `0` | - |
| scrollIntoView | 值应为某子元素 id(id 不能以数字开头),滚动到该元素 | String | `''` | - |
| scrollWithAnimation | 设置滚动条位置时是否使用滚动动画 | Boolean | `true` | `true` \| `false` |
| showScrollbar | 是否显示滚动条 | Boolean | `true` | `true` \| `false` |
| androidOverscroll | Android 端是否开启弹簧回弹效果 | Boolean | `false` | `true` \| `false` |
| androidScrollbarDraggable | Android 端滚动条是否可拖拽 | Boolean | `false` | `true` \| `false` |
| androidRefresherColor | Android 端下拉刷新默认样式颜色 | String | `''` | - |
| enableBackToTop | 点击状态栏回到顶部(iOS 端生效) | Boolean | `false` | `true` \| `false` |
| enablePassive | Web 端原生滚动监听是否使用 passive 模式 | Boolean | Web 端 `true`,其他端 `false` | `true` \| `false` |
| customStyle | 自定义根节点样式 | SnStyleValue | `''` | - |
| customClass | 自定义根节点外部样式类 | String | `''` | - |
> 类型字段:SnRefresherParams(见 https://sinleui.pages.dev/api/types/component#snrefresherparams)
> 类型字段:SnLoadmoreParams(见 https://sinleui.pages.dev/api/types/component#snloadmoreparams)
## 事件
| 名称 | 类型 | 说明 |
| --- | --- | --- |
| refresh | () => Void | 下拉刷新被触发时触发(下拉手势或调用 `refresh` 方法),App 端与 `refresherrefresh` 同步触发 |
| scrolltoupper | (e: UniScrollToUpperEvent) => Void | 滚动到顶部时触发,同时内部复位下拉刷新条(App 端) |
| scrolltolower | (e: UniScrollToLowerEvent) => Void | 滚动到底部时触发,开启 `loadmore` 时自动触发加载(App 端) |
| scroll | (e: UniScrollEvent) => Void | 滚动时触发(App 端) |
| scrollend | (e: UniScrollEvent) => Void | 滚动结束时触发(App 端) |
| refresherpulling | (e: UniRefresherEvent) => Void | 下拉刷新控件被下拉时触发(App 端) |
| refresherrefresh | (e: UniRefresherEvent) => Void | 下拉刷新被触发时触发(App 端) |
| refresherrestore | (e: UniRefresherEvent) => Void | 下拉刷新被复位时触发(App 端) |
| refresherabort | (e: UniRefresherEvent) => Void | 下拉刷新被中止时触发(App 端) |
| loadmore | () => Void | 触底或点击加载状态条时触发,仅在开启 `loadmore` 且状态为 `loadmore` 时生效,触发后状态自动变为 `loading`(App / Web 端均生效) |
## 方法
| 名称 | 参数 | 返回值 | 描述 |
| --- | --- | --- | --- |
| scrollTo | top: Number, left: Number(默认 0) | - | 滚动到指定位置(单位 px),Web 端带平滑动画 |
| refresh | - | - | 主动触发下拉刷新,进入刷新中状态并置位 `refresher-triggered`,同时触发 `refresh` 事件 |
| stopRefresh | - | - | 结束下拉刷新,恢复可下拉状态并复位 `refresher-triggered` |
| loadMore | - | - | 主动触发一次加载更多(等同触底效果) |
| registerBacktop | update: (scrollTop: Number) => Void | - | 注册滚动位置更新回调,供 `sn-backtop` 绑定(一般无需手动调用) |
## 插槽
| 名称 | 说明 |
| --- | --- |
| default | 作用域插槽,渲染每一条数据,作用域参数:`item`(当前数据项)、`index`(当前索引);App 端同 `type` 数据项共用此模板复用回收 |
# Footer 页脚
## 基础用法
页脚组件,常用于页面底部展示品牌 Logo、导航链接与版权信息。
- Logo、链接与版权三部分均可选,按需组合
- Logo 支持图标名或图片路径,地址按形态自动识别为图片
- 链接间自动添加竖向分隔线,点击链接 / Logo 后按打开方式自动跳转
```vue
```
**更多演示请下载 demo 查看**
## 注意事项
Logo 图标支持图标名或图片路径:`http` 开头、以 `/`、`./`、`../` 开头或包含 `.` 的地址按图片处理。
## 属性
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
| --- | --- | --- | --- | --- |
| links | 导航链接列表,字段见下方 `SnFooterLink` | Array<`SnFooterLink`> | `[]` | - |
| logo | 品牌 Logo 配置,字段见下方 `SnFooterLogo` | `SnFooterLogo` | `null` | - |
| text | 页脚文字(一般为版权信息) | String | `''` | - |
| color | Logo 标题颜色 | String | `$title` | - |
| linkColor | 链接文字颜色 | String | `$primary` | - |
| lineColor | 链接分隔线颜色 | String | `$line` | - |
| textColor | 页脚文字颜色 | String | `$textLight` | - |
| customStyle | 自定义根节点样式 | SnStyleValue | `''` | - |
| customClass | 自定义根节点样式类 | String | `''` | - |
| linkClass | 链接文字样式类 | String | `''` | - |
| textClass | 页脚文字样式类 | String | `''` | - |
> 类型字段:SnFooterLink(见 https://sinleui.pages.dev/api/types/component#snfooterlink)
> 类型字段:SnFooterLogo(见 https://sinleui.pages.dev/api/types/component#snfooterlogo)
## 事件
| 名称 | 类型 | 说明 |
| --- | --- | --- |
| linkclick | (link: `SnFooterLink`, index: number) => Void | 点击链接时触发,携带链接数据与索引(跳转仍会执行,可用 `openType: 'none'` 阻止默认跳转自行处理) |
| logoclick | () => Void | 点击 Logo 时触发(Logo 配置了 `url` 时跳转仍会执行) |
# Topbar 导航栏
> [查看 sn-topbar 的 2.0 版本差异](/differences/components/sn-topbar)
## 基础用法
页面顶部导航栏,包含标题、返回按钮与右侧功能区。
- 固定与非固定模式共用一个根容器,默认固定在页面顶部
- 支持背景模糊;可让根容器背景向上延伸覆盖状态栏区域,避免顶部露底或状态栏与内容重叠
- 返回按钮点击时派发事件,页面栈大于 1 时自动返回;导航栏高度默认取全局配置,可单独指定
```vue
```
**更多演示请下载 demo 查看**
## 功能按钮与下拉菜单
`features` 配置右侧功能按钮,每项通过 `icon`(图标)或 `text`(文字)定义内容。`menuButton` 显示"更多"按钮,`menuData` 配置下拉菜单项(配置后菜单按钮自动显示),菜单项选中时触发 `menuselect`。
```vue
```
## 自定义样式
`bg-color` 设置背景色,`title-style` / `title-class` 定制标题,`button-style` 定制按钮,`hover-button-style` 定制按钮按压态,适配主题色或深色导航背景。
```vue
```
## 背景模糊与布局
`blur` 在整体根容器上设置 `backdrop-filter: blur(...)`,Web 同时设置 `-webkit-backdrop-filter`。不创建额外背景层、状态栏层或占位层;`statusBar` 开启时根容器向上覆盖状态栏区域,模糊同样作用于状态栏区域。
菜单弹层独立于导航栏根容器,避免 `backdrop-filter` 改变 Web 固定定位弹层的包含块,影响遮罩范围和菜单锚点定位。
未传 `bgColor` 时,启用模糊会将主题页面背景色转换为半透明颜色,透明度由 `blurOpacity` 控制。显式传入 `bgColor` 时保留该颜色自身的透明度,例如 `rgba(255, 255, 255, 0.58)`;不透明背景会遮住背景模糊效果。
Demo 首页 `pages/index/index.uvue` 的顶部与底部导航栏均启用模糊,半径为 `20px`、背景透明度为 `0.68`;不显式传入背景色,随亮暗主题自动切换。首页顶部导航栏根容器随 `statusBar` 向上覆盖状态栏区域,安全距离和内容占位仍由页面管理。
固定导航栏不会撑开文档流,请在使用方为内容设置间距;`statusBar` 默认开启(背景覆盖状态栏、内容预留状态栏高度),内容间距应取 `$snui.topbarHeightResolved` 加状态栏高度,最简做法是在导航栏后叠加一个 ``。使用 `sn-page` 的内置导航栏时,这些布局由 `sn-page` 处理。非固定模式导航栏本身占据文档流,同样会预留状态栏高度。
未显示返回按钮且未提供 `header` 插槽时,根容器仍保留 `16 × paddingFactor` px 左内边距;有左侧内容时为 `8 × paddingFactor` px。不通过空侧栏实现留白。
```vue
```
## 属性
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
| --- | --- | --- | --- | --- |
| title | 标题文本 | String | `''` | - |
| backButton | 是否显示返回按钮 | Boolean | `true` | `true` \| `false` |
| backButtonIcon | 返回按钮图标名 | String | `'arrow-left-s-line'` | - |
| fixed | 是否固定在页面顶部,不生成占位 | Boolean | `true` | `true` \| `false` |
| statusBar | 是否向上覆盖状态栏区域并为内容预留状态栏高度 | Boolean | `true` | `true` \| `false` |
| titleAlign | 标题对齐方式 | String | `'left'` | `left` \| `center` \| `right` |
| features | 右侧功能按钮数据,每项可配置 icon(图标)或 text(文字) | Array<`SnDataItem`> | `[]` | - |
| menuButton | 是否显示"更多"菜单按钮(menuData 非空时自动显示) | Boolean | `false` | `true` \| `false` |
| menuData | 下拉菜单数据,点击菜单按钮弹出内置菜单 | Array<`SnDataItem`> | `[]` | - |
| bgColor | 背景颜色 | String | `$page` | - |
| blur | 是否启用背景高斯模糊 | Boolean | `false` | `true` \| `false` |
| blurRadius | 背景高斯模糊半径(单位 px) | Number | `15` | - |
| blurOpacity | 未传 bgColor 时的模糊背景透明度,取值 0~1,不影响标题和按钮 | Number | `0.78` | - |
| height | 导航栏内容区高度(不含状态栏,Number 单位 px),取全局配置 `$snui.topbarHeight`(Web 端 + 8px,其他端直接使用该值);`statusBar` 开启时根容器总高度为该值加状态栏高度 | String \| Number | - | - |
| zIndex | 固定定位时的层级 | Number | `998` | - |
| customStyle | 自定义根节点样式 | SnStyleValue | `''` | - |
| customClass | 根节点外部样式类,通过 custom-class 传入 | String | `''` | - |
| titleStyle | 自定义标题样式 | SnStyleValue | `''` | - |
| titleClass | 标题外部样式类 | String | `''` | - |
| buttonStyle | 自定义返回/功能/菜单按钮样式 | SnStyleValue | `''` | - |
| hoverButtonStyle | 自定义按钮按压态样式 | SnStyleValue | `''` | - |
| buttonTextStyle | 自定义按钮文字样式(features 中纯文字按钮) | SnStyleValue | `''` | - |
| buttonIconStyle | 自定义按钮图标样式 | SnStyleValue | `''` | - |
> 类型字段:SnDataItem(见 https://sinleui.pages.dev/api/types/component#sndataitem)
## 事件
| 名称 | 类型 | 说明 |
| --- | --- | --- |
| back | () => Void | 点击返回按钮时触发;页面栈大于 1 时组件会自动执行返回 |
| featureclick | (item: `SnDataItem`, index: number) => Void | 点击功能按钮时触发;点击"更多"菜单按钮且未配置菜单数据时也会触发(item 仅含 icon,index 为 -1) |
| menuselect | (item: `SnDataItem`, index: number) => Void | 选择下拉菜单项时触发 |
## 插槽
| 名称 | 说明 |
| --- | --- |
| header | 替换左侧返回按钮区域 |
| default | 替换中间标题区域 |
| footer | 替换右侧功能按钮区域 |
# Tabbar 底部导航栏
> [查看 sn-tabbar 的 2.0 版本差异](/differences/components/sn-tabbar)
## 基础用法
底部导航栏,用于在页面底部切换子页面,支持文字、字体图标与图片子项,样式可自由定制。
- 子项由数据项配置自动渲染,无需手动引入子项组件,支持拦截鉴权与角标
- 支持固定底部与内嵌两种模式,可开启毛玻璃背景,图标与文字保持清晰
- 为每个子项提供子页面插槽,最多 10 项
```vue
```
**更多演示请下载 demo 查看**
## 实现原理
固定底部(`fixed`)与内嵌(`fixed=false`)模式共用一个主体容器,定位、背景、边框、圆角与模糊均作用于该容器。
## 子页面与占位高度
推荐给固定 Tabbar 设置 `tabbar-key="home"`,子页面调用 [useTabbarHeights](/api/hooks/use-tabbar-heights),通过 `tabbarHeights['home']` 读取实际高度。每个 `sn-page` 的登记表独立,不同页面同名 key 不冲突;同页不同 Tabbar 需使用不同 key。默认 key 为空,不登记。
**占位必须放在子页面 scroll-view 的滚动内容末尾,而不是子组件外侧或页面根布局的底部。** 外侧占位会缩短滚动视口,使 Tabbar 背后一直是空白,无法采样滚动内容形成毛玻璃。首页三个子页面已采用滚动内容末尾占位,首页不再保留外层 `tabbar-safe`。
`fixed` 模式使用固定定位,组件不会自动占位或添加安全区 padding。通过 `v-model:height` 拿到主体实际高度自行放置占位(如 sn-gap),不要手动修改组件输出的高度;该高度包含主体内边距和边框,但不包含外边距、底部偏移或额外安全距离。需要安全距离时,可通过 `customStyle` 设置 `bottom`,并在使用方占位高度中另加安全距离与底部外边距。
`tab1` ~ `tab10` 的页面容器独立于导航栏主体,不受主体的固定定位或背景模糊影响。首次切换到某页才挂载,后续切换保留状态;`showPages=false` 时不渲染子页面。组件不为这些页面自动添加底部间距,需在页面滚动内容末尾自行处理。
```vue
页面内容
```
## 毛玻璃背景
设置 `blur` 后,只在主体容器上设置 `backdrop-filter: blur(...)`,Web 同时设置 `-webkit-backdrop-filter`。关闭时设置 `none`,不创建额外背景层或原生模糊层。
未传 `bgColor` 时使用主题 `front` 色,启用模糊后由 `blurOpacity` 控制背景透明度。显式传入 `bgColor` 时保留该颜色自身的透明度,例如 `rgba(255, 255, 255, 0.58)`;不透明背景会遮住模糊效果。不会通过容器 `opacity` 降低图标和文字的透明度。
Demo 首页 `pages/index/index.uvue` 的顶部与底部导航栏均使用 `blur=true`、`blurRadius=20`、`blurOpacity=0.68`,未显式设置背景色以便随亮暗主题切换;安全距离与占位由首页管理。
```vue
```
App 毛玻璃依赖蒸汽模式的 `backdrop-filter` 支持,不再提供 VDOM 原生模糊层回退。固定模式和内嵌模式均保留 `padding` 指定的内部边距,默认 `$10`,包括首尾子项到容器边缘的距离;不会用空子项来制造边距。
## 数据项 SnTabbarItem
`data` 为 SnTabbarItem[],字段如下:
> 类型字段:SnTabbarItem(见 https://sinleui.pages.dev/api/types/component#sntabbaritem)
---
:::
## 属性
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
| --- | --- | --- | --- | --- |
| v-model:height | 导航栏主体实际高度,供外部占位,不含外边距、底部偏移或自动安全区 | String | `''` | - |
| data | 底部导航栏数据,每一项与插槽一 一匹配,最多 10 项 | Array<`SnTabbarItem`> | `[]` | - |
| index | 首次加载时显示的页面索引(从 1 开始) | Number | `1` | - |
| fixed | 是否固定底部 | Boolean | `true` | `true` \| `false` |
| tabbarKey | 固定 Tabbar 高度登记键;在最近的 sn-page 作用域内唯一,空值不登记,子页面通过 useTabbarHeights 读取 | String | `''` | - |
| showPages | 是否显示子页面插槽内容 | Boolean | `true` | `true` \| `false` |
| imageSize | 子项图片大小(`$` 简写乘字体乘数) | String \| Number | `''` | - |
| padding | 导航栏内边距(`$` 简写乘内边距乘数) | String \| Number | `'$10'` | - |
| margin | 导航栏外边距 | String \| Number | `'0px'` | - |
| bgColor | 导航栏背景颜色 | String | `$front` | - |
| blur | 是否启用背景高斯模糊 | Boolean | `false` | `true` \| `false` |
| blurRadius | 背景高斯模糊半径(单位 px) | Number | `15` | - |
| blurOpacity | 未传 bgColor 时的模糊背景透明度,取值 0~1,不影响图标和文字 | Number | `0.78` | - |
| itemBorderRadius | 子项圆角大小,组件根据导航栏圆角自动计算最合适值 | String \| Number | - | - |
| itemPadding | 子项内边距,透传到 sn-tabbar-item 的 padding,支持 `$` 简写 | String \| Number | `'$5 0'` | - |
| itemSpacing | 各子项之间的间距 | String \| Number | `'0px'` | - |
| itemBgColor | 子项背景颜色 | String | `var(--sn-transparent)` | - |
| itemActiveBgColor | 选中子项的背景颜色 | String | `var(--sn-transparent)` | - |
| border | 导航栏边框 | String | `1px solid var(--sn-line)` | - |
| borderRadius | 导航栏圆角大小 | String \| Number | `'0'` | - |
| textColor | 子项文本颜色 | String | `$text` | - |
| textSize | 子项文本大小 | String \| Number | `$11` | - |
| activeTextColor | 选中子项文本颜色 | String | `$primary` | - |
| iconColor | 子项图标颜色 | String | `$text` | - |
| iconSize | 子项图标大小 | String \| Number | `$22` | - |
| activeIconColor | 选中子项图标颜色 | String | `$primary` | - |
| disabled | 是否禁用整个导航栏 | Boolean | `false` | `true` \| `false` |
| hoverStyle | 子项按压态样式 | SnStyleValue | `'background: var(--sn-info);'` | - |
| hoverStartTime | 按压生效延迟(单位 ms) | Number | `50` | - |
| hoverStayTime | 按压保持时长(单位 ms) | Number | `0` | - |
| hoverTransTime | 按压过渡时长(单位 ms,`$` 简写乘动画乘数) | String \| Number | `''` | - |
| hoverStopPropagation | 按压事件是否阻止冒泡 | Boolean | `false` | `true` \| `false` |
| customStyle | 自定义导航栏样式 | SnStyleValue | `''` | - |
| customClass | 导航栏主体外部样式类,通过 custom-class 传入 | String | `''` | - |
| customContainStyle | 子页面容器样式;未提供子页面插槽时,兼容旧调用合并到主体,后置 customStyle 优先 | SnStyleValue | `''` | - |
## 事件
| 名称 | 类型 | 说明 |
| --- | --- | --- |
| change | (index: number) => Void | 页面切换时触发,index 从 1 开始 |
| heightchange | (height: number) => Void | 导航栏主体实际高度变化时触发,不包含外边距、底部偏移或自动安全区 |
## 方法
| 名称 | 参数 | 返回值 | 描述 |
| --- | --- | --- | --- |
| changeToIndex | `(index: number)` | - | 切换到指定索引的页面,索引值即为插槽名称(如 #tab1 的索引为 1) |
## 插槽
| 名称 | 说明 |
| --- | --- |
| tab1 ~ tab10 | 第 n 个子页面,须与 data 项一 一对应 |
## sn-tabbar-item 属性
`sn-tabbar` 的子项组件,由 `data` 自动渲染,无需手动引入;下列属性均由 `sn-tabbar` 按组配置逐项下发。
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
| --- | --- | --- | --- | --- |
| data | 该项的数据对象 | [SnTabbarItem](/api/types/component#sntabbaritem) | `null` | - |
| index | 该项在 `data` 中的索引 | Number | `0` | - |
| active | 是否为当前选中项 | Boolean | `false` | `true` \| `false` |
| disabled | 是否禁用该项(禁用后不触发 click) | Boolean | `false` | `true` \| `false` |
| isFirst | 是否为第一项(首尾圆角与间距处理用) | Boolean | `false` | `true` \| `false` |
| isLast | 是否为最后一项(首尾圆角与间距处理用) | Boolean | `false` | `true` \| `false` |
| padding | 子项内边距,默认上下 5 × paddingFactor px、左右 0,支持 `$` 简写 | String \| Number | `'$5 0'` | - |
| itemPadding | 兼容旧调用的子项内边距,非空时优先于 padding,支持 `$` 简写 | String \| Number | `''` | - |
| itemBorderRadius | 子项圆角(支持 `$` 简写) | String | `0px` | - |
| itemBgColor | 子项背景颜色 | String | `''` | - |
| itemActiveBgColor | 选中子项背景颜色 | String | `''` | - |
| textColor | 子项文本颜色 | String | `''` | - |
| activeTextColor | 选中子项文本颜色 | String | `''` | - |
| textSize | 子项文本大小(支持 `$` 简写) | String | `''` | - |
| iconColor | 子项图标颜色 | String | `''` | - |
| activeIconColor | 选中子项图标颜色 | String | `''` | - |
| iconSize | 子项图标大小(支持 `$` 简写) | String | `''` | - |
| imageSize | 子项图片大小(`data` 项设置 `image` 时生效,支持 `$` 简写) | String | `35px` | - |
| itemSpacingHalf | 子项间距的一半(首尾对齐用,支持 `$` 简写) | String | `0px` | - |
| hoverStyle | 子项按压态样式 | SnStyleValue | `background: var(--sn-info);` | - |
| hoverStartTime | 按压生效延迟(单位 ms) | Number | `50` | - |
| hoverStayTime | 按压保持时长(单位 ms) | Number | `0` | - |
| hoverTransTime | 按压过渡时长(单位 ms,`$` 简写乘动画乘数) | String \| Number | `''` | - |
| hoverStopPropagation | 按压事件是否阻止冒泡 | Boolean | `false` | `true` \| `false` |
## sn-tabbar-item 事件
| 名称 | 类型 | 说明 |
| --- | --- | --- |
| click | (index: number) => Void | 点击子项时触发,`index` 为该项在 `data` 中的索引(禁用项不触发) |
# Sidebar 侧边栏
> [查看 sn-sidebar 的 2.0 版本差异](/differences/components/sn-sidebar)
## 基础用法
侧边导航栏,适用于商城选购等场景。
- 左侧为选项列表,选中索引支持双向绑定
- 右侧为内容区,可通过默认插槽自定义
- 支持锚点定位与选中线
```vue
右侧内容区
```
**更多演示请下载 demo 查看**
## 锚点定位
`anchor` 为 true 时,选中项变化会驱动内容区滚动到对应 `id` 的节点(scroll-into-view),需在内容区放置带相同 `id` 的节点。
```vue
模块一
模块二
```
## 外部样式
`bar-class` / `bar-style` 定制左侧侧边栏,`item-class` / `item-style` 定制选项,`content-class` / `content-style` 定制内容区。
## 属性
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
| --- | --- | --- | --- | --- |
| v-model | 当前选中的选项索引 | Number | `0` | - |
| data | 侧边栏选项数据数组 | Array<`SnDataItem`> | `[]` | - |
| width | 侧边栏宽度,支持 `$` 前缀按间距乘数缩放 | String | `'100px'` | - |
| itemWidth | 选项宽度,支持 `$` 前缀按间距乘数缩放 | String | `'100px'` | - |
| itemPadding | 选项内边距(支持 1~4 值简写),支持 `$` 前缀按间距乘数缩放 | String | `'15px 0'` | - |
| itemTextColor | 选项文字颜色 | String | `$text` | - |
| itemTextSize | 选项文字大小 | String \| Number | `$16` | - |
| activeItemTextColor | 选中选项文字颜色 | String | `$primary` | - |
| itemBgColor | 选项背景颜色 | String | `var(--sn-transparent)` | - |
| itemBorderRadius | 选项圆角大小 | String \| Number | `'0'` | - |
| activeItemBgColor | 选中选项背景颜色 | String | `$front` | - |
| disabled | 是否禁用所有选项 | Boolean | `false` | `true` \| `false` |
| anchor | 是否使用锚点定位,选中时内容区滚动到对应 id | Boolean | `false` | `true` \| `false` |
| showLine | 是否显示选中线 | Boolean | `true` | `true` \| `false` |
| lineColor | 选中线颜色 | String | `$primary` | - |
| customStyle | 自定义容器样式 | SnStyleValue | `''` | - |
| itemStyle | 自定义选项样式 | SnStyleValue | `''` | - |
| itemClass | 选项外部样式类 | String | `''` | - |
| barStyle | 自定义侧边栏(左侧列表)样式 | SnStyleValue | `''` | - |
| barClass | 侧边栏外部样式类 | String | `''` | - |
| contentStyle | 自定义内容区样式 | SnStyleValue | `''` | - |
| contentClass | 内容区外部样式类 | String | `''` | - |
> 类型字段:SnDataItem(见 https://sinleui.pages.dev/api/types/component#sndataitem)
## 事件
| 名称 | 类型 | 说明 |
| --- | --- | --- |
| change | (value: number) => Void | 选项改变时触发 |
## 插槽
| 名称 | 说明 |
| --- | --- |
| default | 放置侧边栏右侧的内容区域 |
# Tabs 标签页
> [查看 sn-tabs 的 2.0 版本差异](/differences/components/sn-tabs)
## 基础用法
标签页组件,用于切换不同标签内容,一般用于顶部导航。
- 支持滚动模式与滑动式 / 推压式两种指示线动画
- 支持子项单独禁用与徽标
- 支持左右插槽
```vue
```
**更多演示请下载 demo 查看**
## 滚动与动画
`scrollable` 开启后标签可横向滚动,子项自动计算宽度并将选中项居中;`mode` 选择指示线动画方式:`swipe` 滑动式、`push` 推压式。
```vue
```
## 徽标
data 项通过 `badgeConfig` 配置徽标(value/max/size/offset/mode/text/showZero/textColor/bgColor),支持 number/text/dot 三种模式。
```vue
```
## 数据项 SnTabParams
| 字段 | 说明 | 类型 |
| --- | --- | --- |
| text | 标签文本(必需) | String |
| id | 标签唯一标识(必需,用于指示线定位与滚动) | String |
| disabled | 是否禁用该标签 | Boolean |
| badgeConfig | 徽标配置 | `SnBadgeParams` |
> 类型字段:SnBadgeParams(见 https://sinleui.pages.dev/api/types/component#snbadgeparams)
类型中还声明了 icon、checked、showBadge 字段,当前渲染未使用。
## 属性
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
| --- | --- | --- | --- | --- |
| v-model | 当前激活的标签页索引 | Number | `0` | - |
| scrollable | 标签是否可滚动 | Boolean | `false` | `true` \| `false` |
| data | 标签页数据数组 | Array<`SnTabParams`> | `[]` | - |
| mode | 指示线动画模式 | String | `'swipe'` | `swipe` \| `push` |
| width | 标签宽度,支持 `$` 前缀按间距乘数缩放 | String | `'100%'` | - |
| height | 标签高度,支持 `$` 前缀按间距乘数缩放 | String | `'40px'` | - |
| bgColor | 标签背景颜色 | String | `$front` | - |
| textColor | 标签文本颜色 | String | `$title` | - |
| textSize | 标签文本大小 | String \| Number | `$14` | - |
| borderRadius | 标签圆角 | String \| Number | `$12` | - |
| disabledTextColor | 禁用标签文本颜色 | String | `$disabledText` | - |
| activeTextColor | 选中标签文本颜色 | String | `$primary` | - |
| itemPadding | 标签内边距(可滚动时作为左右内边距),支持 `$` 前缀按间距乘数缩放 | String | `'12px'` | - |
| lineColor | 指示线颜色 | String | `$primary` | - |
| lineWidth | 指示线宽度,取标签宽度的 60%,支持 `$` 前缀按间距乘数缩放 | String | - | - |
| lineHeight | 指示线高度,支持 `$` 前缀按间距乘数缩放 | String | `'2px'` | - |
| aniTime | 标签及指示线动画时长(单位 ms,`$` 简写乘动画乘数) | String \| Number | `$normal` | - |
| itemStyle | 选中标签样式 | SnStyleValue | `''` | - |
| itemClass | 选中标签外部样式类 | String | `''` | - |
| textStyle | 标签文本样式 | SnStyleValue | `''` | - |
| textClass | 标签文本外部样式类 | String | `''` | - |
| activeItemStyle | 非选中标签样式 | SnStyleValue | `''` | - |
| activeItemClass | 非选中标签外部样式类 | String | `''` | - |
| customStyle | 自定义样式 | SnStyleValue | `''` | - |
> 类型字段:SnTabParams(见 https://sinleui.pages.dev/api/types/component#sntabparams)
:::
## 事件
| 名称 | 类型 | 说明 |
| --- | --- | --- |
| change | (index: number) => Void | 标签页切换时触发,index 为标签页索引 |
## 插槽
| 名称 | 说明 |
| --- | --- |
| left | 在标签页左侧放置内容 |
| right | 在标签页右侧放置内容 |
# Subsection 分段器
> [查看 sn-subsection 的 2.0 版本差异](/differences/components/sn-subsection)
## 基础用法
分段器,用于用户从几个选项中选择某一个,常作为视图切换控件。
- 分段文本由数据数组驱动,选中索引支持双向绑定
- 滑块随选中项平移并带动画
- 滑块尺寸按容器实际尺寸动态计算,容器尺寸变化时自动重新测量
```vue
```
**更多演示请下载 demo 查看**
## 自定义样式
分段项、滑块、文本均支持外部样式类与自定义样式,可深度改造外观,例如把滑块改为下划线样式:
```vue
```
## 属性
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
| --- | --- | --- | --- | --- |
| v-model | 绑定值,当前选中的分段索引 | Number | `0` | - |
| data | 分段数据,数组中的每个元素代表一个分段的文本 | `Array` | `[]` | - |
| disabled | 是否禁用分段选择器 | Boolean | `false` | `true` \| `false` |
| padding | 分段器内边距 | String \| Number | `'3px'` | - |
| blockPadding | 每个分段项的内边距 | String \| Number | `'10px'` | - |
| borderRadius | 分段器圆角 | String \| Number | `$12` | - |
| textSize | 分段文本大小 | String \| Number | `$14` | - |
| bgColor | 分段器背景颜色 | String | `$info` | - |
| disabledBgColor | 禁用时分段器背景颜色,亮色主题为 `$disabled`、暗黑主题为 `$disabledDark` | String | - | - |
| blockBgColor | 滑块背景颜色 | String | `$front` | - |
| disabledBlockBgColor | 禁用时滑块背景颜色,亮色主题为 `$disabledDark`、暗黑主题为 `$disabled` | String | - | - |
| textColor | 未选中分段文本颜色 | String | `$text` | - |
| activeTextColor | 选中分段文本颜色 | String | `$primaryDark` | - |
| disabledTextColor | 禁用时文本颜色 | String | `$disabledText` | - |
| customStyle | 自定义分段器根节点样式 | SnStyleValue | `''` | - |
| customClass | 分段器根节点的外部样式类 | String | `''` | - |
| itemClass | 分段项的外部样式类 | String | `''` | - |
| itemStyle | 自定义分段项样式 | SnStyleValue | `''` | - |
| blockClass | 滑块的外部样式类 | String | `''` | - |
| blockStyle | 自定义滑块样式 | SnStyleValue | `''` | - |
| textClass | 分段文本的外部样式类 | String | `''` | - |
| textStyle | 自定义分段文本样式 | SnStyleValue | `''` | - |
## 事件
| 名称 | 类型 | 说明 |
| --- | --- | --- |
| change | (value: number) => Void | 选中分段变化时触发,携带新的分段索引 |
# Steps 步骤条
## 基础用法
步骤条,用于展示流程进度,由 `sn-steps`(容器)与 `sn-step`(步骤项)组合使用。
- 支持横向 / 竖向与两种步骤形态
- 支持点击切换与当前步骤状态
- 容器属性(尺寸、颜色、外部样式等)统一下发给各步骤项
```vue
```
**更多演示请下载 demo 查看**
## 点状步骤条
`type` 设为 `dot` 使用小圆点的简略模式。
```vue
```
## 竖向步骤条
`vertical` 属性改为纵向排列,适合物流详情等场景。
```vue
```
## 自定义样式
`active-color` 定制激活色,`circle-size` / `text-size` / `content-size` 定制尺寸,`title-style` / `title-class` 等外部样式/类定制各部分。
```vue
```
## sn-steps 属性
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
| --- | --- | --- | --- | --- |
| v-model | 当前步骤索引 | Number | `0` | - |
| vertical | 是否竖向排列 | Boolean | `false` | `true` \| `false` |
| type | 展示形态 | String | `'default'` | `default` \| `dot` |
| status | 当前步骤(激活步骤)的状态 | String | `'process'` | `wait` \| `finish` \| `process` \| `error` |
| selectable | 是否允许点击步骤切换 | Boolean | `true` | `true` \| `false` |
| activeColor | 激活色 | String | `$primary` | - |
| circleSize | 圆形节点大小 | String \| Number | `'$22'` | - |
| textSize | 标题文字大小 | String \| Number | `$14` | - |
| contentSize | 内容文字大小 | String \| Number | `$12` | - |
| stepStyle | 自定义步骤项样式 | SnStyleValue | `''` | - |
| stepClass | 步骤项外部样式类 | String | `''` | - |
| titleStyle | 自定义标题样式 | SnStyleValue | `''` | - |
| titleClass | 标题外部样式类 | String | `''` | - |
| contentStyle | 自定义内容样式 | SnStyleValue | `''` | - |
| contentClass | 内容外部样式类 | String | `''` | - |
| lineStyle | 自定义连接线样式 | SnStyleValue | `''` | - |
| lineClass | 连接线外部样式类 | String | `''` | - |
| customStyle | 自定义容器样式 | SnStyleValue | `''` | - |
| customClass | 容器外部样式类 | String | `''` | - |
## sn-steps 事件
| 名称 | 类型 | 说明 |
| --- | --- | --- |
| change | (value: number) => Void | 步骤改变时触发 |
## sn-steps 插槽
| 名称 | 说明 |
| --- | --- |
| default | 放置 sn-step 步骤项 |
## sn-step 属性
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
| --- | --- | --- | --- | --- |
| title | 步骤标题 | String | `''` | - |
| content | 步骤内容 | String | `''` | - |
| icon | 自定义图标名,finish 显示 check-line、error 显示 close-line | String | - | - |
| status | 单独覆盖该步骤的状态,由索引与容器 status 自动推导 | String | - | `wait` \| `finish` \| `process` \| `error` |
| stepClass | 步骤项外部样式类(与容器的 stepClass 合并) | String | `''` | - |
| titleClass | 标题外部样式类(与容器的 titleClass 合并) | String | `''` | - |
| contentClass | 内容外部样式类(与容器的 contentClass 合并) | String | `''` | - |
| lineClass | 连接线外部样式类(与容器的 lineClass 合并) | String | `''` | - |
## sn-step 插槽
| 名称 | 说明 |
| --- | --- |
| icon | 替换圆形节点内容,作用域插槽可访问当前状态 status |
| title | 替换标题内容 |
| content | 替换内容区文本 |
| extra | 在内容区底部追加额外内容 |
# Menu 菜单
> [查看 sn-menu 的 2.0 版本差异](/differences/components/sn-menu)
## 基础用法
锚点菜单,在触发元素(按钮、图标等)旁弹出一组操作选项,常用于「更多操作」场景。
- 菜单项由数组驱动,支持文字、图标、右侧内容、文字颜色与禁用
- 自动定位到锚点下方,下方空间不足时改为上方弹出,三角箭头随之翻转
- 点击菜单项派发事件并自动关闭,遮罩可关闭或自定义
::: danger 必须放在 sn-page 下
本组件为弹出层,需直接放在 `sn-page` 根节点下使用,否则主题颜色与动画时长等 CSS 变量无法作用到组件内部。
:::
::: info 平台差异
HarmonyOS 端菜单透明度由入退场动画控制,遮罩独立淡入淡出。
:::
```vue
```
**更多演示请下载 demo 查看**
## 对齐方式与箭头
```vue
```
## 属性
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
| --- | --- | --- | --- | --- |
| v-model:show | 菜单显示状态绑定值 | Boolean | `false` | `true` \| `false` |
| target | 锚点元素选择器(如 `#menu-btn`),菜单将定位到该元素旁 | String | `''` | - |
| align | 菜单相对锚点的对齐方式 | String | `left` | `left` \| `center` \| `right` |
| items | 菜单项数组,每项支持 `text`、`icon`、`value`、`color`、`disabled` 字段 | Array<`SnDataItem`> | `[]` | - |
| width | 菜单宽度(px),支持 `$` 前缀按间距乘数缩放 | String \| Number | `160px` | - |
| zIndex | 弹出层层级 | Number | `999` | - |
| showArrow | 是否显示指向锚点的三角箭头 | Boolean | `true` | `true` \| `false` |
| overlay | 是否显示遮罩 | Boolean | `true` | `true` \| `false` |
| overlayOpacity | 遮罩透明度,`overlay` 为 `false` 时不显示遮罩 | Number | `0.3` | - |
| overlayStyle | 自定义遮罩样式 | SnStyleValue | `''` | - |
| overlayClass | 遮罩外部类 | String | `''` | - |
| menuStyle | 自定义菜单容器样式 | SnStyleValue | `''` | - |
| menuClass | 菜单容器外部类 | String | `''` | - |
| aniTime | 显示 / 关闭动画时长(ms),支持 `$` 简写 | String \| Number | `200` | - |
| cellStyle | 自定义菜单项样式(透传内部 sn-cell) | SnStyleValue | `''` | - |
| cellClass | 菜单项外部类(透传内部 sn-cell) | String | `''` | - |
| cellBorder | 是否显示菜单项之间的分隔线 | Boolean | `true` | `true` \| `false` |
| closeOnClickOverlay | 点击遮罩时是否关闭菜单 | Boolean | `true` | `true` \| `false` |
> 类型字段:SnDataItem(见 https://sinleui.pages.dev/api/types/component#sndataitem)
## 事件
| 名称 | 类型 | 说明 |
| --- | --- | --- |
| update:show | (value: boolean) => Void | 菜单显示状态变化时触发,配合 `v-model:show` 使用 |
| select | (index: number, item: `SnDataItem`) => Void | 点击菜单项时触发,参数为索引与所选菜单项,随后自动关闭 |
| clickoverlay | () => Void | 点击遮罩时触发 |
| beforeenter | () => Void | 入场动画开始前触发 |
| enter | () => Void | 入场动画开始时触发 |
| afterenter | () => Void | 入场动画结束后触发 |
| beforeleave | () => Void | 离场动画开始前触发 |
| leave | () => Void | 离场动画开始时触发 |
| afterleave | () => Void | 离场动画结束后触发 |
# Search 搜索框
> [查看 sn-search 的 2.0 版本差异](/differences/components/sn-search)
## 基础用法
基于 `sn-input` 二次封装的搜索框,键盘确认按钮固定为 search,开箱即用。
- 聚焦时右侧取消按钮平滑展开,点击取消会清空输入内容并派发事件
- 输入值变化时派发事件,可显示一键清空按钮
- 前后图标可更换,也可用插槽自定义
```vue
```
**更多演示请下载 demo 查看**
## 自定义取消按钮
通过 `showCancel` 控制是否显示取消按钮(默认隐藏,聚焦时展开),`fixCancel` 让其常驻显示,文案与样式可用 `cancelText` / `cancelTextSize` / `cancelTextColor` 或 `cancelClass` / `cancelStyle` 定制。
```vue
```
## 自定义图标与插槽
```vue
```
## 属性
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
| --- | --- | --- | --- | --- |
| v-model | 绑定值 | String | `''` | - |
| placeholder | 占位文本 | String | `请输入搜索内容` | - |
| type | 输入框键盘类型 | String | `text` | `text` \| `number` \| `digit` \| `tel` \| `idcard` \| `nickname` |
| padding | 输入框内边距 | String | `8px 12px` | - |
| textColor | 输入文本颜色 | String | `''` | - |
| textSize | 输入文本大小 | String \| Number | `''` | - |
| loading | 是否显示加载状态 | Boolean | `false` | `true` \| `false` |
| disabled | 是否禁用输入框 | Boolean | `false` | `true` \| `false` |
| readonly | 是否只读 | Boolean | `false` | `true` \| `false` |
| clearable | 是否显示清除按钮 | Boolean | `false` | `true` \| `false` |
| focus | 是否获得焦点 | Boolean | `false` | `true` \| `false` |
| showBorder | 是否显示边框 | Boolean | `true` | `true` \| `false` |
| showActiveBorder | 聚焦时是否切换为激活边框颜色 | Boolean | `true` | `true` \| `false` |
| showCancel | 是否显示取消按钮(聚焦时平滑展开) | Boolean | `false` | `true` \| `false` |
| fixCancel | 取消按钮是否常驻显示(不随聚焦收起) | Boolean | `false` | `true` \| `false` |
| cancelText | 取消按钮文本 | String | `取消` | - |
| cancelTextSize | 取消按钮文本大小 | String \| Number | `$14` | - |
| cancelTextColor | 取消按钮文本颜色 | String | `$primaryDark` | - |
| bgColor | 输入框背景颜色 | String | `$info` | - |
| activeBgColor | 聚焦时的背景颜色 | String | `$info` | - |
| activeBorderColor | 聚焦时的边框颜色 | String | `'$line'` | - |
| borderRadius | 输入框圆角大小 | String \| Number | `''` | - |
| borderColor | 输入框边框颜色 | String | `'$line'` | - |
| borderWidth | 输入框边框宽度 | String \| Number | `1px` | - |
| cursorColor | 光标颜色 | String | `''` | - |
| prefixIcon | 前置图标名称,存在 prefix 插槽时不显示 | String | `search-2-line` | - |
| suffixIcon | 后置图标名称,存在 suffix 插槽时不显示 | String | `''` | - |
| customStyle | 自定义根节点样式 | SnStyleValue | `''` | - |
| inputStyle | 自定义内部输入框样式 | SnStyleValue | `''` | - |
| inputClass | 内部输入框的外部类 | String | `''` | - |
| cancelStyle | 自定义取消按钮样式 | SnStyleValue | `''` | - |
| cancelClass | 取消按钮的外部类 | String | `''` | - |
## 事件
| 名称 | 类型 | 说明 |
| --- | --- | --- |
| change | (value: string) => Void | 绑定值变化时触发,参数为当前输入内容 |
| focus | (event: UniInputFocusEvent) => Void | 输入框聚焦时触发 |
| blur | (event: UniInputBlurEvent) => Void | 输入框失去焦点时触发 |
| confirm | (event: UniInputConfirmEvent) => Void | 点击键盘搜索按钮时触发 |
| cancel | () => Void | 点击取消按钮时触发,同时会清空输入内容 |
| suffix-click | () => Void | 点击后置图标时触发 |
## 插槽
| 名称 | 说明 |
| --- | --- |
| prefix | 自定义前置内容,使用后前置图标不显示 |
| suffix | 自定义后置内容,使用后后置图标不显示 |
# Collapse 折叠面板
> [查看 sn-collapse 的 2.0 版本差异](/differences/components/sn-collapse)
## 基础用法
折叠面板,用于收纳内容区域。
- 由折叠组与折叠项组合使用,点击子项头部展开 / 收起
- 默认多个子项独立展开,也可改为同一时间仅展开一个
- 子项支持标题、右侧说明文本与左侧图标,内容区高度自适应并带展开动画
```vue
```
**更多演示请下载 demo 查看**
## 手风琴模式
开启 `accordion` 后,同一时间只展开一个子项,展开新子项时其余子项自动收起。
```vue
```
## 自定义头部
通过 `header` 插槽可整体替换子项头部区域(替换标题、说明文本与展开箭头)。
```vue
```
## 属性
**sn-collapse-group**
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
| :--- | :--- | :--- | :--- | :--- |
| accordion | 是否开启手风琴模式(同一时间仅展开一个子项,展开新项时其余自动收起) | Boolean | `false` | `true` \| `false` |
| aniTime | 展开/收起动画时长,支持 `$` 简写 | String \| Number | `$snui.aniTimeNormal` | - |
| bgColor | 面板背景颜色 | String | `$front` | - |
| titleSize | 子项标题字体大小,支持 `$` 简写 | String \| Number | `15px × fontsizeFactor` | - |
| titleColor | 子项标题颜色 | String | `$title` | - |
| activeTitleColor | 展开状态子项标题颜色 | String | `$primary` | - |
| noteSize | 子项说明文本字体大小,支持 `$` 简写 | String \| Number | `13px × fontsizeFactor` | - |
| noteColor | 子项说明文本颜色(同时是展开箭头颜色) | String | `$lineText` | - |
| borderRadius | 面板圆角大小,支持 `$` 简写 | String \| Number | `8px × radiusFactor` | - |
| showBorder | 是否显示子项之间的分割线(末尾子项不显示) | Boolean | `true` | `true` \| `false` |
| titleStyle | 子项标题样式,作用于所有子项 | SnStyleValue | `''` | - |
| noteStyle | 子项说明文本样式,作用于所有子项 | SnStyleValue | `''` | - |
| holderStyle | 子项内容区容器样式,作用于所有子项 | SnStyleValue | `''` | - |
| titleClass | 子项标题外部样式类,透传至所有子项 | String | `''` | - |
| noteClass | 子项说明文本外部样式类,透传至所有子项 | String | `''` | - |
| holderClass | 子项内容区外部样式类,透传至所有子项 | String | `''` | - |
| customStyle | 自定义根节点样式 | SnStyleValue | `''` | - |
**sn-collapse-item**
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
| :--- | :--- | :--- | :--- | :--- |
| title | 子项标题 | String | `''` | - |
| note | 子项说明文本,显示在标题右侧 | String | `''` | - |
| icon | 子项标题左侧图标名称 | String | `''` | - |
| open | 初始状态是否展开 | Boolean | `false` | `true` \| `false` |
| disabled | 是否禁用(禁用后不可点击展开,标题与箭头显示禁用色) | Boolean | `false` | `true` \| `false` |
| titleClass | 当前子项标题外部样式类,与 group 级 `titleClass` 合并 | String | `''` | - |
| noteClass | 当前子项说明文本外部样式类,与 group 级 `noteClass` 合并 | String | `''` | - |
| holderClass | 当前子项内容区外部样式类(external-class:`holder-class`),与 group 级 `holderClass` 合并 | String | `''` | - |
| customStyle | 自定义子项根节点样式 | SnStyleValue | `''` | - |
子项未单独传入的标题/说明颜色与字号,继承 group 上设置的对应值。
## 方法
以下方法可通过模板 ref 调用,其中 `register`、`setOrder` 主要供组件内部协调使用,一般无需手动调用。
**sn-collapse-group**
| 名称 | 参数 | 返回值 | 描述 |
| :--- | :--- | :--- | :--- |
| closeAll | - | - | 收起所有子项(仅手风琴模式下生效) |
| register | node: ComponentPublicInstance | Void | 注册子项(供 sn-collapse-item 挂载时内部调用) |
**sn-collapse-item**
| 名称 | 参数 | 返回值 | 描述 |
| :--- | :--- | :--- | :--- |
| close | - | - | 收起当前子项 |
| setOrder | index: Number, border: Boolean | Void | 设置子项序号与是否显示底部分割线(供 sn-collapse-group 内部调用) |
## 插槽
**sn-collapse-group**
| 名称 | 说明 |
| :--- | :--- |
| default | 在这里放置子组件 `sn-collapse-item` |
**sn-collapse-item**
| 名称 | 说明 |
| :--- | :--- |
| default | 子项内部放置收纳的内容 |
| header | 自定义子项头部区域(替换标题、说明文本与展开箭头) |
# Sorter 排序
## 基础用法
排序组件,常用于列表排序切换。
- 点击在无序、升序、降序之间循环切换,也可仅在升序与降序之间切换
- 支持控制首次点击进入的方向
- 箭头通过颜色区分激活方向,激活与未激活颜色均可自定义
```vue
```
**更多演示请下载 demo 查看**
## 自定义内容
默认插槽可替换标签内容,`arrow` 作用域插槽可完全自定义箭头区域(作用域参数 `{ value: number }`)。
```vue
筛选结果
```
## 属性
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
| --- | --- | --- | --- | --- |
| v-model | 排序状态:`0` 无序、`1` 升序、`-1` 降序 | Number | `0` | `0` \| `1` \| `-1` |
| label | 排序标签文本 | String | `''` | - |
| allowReset | 是否允许重置为无序(开启后按无序、升序、降序三态循环) | Boolean | `false` | `true` \| `false` |
| descFirst | 首次点击是否进入降序 | Boolean | `false` | `true` \| `false` |
| activeColor | 激活方向箭头的颜色 | String | `` `$primary` `` | - |
| inactiveColor | 非激活方向箭头的颜色 | String | `` `$textLight` `` | - |
| arrowSize | 箭头尺寸 | String \| Number | `$20` | - |
| disabled | 是否禁用 | Boolean | `false` | `true` \| `false` |
| customStyle | 自定义根节点样式 | SnStyleValue | `''` | - |
| customClass | 自定义根节点样式类 | String | `''` | - |
| labelStyle | 自定义标签样式 | SnStyleValue | `''` | - |
| labelClass | 自定义标签样式类 | String | `''` | - |
| arrowStyle | 自定义箭头区域样式 | SnStyleValue | `''` | - |
| arrowClass | 自定义箭头区域样式类 | String | `''` | - |
## 事件
| 名称 | 类型 | 说明 |
| --- | --- | --- |
| change | (value: number) => Void | 排序状态变化时触发,携带新状态值(`0` 无序、`1` 升序、`-1` 降序) |
## 插槽
| 名称 | 说明 |
| --- | --- |
| default | 替换标签文本内容 |
| arrow | 替换箭头区域,作用域参数 `{ value: number }` 为当前排序状态 |
# Timer 计时器
> [查看 sn-timer 的 2.0 版本差异](/differences/components/sn-timer)
## 基础用法
正向计时器,从 0 开始累计计时。
- 可自动开始,也可手动控制开始、暂停与重置
- 基于动画帧驱动,走秒平滑,可开启毫秒级刷新
- 计时变化时派发事件返回已计时数据;重置会停止当前计时并归零
```vue
```
**更多演示请下载 demo 查看**
## 时间格式
`format` 中支持以下占位符,某个单位占位符缺省时,该单位会自动进位到上一级(如格式中没有 `DD`,天数会折算进小时显示):
| 占位符 | 说明 |
| :--- | :--- |
| `DD` | 天数,两位数补齐 |
| `HH` | 小时,两位数 |
| `mm` | 分钟,两位数 |
| `ss` | 秒,两位数 |
| `SSS` | 毫秒,三位数 |
| `SS` | 十毫秒,两位数 |
| `S` | 百毫秒,一位数 |
使用毫秒占位符(`SSS` / `SS` / `S`)时请开启 `millisecond`,否则毫秒部分不会随帧刷新。
## 自定义布局
使用默认插槽后,组件不再渲染内部文本,可配合 `change` 事件自行布局(参数为包含 `d`、`h`、`m`、`s`、`ms` 字段的 `SnTime` 对象),例如分段数字样式:
```vue
{{ h }}:{{ m }}:{{ s }}
```
## 属性
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
| --- | --- | --- | --- | --- |
| format | 时间格式,占位符见上方"时间格式" | String | `HH:mm:ss` | - |
| autoplay | 初始化后自动开始计时 | Boolean | `true` | `true` \| `false` |
| millisecond | 开启毫秒级刷新(显示毫秒占位符时务必开启) | Boolean | `false` | `true` \| `false` |
| textSize | 文本字体大小,支持 `$` 动态尺寸 | String \| Number | `$14` | - |
| textColor | 文本颜色,支持 `$` 主题色简写 | String | `$text` | - |
| selectable | 文本是否可选中复制 | Boolean | `false` | `true` \| `false` |
| bold | 文本是否加粗 | Boolean | `false` | `true` \| `false` |
| textClass | 文本节点外部样式类 | String | `''` | - |
| customStyle | 根节点自定义样式 | SnStyleValue | `''` | - |
## 事件
| 名称 | 类型 | 说明 |
| --- | --- | --- |
| change | (value: `SnTime`) => Void | 计时时间变化时触发,参数为包含 `d`、`h`、`m`、`s`、`ms` 字段的 `SnTime` 对象 |
> 类型字段:SnTime(见 https://sinleui.pages.dev/api/types/component#sntime)
## 方法
| 名称 | 参数 | 返回值 | 描述 |
| --- | --- | --- | --- |
| start | - | - | 开始计时(或从暂停处继续) |
| pause | - | - | 暂停计时 |
| reset | - | - | 停止当前计时并归零;`autoplay` 为 `true` 时自动重新开始,为 `false` 时等待调用 `start()` |
## 插槽
| 名称 | 说明 |
| --- | --- |
| default | 自定义计时内容,接管内部文本渲染,可配合 `change` 事件实现分段数字等布局 |
# Countdown 倒计时
> [查看 sn-countdown 的 2.0 版本差异](/differences/components/sn-countdown)
## 基础用法
倒计时组件,用于展示一段剩余时间。
- 基于动画帧驱动,走秒平滑不跳秒,可开启毫秒级刷新
- 提供开始、暂停、重置与停止控制
- 剩余时间变化时派发事件返回时间数据
```vue
```
**更多演示请下载 demo 查看**
## 时间格式
`format` 中支持以下占位符,某个单位占位符缺省时,该单位会自动进位到上一级(如格式中没有 `DD`,天数会折算进小时显示):
| 占位符 | 说明 |
| :--- | :--- |
| `DD` | 天数,两位数补齐 |
| `HH` | 小时,两位数 |
| `mm` | 分钟,两位数 |
| `ss` | 秒,两位数 |
| `SSS` | 毫秒,三位数 |
| `SS` | 十毫秒,两位数 |
| `S` | 百毫秒,一位数 |
使用毫秒占位符(`SSS` / `SS` / `S`)时请开启 `millisecond`,否则毫秒部分不会随帧刷新。
## 自定义布局
使用默认插槽后,组件不再渲染内部文本,可配合 `change` 事件自行布局(参数为包含 `d`、`h`、`m`、`s`、`ms` 字段的 `SnTime` 对象):
```vue
{{ h }}时{{ m }}分{{ s }}秒
```
## 属性
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
| --- | --- | --- | --- | --- |
| time | 倒计时总时长(单位 ms),变化时自动重置 | Number | `0` | - |
| format | 时间格式,占位符见上方"时间格式" | String | `HH:mm:ss` | - |
| autoplay | 初始化及重置后自动开始计时 | Boolean | `true` | `true` \| `false` |
| millisecond | 开启毫秒级刷新(显示毫秒占位符时务必开启) | Boolean | `false` | `true` \| `false` |
| textSize | 文本字体大小,支持 `$` 动态尺寸 | String \| Number | `$14` | - |
| textColor | 文本颜色,支持 `$` 主题色简写 | String | `$text` | - |
| selectable | 文本是否可选中复制 | Boolean | `false` | `true` \| `false` |
| bold | 文本是否加粗 | Boolean | `false` | `true` \| `false` |
| textClass | 文本节点外部样式类 | String | `''` | - |
| customStyle | 根节点自定义样式 | SnStyleValue | `''` | - |
## 事件
| 名称 | 类型 | 说明 |
| --- | --- | --- |
| change | (value: `SnTime`) => Void | 剩余时间变化时触发,参数为包含 `d`、`h`、`m`、`s`、`ms` 字段的 `SnTime` 对象 |
| finish | () => Void | 倒计时归零时触发 |
> 类型字段:SnTime(见 https://sinleui.pages.dev/api/types/component#sntime)
## 方法
| 名称 | 参数 | 返回值 | 描述 |
| --- | --- | --- | --- |
| start | - | - | 开始计时(或从暂停处继续) |
| pause | - | - | 暂停计时 |
| reset | - | - | 重置为 `time` 设定的剩余时长,`autoplay` 为 `true` 时自动重新开始 |
| stop | - | - | 停止计时并归零,触发 `finish` 事件 |
## 插槽
| 名称 | 说明 |
| --- | --- |
| default | 自定义倒计时内容,接管内部文本渲染,可配合 `change` 事件实现个性化布局 |
# Countto 数字滚动
> [查看 sn-countto 的 2.0 版本差异](/differences/components/sn-countto)
## 基础用法
数字滚动组件,常用于数据大屏、经营数据展示等场景。
- 数字从起始值滚动到目标值,动画时长可配置
- 支持结束前减速的缓动效果
- 可控制小数位数并按位插入千分位式分隔符
```vue
```
**更多演示请下载 demo 查看**
## 分割数字
`separate` 设为非 0 值后,整数部分每隔几位会用 `,` 分隔(小数部分不受影响),常用于金融场景:
```vue
```
## 自定义样式
通过 `text-size` / `text-color` / `bold` 与 `custom-style` 定制数字文本表现:
```vue
```
## 属性
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
| --- | --- | --- | --- | --- |
| startVal | 开始值,变化时自动重新播放 | Number | `0` | - |
| endVal | 结束值,变化时自动重新播放 | Number | `0` | - |
| duration | 动画时长(单位 ms) | Number | `2000` | - |
| decimals | 小数位数(大于 0 时滚动过程数字带随机跳动效果) | Number | `0` | - |
| separate | 分割位数(整数部分每隔几位插入一次 `,`,`0` 为不分割) | Number | `0` | - |
| autoplay | 初始化后自动播放 | Boolean | `true` | `true` \| `false` |
| easing | 以 easeOutSine 缓动动画代替默认的 linear 动画,使动画在结束前减速 | Boolean | `false` | `true` \| `false` |
| textSize | 数字文本字体大小,支持 `$` 动态尺寸 | String \| Number | `$14` | - |
| textColor | 数字文本颜色,支持 `$` 主题色简写 | String | `$text` | - |
| selectable | 文本是否可选中复制 | Boolean | `false` | `true` \| `false` |
| bold | 文本是否加粗 | Boolean | `false` | `true` \| `false` |
| textClass | 文本节点外部样式类 | String | `''` | - |
| customStyle | 根节点自定义样式 | SnStyleValue | `''` | - |
## 事件
| 名称 | 类型 | 说明 |
| --- | --- | --- |
| finish | () => Void | 动画播放完成时触发 |
## 方法
| 名称 | 参数 | 返回值 | 描述 |
| --- | --- | --- | --- |
| play | - | - | 播放动画(从当前进度继续) |
| pause | - | - | 暂停动画 |
| stop | - | - | 停止动画并直接显示 `endVal`,触发 `finish` 事件 |
| reset | - | - | 重置到 `startVal`,`autoplay` 为 `true` 时自动重新播放 |
## 插槽
| 名称 | 说明 |
| --- | --- |
| default | 自定义数字内容,接管内部文本渲染 |
# Fullscreen 原位展开全屏
## 基础用法
让一块内容“原位”拉伸占满整个视口的容器(如卡片、模拟播放器),收起时动画回到原位置。
- 展开期间原位置由等高占位节点撑住,页面布局不塌陷
- 默认点击内容即可展开
- 全屏时点击是否关闭可配置,也提供打开、关闭与切换方法
```vue
点我全屏
```
**更多演示请下载 demo 查看**
## 进阶用法
### 关闭按钮模式
设置 `trigger-click="false"` 关闭点击自动展开,改由按钮或内容内关闭图标控制,适合播放器等场景。
```vue
```
## 属性
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
| --- | --- | --- | --- | --- |
| triggerClick | 非全屏状态下点击内容层时自动展开全屏 | Boolean | `true` | `true` \| `false` |
| clickClose | 全屏状态下点击内容层时收起回到原位 | Boolean | `false` | `true` \| `false` |
| aniTime | 展开与收起的动画时长,`0` 为瞬时切换,支持 `$short`/`$normal`/`$long`(也接受不带 `$` 的同名写法),数字单位为 ms | String \| Number | `$long` | - |
| zIndex | 全屏时内容层的层级 | Number | `999` | - |
| disabled | 是否禁用(禁用后点击与方法均不生效) | Boolean | `false` | `true` \| `false` |
| layerClass | 内容层外部样式类 | String | `''` | - |
| layerStyle | 自定义内容层样式(通常用它设置内容的初始宽高) | SnStyleValue | `''` | - |
| customClass | 根节点外部样式类 | String | `''` | - |
| customStyle | 自定义根节点样式 | SnStyleValue | `''` | - |
## 事件
| 名称 | 类型 | 说明 |
| --- | --- | --- |
| open | () => Void | 开始展开全屏时触发 |
| close | () => Void | 开始收起(关闭全屏)时触发 |
## 方法
| 名称 | 参数 | 返回值 | 描述 |
| --- | --- | --- | --- |
| open | - | - | 展开全屏;正在动画或已全屏、或内容层尺寸无效时不执行 |
| close | - | - | 收起并动画回到原位置;非全屏或正在动画时不执行 |
| toggle | - | - | 在全屏与原位之间切换 |
## 插槽
| 名称 | 说明 |
| --- | --- |
| default | 内容层内容,全屏时随容器拉伸重新布局 |
# Clipper 图片裁剪
## 基础用法
内置完整裁剪交互的图片裁剪器,可卡片内嵌,也可作为整页裁剪器使用。
- 支持手势拖动 / 双指缩放图片与 8 向手柄调整裁剪框
- 底部提供比例预设、旋转 / 镜像与还原工具
- 导出结果为 PNG(base64),并返回尺寸、比例与旋转信息
```vue
```
**更多演示请下载 demo 查看**
## 进阶用法
### 作为整页裁剪器
设置 `fill-viewport` 后裁剪区自动占满父容器剩余空间,适合放在全屏页面中。
```vue
```
### 自定义比例预设
通过 `ratio-list` 自定义比例按钮,`ratio` 为 `0` 表示自由比例;`initial-ratio-id` 指定初始选中项。
> 说明:比例预设为横向排列,超出宽度时可横向滑动;Web / PC 端除滚动条外还支持按住鼠标左右拖动该区域滚动。
```vue
```
### 通过 ref 控制
```vue
```
## 实现原理
导出会等待图片、画布尺寸和绘制帧完成,首次进入页面即可得到有效裁剪结果。
## 属性
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
| --- | --- | --- | --- | --- |
| imageUrl | 要裁剪的图片路径,为空时显示“请传入图片”占位 | String | `''` | - |
| bgColor | 裁剪预览区背景颜色,支持 `$` 主题色简写 | String | `$page` | - |
| previewHeight | 预览区高度,数字单位为 px;`fill-viewport` 为 `true` 时忽略此值 | String \| Number | `360` | - |
| fillViewport | 是否让预览区撑满父容器剩余空间(整页裁剪模式) | Boolean | `false` | `true` \| `false` |
| tabBodyHeight | 底部工具面板主体区高度(预留,当前未生效,实际高度随字体大小乘数固定) | String \| Number | `''` | - |
| minCropWidth | 裁剪框最小宽度,数字单位为 px,为空时不限制 | String \| Number | `''` | - |
| minCropHeight | 裁剪框最小高度,数字单位为 px,为空时不限制 | String \| Number | `''` | - |
| minScale | 图片最小缩放比例 | Number | `1` | - |
| minCropPixels | 裁剪框对应原图的最小像素边长,用于限制最大放大倍数 | Number | `4` | - |
| outputScale | 输出倍率,导出图片尺寸 = 裁剪框尺寸 × 该倍率(再乘设备像素比) | Number | `1` | - |
| quality | 导出图片质量(0-1),当前导出固定为 PNG 格式 | Number | `1` | - |
| initialRatioId | 初始选中的比例项 id | String | `ratio-1-1` | - |
| ratioList | 比例预设列表 | SnClipperRatioItem[] | `自由、1:1、3:4、4:3、9:16、16:9 六项` | - |
| borderColor | 裁剪框边框与四角颜色 | String | `#FFFFFF` | - |
| customStyle | 自定义根节点样式 | SnStyleValue | `''` | - |
| customClass | 根节点外部样式类 | String | `''` | - |
> 类型字段:SnClipperRatioItem(见 https://sinleui.pages.dev/api/types/component#snclipperratioitem)
## 事件
| 名称 | 类型 | 说明 |
| --- | --- | --- |
| ready | (detail: SnClipperReadyDetail) => Void | 图片加载成功时触发,`detail` 包含 `width`、`height`(图片原始尺寸)与 `ratio`(当前比例) |
| change | (detail: SnClipperChangeDetail) => Void | 裁剪状态变化时触发(拖动、缩放、旋转、镜像、切换比例等),`detail` 包含 `rotation`、`flipX`、`flipY`、`scale`、`translateX`、`translateY`、`cropLeft`、`cropTop`、`cropWidth`、`cropHeight`、`ratio` |
| confirm | (detail: SnClipperConfirmDetail) => Void | 裁剪导出成功时触发 |
| cancel | () => Void | 点击取消(×)按钮时触发 |
| error | (error: SnClipperErrorDetail) => Void | 图片加载失败或导出失败时触发,`error.message` 为错误信息 |
> 类型字段:SnClipperConfirmDetail(见 https://sinleui.pages.dev/api/types/component#snclipperconfirmdetail)
> 类型字段:SnClipperReadyDetail(见 https://sinleui.pages.dev/api/types/component#snclipperreadydetail)
> 类型字段:SnClipperChangeDetail(见 https://sinleui.pages.dev/api/types/component#snclipperchangedetail)
> 类型字段:SnClipperErrorDetail(见 https://sinleui.pages.dev/api/types/component#snclippererrordetail)
## 方法
| 名称 | 参数 | 返回值 | 描述 |
| --- | --- | --- | --- |
| crop | - | - | 执行裁剪导出,成功后触发 `confirm` 事件;图片/画布未就绪时 toast 提示 |
| restore | - | - | 还原所有变换(旋转、镜像、缩放、平移、比例)至初始状态 |
| rotateCounterclockwise | - | - | 逆时针旋转 90°(别名 `rotateLeft`) |
| rotateClockwise | - | - | 顺时针旋转 90°(别名 `rotateRight`) |
| flipHorizontal | - | - | 左右镜像 |
| flipVertical | - | - | 上下镜像 |
| setRatio | (item: SnClipperRatioItem) | - | 切换为指定比例项并最大化裁剪框 |
# Signature 签名
> [查看 sn-signature 的 2.0 版本差异](/differences/components/sn-signature)
## 基础用法
手写签名板,适用于电子签署与自由书写。
- 提供多种笔触和画布背景、网格设置
- 支持撤销、重做、清空、导出与横竖屏切换
- 设置面板支持分类切换与滚动操作
::: details 设置面板与笔触说明
设置面板为组件内部自实现的覆盖层(非 `sn-drawer`),左右滑出动画只做 `transform` 过渡、显隐交给 `visibility`,无打开闪动;面板展开期间画布区不响应落笔,面板内 Tabs、滑块、开关等交互在横竖屏下一致可用;App 端面板内容区为组件内自实现的拖动滚动与横向 Tabs 切换,避免原生全屏容器内 `scroll-view` 子元素点击/触摸异常。
内置 17 种笔触(钢笔、毛笔、蜡笔、喷漆等),设置面板采用 Tabs 分类:「笔触」(笔触类型、线条颜色与粗细)与「画布」(画布背景、网格背景),点选标签或左右滑动内容区切换分类,面板内容区可上下拖动滚动;滚动后仍可点击当前可见的笔触按钮、色块和滑块。通过 ref 调用 `undo`、`redo`、`clear`、`exportImage`、`setLandscape` 方法可编程控制签名板。
:::
```vue
```
**更多演示请下载 demo 查看**
## 进阶用法
### 自定义笔触
通过 `brush` 属性指定初始笔触,设置面板内也可实时切换;`show-brush-settings` 为 `false` 时隐藏面板中的笔触选项。
```vue
```
### 横屏签名
点击操作栏的横屏图标可全屏横置签名板(Web 端铺满视口,App 端调用原生全屏横屏);也可通过 ref 调用 `setLandscape` 方法控制。横屏后签名板按当前窗口高度铺满屏幕,画布自动占据操作栏之外的全部空间。
App 端原生全屏(`requestFullscreen`)容器内,`scroll-view` 的子元素收不到点击/触摸事件(只有原生滚动仍生效),因此设置面板内容区在 App 端改为组件内自实现的拖动滚动与横向 Tabs 切换,横屏下 Tabs、滑块、开关、取色块均正常响应。
```vue
```
## 属性
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
| --- | --- | --- | --- | --- |
| width | 签名板宽度,支持 `$` 动态尺寸语法 | String \| Number | `100%` | - |
| height | 签名板(画布区)高度,数字单位为 px,支持 `$` 动态尺寸语法 | String \| Number | `280` | - |
| bgColor | 画布背景颜色,同时作为导出图片的背景色 | String | `#FFFFFF` | - |
| lineColor | 签名线条颜色 | String | `#1F1F1F` | - |
| lineWidth | 线条粗细(px) | Number | `3` | - |
| brush | 笔触样式 | `SnSignatureBrush` | `default` | `default`(默认) \| `pen`(钢笔) \| `gel`(中性笔) \| `pencil`(铅笔) \| `brush`(毛笔) \| `marker`(马克笔) \| `crayon`(蜡笔) \| `fur`(毛皮) \| `ink`(墨水) \| `longfur`(长绒毛) \| `ribbon`(丝带) \| `shaded`(阴影) \| `sketchy`(速写) \| `spray`(喷漆) \| `squares`(方格) \| `circle`(圆泡) \| `web`(蛛网) |
| showBrushSettings | 设置面板中是否显示笔触选项 | Boolean | `true` | `true` \| `false` |
| gridEnabled | 是否显示网格背景 | Boolean | `false` | `true` \| `false` |
| gridStyle | 网格样式,`gridEnabled` 为 `true` 时生效 | `SnSignatureGridStyle` | `square` | `dot` \| `square` \| `line` |
| gridColor | 网格线颜色 | String | `#B8B8B8` | - |
| gridLineWidth | 网格线宽(px) | Number | `1` | - |
| gridDensity | 网格密度,即网格间距(px) | Number | `20` | - |
| maxHistory | 最大撤销历史记录数 | Number | `20` | - |
| showActionBar | 是否显示底部操作栏(横竖屏、撤销、重做、清空、设置、导出) | Boolean | `true` | `true` \| `false` |
| drawerPosition | 设置面板滑出的方向 | String | `right` | `left` \| `right`(`top`/`bottom` 视为 `right`) |
| drawerWidth | 设置面板宽度 | String \| Number | `300px` | - |
| aniTime | 设置面板动画时长,支持 `$` 动态时长语法 | String \| Number | `''` | - |
| customStyle | 自定义根节点样式 | SnStyleValue | `''` | - |
| customClass | 根节点外部样式类 | String | `''` | - |
| canvasWrapClass | 画布容器外部样式类 | String | `''` | - |
| canvasWrapStyle | 自定义画布容器样式 | SnStyleValue | `''` | - |
| barClass | 操作栏外部样式类 | String | `''` | - |
| barStyle | 自定义操作栏样式 | SnStyleValue | `''` | - |
| toolClass | 操作栏工具按钮外部样式类 | String | `''` | - |
> 类型字段:SnSignatureBrush(见 https://sinleui.pages.dev/api/types/component#snsignaturebrush)
## 事件
| 名称 | 类型 | 说明 |
| --- | --- | --- |
| change | (data: SignatureData) => Void | 签名内容变化时触发(一笔结束、撤销、重做、清空),`data.dataUrl` 为空字符串,`width`/`height` 为当前画布尺寸 |
| exported | (data: SignatureData) => Void | 导出签名图片成功后触发,`data.dataUrl` 为 base64 图片数据,`width`/`height` 为图片实际像素尺寸(已乘设备像素比) |
| undo | () => Void | 撤销签名时触发 |
| redo | () => Void | 重做签名时触发 |
| clear | () => Void | 清空签名板时触发 |
| orientationchange | (landscape: boolean) => Void | 横竖屏切换时触发,参数为是否横屏 |
> 类型字段:SnSignatureGridStyle(见 https://sinleui.pages.dev/api/types/component#snsignaturegridstyle)
> 类型字段:SignatureData(见 https://sinleui.pages.dev/api/types/component#signaturedata)
## 方法
| 名称 | 参数 | 返回值 | 描述 |
| --- | --- | --- | --- |
| undo | - | - | 撤销上一笔签名 |
| redo | - | - | 重做上一笔撤销的签名 |
| clear | - | - | 清空签名板 |
| exportImage | - | - | 将签名导出为 base64 图片并通过 `exported` 事件返回;画布未就绪或无内容时以 toast 提示且不导出 |
| setLandscape | (land: Boolean) | - | 设置横屏(全屏)模式,`true` 进入横屏、`false` 退出 |
# Sketchpad 画板
## 基础用法
独立的手写画板组件,适用于签名、涂鸦、笔记等自由绘制场景。
- 支持画笔、橡皮与取色器,内置 18 种笔触与侧面色板
- 支持撤销 / 重做、清空与导出图片,可随时新建指定尺寸画布
- 支持网格背景与漫游模式(拖动画布、捏合缩放、松手惯性滑行),配色跟随主题
```vue
```
**更多演示请下载 demo 查看**
## 笔触与操作栏
内置 18 种笔触(含橡皮),完整取值可在属性表 `brush` 行展开查看。画笔与橡皮的粗细相互独立:切换工具后,颜色与粗细弹层、设置面板中的粗细滑块会自动指向当前工具的独立数值,互不干扰。画笔粗细范围为 1–128px、橡皮为 2–128px;蜡笔等笔触的粗细已与铅笔对齐,小尺寸下不再异常粗重。
顶部悬浮操作组提供漫游模式、重置视图、撤销、重做、清空、横竖屏切换与导出。竖屏底部控制区分为两行:上排为可横向拖动的紧凑笔触按钮,选中时显示主题色描边、浅色背景,图标与文字同步高亮;下排的画笔、橡皮、取色器与设置入口采用图标在上、文字在下的无底框布局,图标缩小但保持原有触控区域,中间保留圆形颜色与粗细入口。横屏时快捷笔触栏并入工具行,留出更多绘图区;横向拖动后可继续点击可见的笔触按钮。
设置面板采用抽屉样式与 Tabs 分类:「笔触」(全部笔触、线条颜色与粗细、端点样式)、「画布」(画布尺寸、画布背景、网格样式与参数、最大撤销步骤数)与「功能」(漫游模式、取色器、侧面色板、多指绘制开关与缩放控制);点选标签或左右滑动内容区切换分类。内容区和选项按钮采用紧凑内边距;各分类的内容可纵向惯性滚动并独立保留滚动位置,滚动后可继续操作当前可见的按钮、色块、滑块与开关;底部完成按钮保持紧凑高度。
操作栏和设置面板中的按钮、色块均由原生视图实现;设置按钮通过统一点击态机制提供按下反馈。
`lineCap`(默认 `round`)控制笔触端点形状:`butt` 平头、`square` 方头、`round` 圆头,设置面板「笔触」分类内以「平头 / 方头 / 圆头」显示并可切换。它对线型笔触(默认、钢笔、中性笔、马克笔、铅笔、毛笔等以线条描边为主的笔触)生效,每笔落笔时固定,改变设置只影响之后的笔画。
`multiTouch`(默认 `false`)控制多指绘制:开启后可用多根手指同时在画布上绘制,多笔并行互不干扰;关闭时仅响应第一根手指。漫游模式下点击画笔 / 橡皮 / 取色器按钮或任一画笔类型(即使点击的是当前已选中的笔刷)都会自动退出漫游模式并切回绘制模式,仅调整颜色与粗细不会退出。
## 全屏画板
将 `height` 设为 `fill`,并配合 `sn-page` 的 `fill-content` 属性(内容区填满剩余高度、不滚动)即可让画板铺满整个页面:
绘制事件仅在实际画布范围内生效。自适应画布已有内容时,页面可用空间变化会同步调整逻辑画布并迁移已有笔迹。
::: warning 横竖屏切换
如果需要切换横竖屏后保持绘制内容不变形,必须选定画布尺寸(同时指定 `canvasWidth` 和 `canvasHeight`,或在设置面板选择固定尺寸),不要使用「适应组件」。
:::
```vue
```
Demo 页收到导出成功事件后,竖屏直接以 `sn-popup` 展示导出图片;横屏先调用 `setLandscape(false)` 退出全屏,待 `orientationchange(false)` 后再打开弹窗。预览使用 `image` 的 `aspectFit` 模式,点击关闭按钮或遮罩可返回画板。
## 横屏模式
点击顶部悬浮栏的横屏图标可进入原生全屏横屏,再次点击退出;也可通过 ref 调用 `setLandscape` 方法控制。横屏后画板根据原生全屏事件获取当前窗口尺寸,绘图区自动占据底部工具栏之外的全部空间;默认底部设置抽屉在横屏下适当增高,左右两侧叠加屏幕安全区和固定留白,避开刘海、挖孔区域(自定义抽屉尺寸保持原值);组件卸载时会自动退出全屏。
横屏时首次触发页面返回会退出横屏并留在当前页面;恢复竖屏后再次返回,由页面按默认行为处理。iOS 侧滑返回默认不触发页面返回事件,不在此拦截范围内。
```vue
```
## 网格样式
`gridStyle` 支持 `dot`(点阵)、`square`(方格)、`line`(横线)三种样式,与「无网格」组成设置面板中的四态选择;`gridEnabled` 为 `false` 时等同于「无」,不显示网格。
```vue
```
## 画布尺寸
通过 `canvasWidth` / `canvasHeight` 指定画布逻辑尺寸(px,取值 64–4096),需同时大于 0 才生效;任一为 0(默认)时画布自动适应组件尺寸。画布尺寸大于组件显示区域时会等比缩放适配显示,导出位图的 `width` / `height` 以实际渲染倍率为准;该倍率只由画布尺寸、组件显示尺寸与设备像素比决定,**与当前漫游缩放倍率无关**,因此同一画布在不同缩放下导出结果一致。
也可通过 ref 调用 `newCanvas(width, height)` 随时新建指定尺寸画布,新画布会清空当前笔画与历史(`width`、`height` 传 0 或省略时恢复自适应尺寸):
```vue
```
设置面板「画布」分类内置 `适应组件`、`1:1`、`4:3`、`16:9`、`9:16` 比例预设与自定义宽高输入。
画布之外会露出垫层(底色):垫层颜色可在设置面板「画布」→「画布垫层」中配置,或通过 `underlayColor` 属性指定,画布自身带一圈可见边界线,便于区分画布范围;橡皮擦除只作用在笔画层,擦掉处露出画布背景与网格。
## 漫游模式
`roamEnabled` 为 `true`(默认)时,左上角悬浮操作组首位显示漫游开关;开启后单指拖动画布、双指捏合缩放(缩放范围 25%–800%),拖动松手后按松手速度惯性滑行并指数阻尼减速,撞到平移边界立即停止;此时画布不接受落笔;点击画笔 / 橡皮 / 取色器,或切换笔触(快捷笔刷栏与设置面板中的笔触选项)会自动退出漫游模式,仅调整颜色或粗细不会退出。漫游中悬浮组会依次显示「重置视图」、缩小、放大按钮(每次缩放步长由 `zoomStep` 控制,默认 10%),设置面板「功能」分类也提供缩小、重置、放大控制与当前缩放比例显示(缩放比例在松手后更新,避免手势中反复刷新面板)。
平移范围受限,画布不会被移出屏幕:画布边角最远只能移动到视口中心,即画布始终覆盖视口中心点——因此拖动可以露出画布边界外的垫层,但画布始终有一部分留在视口内、不会被整体移出。缩小 / 放大以视口中心为锚点(捏合则以两指中点为锚点),视角不会因缩放而跳动。
### 渲染与清晰度
画板由底图层和笔画层组成,两层同处一个合成层(漫游时只改这一层的合成变换、不做任何重绘),因此手势始终跟手:
- **底图**:画布背景与网格,整幅画布尺寸;
- **笔画层**:全部笔画的全幅画布,内容变化时仅重绘该层,手势过程不触发整幅位图重建。
画布位图尺寸由画布尺寸、组件显示尺寸与设备像素比决定:App 平台画布位图尺寸只读、由平台按画布元素布局尺寸决定(`canvas.width/height` 赋值不生效),Web 端由框架按设备像素比设置。绘制倍率始终按画布**实际位图尺寸**反推(`canvas.width / 画布逻辑宽度`),保证屏幕坐标与画布内容坐标严格一致。
App 端笔画层在创建时与画布尺寸变化时按位图像素预算一次性预留放大分辨率(通过画布元素的布局尺寸实现,位图随布局自动放大到该分辨率),因此放大后笔画依然清晰。漫游缩放与平移全程只做合成变换,不重建位图、不改变画布尺寸与内容,手势期间无闪动、无偏移。
::: info
放大分辨率受位图像素预算(约 800 万像素)封顶,极大画布或极高倍率下会优先保证稳定性;App 平台画布位图尺寸只读,清晰度上限由设备像素比与画布布局尺寸决定。
:::
拖动 / 缩放过程中只对整个 stage 做合成变换;快速连续拖动或缩放不会重绘画布。
### 大画布与大量笔画
笔画较多时,整幅重建会被拆成按帧预算(约 8ms)执行的分片任务,在 `requestAnimationFrame` 回调间推进:UI 线程不会被一次重建长时间占住,按钮、面板等交互全程可用,画面则从旧内容平滑地补全为新内容。笔画很少时(不超过 150 笔)仍然一次性同步完成,避免无谓的分帧开销。同一时刻只存在一个重建任务,新的手势、撤销重做、清空、导出都会正确接管或取消它。
笔画渲染本身的复杂度也已收敛:`shaded`、`sketchy`、`fur`、`longfur`、`web` 这类"纤维"笔刷原先对每一段都回溯该笔画此前的**全部**点(长笔画退化为 O(n²)),现在改为只回溯弧长范围内的邻近点,长笔画的开销与点数线性相关。
```vue
```
## 取色器与侧面色板
`eyedropperEnabled`(默认 `true`)控制工具栏吸管工具,点击画布任意位置吸取颜色:吸取结果会设为当前笔触颜色、触发 `pick` 事件,并在侧面色板开启时自动加入色板。橡皮工具旁的吸管图标仅在开启时显示。
`paletteEnabled`(默认 `true`)控制画布侧边的色板:色点为圆形排列,点击应用为当前笔触颜色(可快速切换笔刷颜色),长按删除色点;「+」按钮打开颜色选择器(弹窗内同时展示内置预设颜色),横屏下会先退出横屏、待布局恢复后再打开颜色选择器,点击已有色点则保持横屏并直接选色。色板同步展示在弹窗底部的 `extra` 插槽中——点击色点将该颜色载入取色面板(再点「确定」生效),长按色点删除,直接用取色面板选好颜色后点「确定」即可把新颜色加入色板,色板为空时插槽内会显示空状态提示;`palettePosition` 可设为 `left` 或 `right`(默认)决定色板所在侧,`paletteColors` 提供初始色板颜色。色板容量随画布显示高度自适应,超出时不再允许添加。
:::tip 提示
uvue 的事件系统不提供右键事件(`UniMouseEvent` 无按键信息),色点删除统一使用长按(触屏)或按住鼠标左键(Web)约 0.65 秒实现。
:::
```vue
```
## 撤销与重做
撤销/重做的历史由框架的 [`useHistory`](/api/hooks/use-history) 增量操作日志引擎驱动,理解它的存储模型有助于正确设置 `maxHistory`:
- **一笔即一步**:每一笔完整笔画(含橡皮笔画与点按产生的短笔画)记录为一步,不做按时间窗口的连笔合并,撤销语义与「撤销上一笔」完全一致。
- **不存快照**:历史只记录每一步在笔画池中的下标与权重,既不复制笔画,也不缓存画布位图,因此历史内存与「笔画的点数」成正比,而不是与步数 × 画布面积成正比。
- **两步预算**:`maxHistory` 是步数上限;此外引擎还有 12 万点的权重预算,笔画特别密集时实际可撤销步数会少于 `maxHistory`,但内存占用始终有上限。
- **可在设置面板调节**:设置面板「画布」分类底部提供「最大撤销步骤数」滑块,范围 1–100(`maxHistory` 传入大于 100 时滑块上限随之扩展);面板改动即时生效,调小后立刻回收多余的历史步骤,`maxHistory` prop 变化时也会同步回面板。
- **重做失效时机**:只有「当前笔结束、产生新的一步」会清空重做;切换工具、改颜色、改网格、横竖屏切换都不会丢弃已撤销的内容。
- **清空会重置历史**:调用 `clear` 方法(或点击清空按钮)后撤销栈一并清空,此前的内容无法再撤销。
- **落笔期间不接受撤销**:手指未离开画布时调用 `undo`、`redo` 或 `clear` 会被忽略,避免历史与画布内容不同步。
撤销只对受影响的区域做增量重绘:先清掉被撤销笔画的包围盒,再按顺序重放与之相交的笔画;重做则只补画被恢复的那一笔。因此撤销、重做的开销与「相交笔画数」相关,而不是与总笔画数相关。
## 属性
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
| --- | --- | --- | --- | --- |
| width | 画板宽度,支持 `$` 动态尺寸语法 | String \| Number | `100%` | - |
| height | 画布高度,数字单位为 px,传入 `fill` 时画布占满组件剩余高度(配合 `sn-page` 的 `fill-content` 可铺满全屏) | String \| Number | `280` | - |
| canvasWidth | 指定画布逻辑宽度(px,64–4096),需与 `canvasHeight` 同时大于 0;任一为 0 时画布自适应组件尺寸 | Number | `0` | - |
| canvasHeight | 指定画布逻辑高度(px,64–4096),需与 `canvasWidth` 同时大于 0;任一为 0 时画布自适应组件尺寸 | Number | `0` | - |
| bgColor | 画布背景和导出图片背景颜色,为空时跟随主题(亮色 `#FFFFFF`、暗色 `#28292A`) | String | `跟随主题` | - |
| underlayColor | 画布垫层(画布边界之外的底衬)颜色,为空时跟随主题(亮色 `#E5E7EB`、暗色 `#141416`) | String | `跟随主题` | - |
| lineColor | 笔触颜色,为空时跟随主题(亮色 `#1F1F1F`、暗色 `#F1F1F1`) | String | `跟随主题` | - |
| lineWidth | 笔触粗细,单位 px | Number | `3` | - |
| eraserWidth | 橡皮粗细,单位 px | Number | `16` | - |
| brush | 初始笔触类型 | `SnSketchpadBrush` | `default` | - |
| lineCap | 笔触端点样式,设置面板「笔触」分类内可切换 | String | `round` | `butt` \| `square` \| `round` |
| showBrushSettings | 是否显示快捷笔刷栏与设置面板中的笔触选项 | Boolean | `true` | `true` \| `false` |
| multiTouch | 是否开启多指绘制(设置面板「功能」分类内可切换) | Boolean | `false` | `true` \| `false` |
| gridEnabled | 是否显示网格背景 | Boolean | `false` | `true` \| `false` |
| gridStyle | 网格样式,`gridEnabled` 为 `true` 时生效 | `SnSketchpadGridStyle` | `square` | `dot` \| `square` \| `line` |
| gridColor | 网格颜色 | String | `#B8B8B8` | - |
| gridLineWidth | 网格线宽,单位 px | Number | `1` | - |
| gridDensity | 网格间距,单位 px | Number | `20` | - |
| maxHistory | 最大撤销步骤数,设置面板内可直接调节(默认上限 100) | Number | `20` | - |
| roamEnabled | 是否启用漫游模式(左上角悬浮按钮与设置面板开关) | Boolean | `true` | `true` \| `false` |
| eyedropperEnabled | 是否启用取色器(工具栏吸管工具与设置面板开关) | Boolean | `true` | `true` \| `false` |
| paletteEnabled | 是否启用侧面色板 | Boolean | `true` | `true` \| `false` |
| palettePosition | 侧面色板位置 | String | `right` | `left` \| `right` |
| paletteColors | 侧面色板初始颜色 | Array\ | `空` | - |
| zoomStep | 漫游缩放按钮每次放大 / 缩小的百分比步长 | Number | `10` | - |
| showActionBar | 是否显示操作栏(顶部悬浮按钮与底部控制区) | Boolean | `true` | `true` \| `false` |
| drawerPosition | 设置面板方向 | String | `bottom` | `top` \| `right` \| `bottom` \| `left` |
| drawerWidth | 设置面板尺寸,`left`/`right` 为宽度、`top`/`bottom` 为高度,支持百分比 | String \| Number | `70%` | - |
| aniTime | 设置面板动画时长 | String \| Number | `''` | - |
| customStyle | 根节点样式 | UTSJSONObject \| String | `''` | - |
| customClass | 根节点外部样式类 | String | `''` | - |
| canvasWrapClass | 画布容器外部样式类 | String | `''` | - |
| canvasWrapStyle | 画布容器样式 | UTSJSONObject \| String | `''` | - |
| barClass | 底部控制区外部样式类 | String | `''` | - |
| barStyle | 底部控制区样式 | UTSJSONObject \| String | `''` | - |
| toolClass | 操作按钮外部样式类 | String | `''` | - |
## 事件
| 名称 | 类型 | 说明 |
| --- | --- | --- |
| change | `(data: SketchpadData) => Void` | 一笔结束、撤销、重做、清空或画布尺寸变化后触发 |
| exported | `(data: SketchpadData) => Void` | 导出图片成功后触发,`dataUrl` 为 base64 图片数据 |
| undo | `() => Void` | 撤销成功后触发 |
| redo | `() => Void` | 重做成功后触发 |
| clear | `() => Void` | 清空成功后触发 |
| pick | `(color: string) => Void` | 取色器吸取颜色后触发 |
| palettechange | `(colors: Array) => Void` | 侧面色板颜色增删后触发 |
| orientationchange | `(landscape: Boolean) => Void` | 横竖屏模式切换后触发 |
## 方法
| 名称 | 参数 | 说明 |
| --- | --- | --- |
| undo | - | 撤销上一笔 |
| redo | - | 重做上一笔撤销的内容 |
| clear | - | 清空画板 |
| exportImage | - | 导出为 base64 图片并触发 `exported` |
| setLandscape | `land: Boolean` | 设置横屏或竖屏模式 |
| newCanvas | `width?: Number, height?: Number` | 新建指定尺寸画布并覆盖当前画布(清空笔画与历史);传 0 或省略恢复自适应尺寸 |
| resetView | - | 重置漫游视图(缩放恢复 100%、平移归零) |
> 类型字段:SnSketchpadBrush(见 https://sinleui.pages.dev/api/types/component#snsketchpadbrush)
> 类型字段:SnSketchpadGridStyle(见 https://sinleui.pages.dev/api/types/component#snsketchpadgridstyle)
> 类型字段:SketchpadData(见 https://sinleui.pages.dev/api/types/component#sketchpaddata)
# CalendarPunch 签到日历
## 基础用法
签到打卡日历,是日历组件的打卡形态。
- 已打卡、可补签与今天分别以圆点或文字高亮区分
- 可关闭补签;周起始日与标题格式可配置
- 组件不执行签到,业务在日期选择回调中处理打卡 / 补签
```vue
```
**更多演示请下载 demo 查看**
## 进阶用法
### 关闭补签
```vue
```
## 属性
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
| --- | --- | --- | --- | --- |
| v-model | 绑定值(type 固定为 single,实际为当天零点时间戳或 null) | SnCalendarValue | `null` | - |
| signedDates | 已打卡日期列表(YYYY-MM-DD,无效值自动忽略,按天匹配) | String[] | `[]` | - |
| canSupplement | 是否允许补签(为 true 时未打卡且不晚于今天的日期显示补签圆点) | Boolean | `true` | `true \| false` |
| signedDotColor | 已打卡圆点颜色,支持 $ 简写 | String | `$primary` | - |
| unsignedDotColor | 可补签圆点颜色,支持 $ 简写 | String | `$warning` | - |
| todayText | 今天日期显示的文字,空时显示原始日期 | String | `今天` | - |
| todayTextColor | 今天文字颜色,支持 $ 简写 | String | `$warning` | - |
| minDate | 最小可选日期(毫秒时间戳),默认 6 个月前的当月 1 号 | Number | - | - |
| maxDate | 最大可选日期(毫秒时间戳),默认当天起 6 个月 | Number | - | - |
| firstDayOfWeek | 每周第一天(0 为周日) | Number | `1` | `0~6` |
| readonly | 是否只读(禁用切换与选择) | Boolean | `false` | `true \| false` |
| titlePicker | 点击标题是否展开年月选择面板 | Boolean | `false` | `true \| false` |
| switchLongpress | 长按左右切换按钮是否连续切换 | Boolean | `true` | `true \| false` |
| showWatermark | 是否显示月份水印数字 | Boolean | `false` | `true \| false` |
| rowHeight | 单行日期高度 | String \| Number | `$48` | - |
| height | 视图整体高度 | String \| Number | `$420` | - |
| dayFontSize | 日期字号 | String \| Number | `$14` | - |
| dayRadius | 日期气泡圆角 | String \| Number | `$6` | - |
| dayGap | 日期气泡与单元格边缘的间距 | String \| Number | `$2` | - |
| selectedDayBgColor | 选中日期背景色,支持 $ 简写 | String | `$line` | - |
| selectedDayTextColor | 选中日期文字颜色,支持 $ 简写 | String | `$text` | - |
| dayTextColor | 日期文字颜色 | String | `$text` | - |
| adjacentDayTextColor | 非当前月日期文字颜色 | String | `$lineText` | - |
| disabledDayTextColor | 禁用日期文字颜色 | String | `$disabledText` | - |
| customStyle | 自定义根节点样式 | SnStyleValue | `''` | - |
| customClass | 外部样式类 | String | `''` | - |
| headerStyle | 自定义头部样式 | SnStyleValue | `''` | - |
| headerClass | 外部样式类 | String | `''` | - |
| switchStyle | 自定义月份切换按钮样式 | SnStyleValue | `''` | - |
| switchClass | 外部样式类 | String | `''` | - |
| weekdaysStyle | 自定义星期标题行样式 | SnStyleValue | `''` | - |
| weekdaysClass | 外部样式类 | String | `''` | - |
| weekdayStyle | 自定义单个星期标题样式 | SnStyleValue | `''` | - |
| weekdayClass | 外部样式类 | String | `''` | - |
| monthTitleStyle | 自定义月份标题文字样式 | SnStyleValue | `''` | - |
| monthTitleClass | 外部样式类 | String | `''` | - |
> 类型字段:SnCalendarValue(见 https://sinleui.pages.dev/api/types/component#sncalendarvalue)
## 事件
| 名称 | 类型 | 说明 |
| --- | --- | --- |
| select | (day: `SnCalendarPunchDay`) => Void | 点击选中日期时触发,返回打卡信息(`SnCalendarPunchDay`,见下方类型) |
| panel-change | (detail: `SnCalendarPanelChangeDetail`) => Void | 面板所在月份变化时触发 |
> 类型字段:SnCalendarPunchDay(见 https://sinleui.pages.dev/api/types/component#sncalendarpunchday)
> 类型字段:SnCalendarPanelChangeDetail(见 https://sinleui.pages.dev/api/types/component#sncalendarpanelchangedetail)
## 方法
| 名称 | 参数 | 返回值 | 描述 |
| --- | --- | --- | --- |
| scrollToDate | (value: Number) | - | 选中指定日期(毫秒时间戳)并跳转到其所在月份 |
## 类型
`SnCalendarPanelChangeDetail` 与 `format` 相关的 `SnCalendarDay` 等类型见 `sn-calendar-view` 文档的「类型」一节。
# Barcode 一维码
> [查看 sn-barcode 的 2.0 版本差异](/differences/components/sn-barcode)
## 基础用法
纯 Canvas 自绘的一维码组件,不依赖原生条码库。
- 支持 9 种常见一维码格式,可旋转与圆角化显示
- 可在条码下方显示编码文本
- 编码内容按 UTF-8 字节数计算,上限 300 字节,超出自动截断
::: info 首帧渲染
组件在画布取得实际尺寸后绘制首帧,首次进入页面即可正常显示,无需再次进入。
:::
```vue
```
**更多演示请下载 demo 查看**
## 属性
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
| --- | --- | --- | --- | --- |
| value | 条形码数据 | String | `SN-20260820` | - |
| codeType | 条形码格式 | `SnBarcodeFormat` | `code128` | `code128` \| `code39` \| `code93` \| `codabar` \| `ean8` \| `ean13` \| `upca` \| `upce` \| `itf` |
| width | 条码区域宽度,最小 48px | String \| Number | `280` | - |
| height | 条码区域高度,最小 24px | String \| Number | `96` | - |
| padding | 左右留白边距 | String \| Number | `8` | - |
| rotation | 旋转方向 | String | `N` | `N` 正常 \| `L` 左转 \| `R` 右转 \| `I` 倒转 |
| showValue | 是否在条码下方显示编码文本 | Boolean | `true` | `true` \| `false` |
| valueAlign | 编码文本对齐方式 | String | `center` | `left` \| `center` \| `right` |
| valueFontSize | 编码文本字体大小,最小 8px | String \| Number | `14` | - |
| valueSpacing | 编码文本与条码间距 | String \| Number | `8` | - |
| barColor | 条纹(前景)颜色,支持 `$` 主题色与 `var(--sn-*)` | String | `#111111` | - |
| backgroundColor | 背景颜色,支持 `$` 主题色与 `var(--sn-*)` | String | `transparent` | - |
| valueColor | 编码文本颜色,跟随 `barColor` | String | - | - |
| barShape | 条纹形状 | String | `flat` | `flat` \| `rounded` |
| barRadius | 条纹圆角(仅 `barShape=rounded` 生效) | String \| Number | `6` | - |
| moduleMinWidth | 最小模块宽(px),保证密集码型可辨认 | String \| Number | `1` | - |
| customStyle | 自定义根节点样式 | SnStyleValue | - | - |
| codeStyle | 自定义条码画布样式 | SnStyleValue | - | - |
| valueStyle | 自定义编码文本样式 | SnStyleValue | - | - |
| customClass | 自定义根节点类名 | String | - | - |
| codeClass | 自定义条码画布类名 | String | - | - |
| valueClass | 自定义编码文本类名 | String | - | - |
> 类型字段:SnBarcodeFormat(见 https://sinleui.pages.dev/api/types/component#snbarcodeformat)
## 类型
> 类型字段:SnBarcodeBarElement(见 https://sinleui.pages.dev/api/types/component#snbarcodebarelement)
> 类型字段:SnBarcodeData(见 https://sinleui.pages.dev/api/types/component#snbarcodedata)
# Qrcode 二维码
> [查看 sn-qrcode 的 2.0 版本差异](/differences/components/sn-qrcode)
## 基础用法
纯 Canvas 自绘的二维码组件,不依赖任何原生二维码库,跨平台可用。
- 支持自定义信息点 / 定位点 / 校准点 / 时序点的形状、缩放、圆角与颜色
- 支持在二维码中央叠加 Logo,并可指定二维码版本与掩码图样
- 编码内容按 UTF-8 字节数计算,上限 300 字节,超出自动截断且不拆分多字节字符
::: info 首帧渲染
组件在画布取得实际尺寸后绘制首帧,首次进入页面即可正常显示,无需再次进入。
:::
```vue
```
**更多演示请下载 demo 查看**
## 属性
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
| --- | --- | --- | --- | --- |
| value | 二维码内容数据 | String | https://sinleui.pages.dev | - |
| size | 画板尺寸(宽高一致),最小 96px | String \| Number | `200` | - |
| padding | 留白边距(模块数) | Number | `2` | - |
| errorCorrectionLevel | 纠错等级 | `QrEcLevel` | `medium` | `low` \| `medium` \| `quartile` \| `high` |
| qrVersion | 二维码版本(1-40),0 表示自动选择 | Number | `0` | - |
| maskPattern | 掩码图样(0-7),-1 表示自动选择最优 | Number | `-1` | - |
| infoDotShape | 信息点形状 | `QrModuleShape` | `square` | `square` \| `rounded` \| `circle` \| `diamond` |
| locateDotShape | 定位点(点阵模式)形状 | `QrModuleShape` | `square` | `square` \| `rounded` \| `circle` \| `diamond` |
| locateDotPattern | 定位点绘制图样 | String | `dots` | `dots` \| `square` \| `rounded-square` \| `circle` |
| infoDotScale | 信息点缩放(0.1-1.3) | Number | `1` | - |
| locateDotScale | 定位点缩放(0.1-1.3) | Number | `1` | - |
| infoDotRadius | 信息点圆角系数(0-0.5) | Number | `0.22` | - |
| locateDotRadius | 定位点圆角系数(0-0.5) | Number | `0.28` | - |
| infoDotGap | 信息点间隙(0-0.6) | Number | `0` | - |
| infoDotColor | 信息点颜色 | String | `#111111` | - |
| locateDotColor | 定位点颜色,跟随 `infoDotColor` | String | - | - |
| alignDotColor | 校准点颜色,依次跟随 `locateDotColor`、`infoDotColor` | String | - | - |
| timingDotColor | 时序点颜色,跟随 `infoDotColor` | String | - | - |
| backgroundColor | 背景颜色 | String | `#ffffff` | - |
| showBackground | 是否绘制背景层 | Boolean | `true` | `true` \| `false` |
| logoSrc | 中央 Logo 图片路径,留空不显示 | String | - | - |
| logoSize | Logo 尺寸,自动限制在画板的 16px ~ 45% 之间 | String \| Number | `52` | - |
| logoPadding | Logo 内边距,自动限制不超过尺寸的 1/3 | String \| Number | `8` | - |
| logoRadius | Logo 圆角 | String \| Number | `14` | - |
| logoBackgroundColor | Logo 背景颜色 | String | `#ffffff` | - |
| customStyle | 自定义根节点样式 | SnStyleValue | - | - |
| backgroundStyle | 自定义背景层样式 | SnStyleValue | - | - |
| customClass | 自定义根节点类名 | String | - | - |
| backgroundClass | 自定义背景层类名 | String | - | - |
> 类型字段:QrEcLevel(见 https://sinleui.pages.dev/api/types/component#qreclevel)
> 类型字段:QrModuleShape(见 https://sinleui.pages.dev/api/types/component#qrmoduleshape)
# Scan 扫码
> [查看 sn-scan 的 2.0 版本差异](/differences/components/sn-scan)
## 基础用法
基于 `sn-e-scan-provider` 扩展插件重构的一体化扫码组件,内置完整扫码界面,支持二维码 / 条码识别。
- 内置导航栏、扫描线动效、提示文字、手电筒、相册入口与识别点
- 支持双击还原缩放、双指捏合缩放、相册图片识别、只扫一次与连续扫描
- 浮层相对组件自身区域定位,可整页使用,也可嵌入页面局部区域(如半屏扫码)
::: info 平台支持
- 当前在 **App 全平台**(Android / iOS / HarmonyOS)端渲染与生效,其余平台渲染为空视图
- **平台差异**:iOS 端由底层 `sn-scan-provider`(zcscan)拉起整页扫码界面,手电筒、手势缩放、初始缩放、识别间隔不生效(相机扫码由其整页界面接管);HarmonyOS 端由 Scan Kit 自定义界面扫码实现,能力与 Android 端一致
:::
```vue
```
**更多演示请下载 demo 查看**
## 属性
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
| --- | --- | --- | --- | --- |
| title | 扫码页面标题 | String | `扫一扫` | - |
| titleSize | 标题字体大小 | String \| Number | `$18` | - |
| titleColor | 标题颜色 | String | `#fff` | - |
| tip | 扫码提示文字;按 `scanType` 自动显示(二维码 / 条码 / 二维码或条码) | String | - | - |
| tipColor | 提示文字颜色,跟随 `titleColor` | String | - | - |
| tipSize | 提示文字字体大小 | String \| Number | `$14` | - |
| torchText | 手电筒提示文字 | String | `轻触点亮或关闭` | - |
| torchTextColor | 手电筒提示文字颜色 | String | `#fff` | - |
| torchTextSize | 手电筒提示文字字体大小 | String \| Number | `$12` | - |
| dotSize | 识别点大小 | String \| Number | `35px` | - |
| scanType | 扫码类型 | SnScanType | `all` | `qrcode` \| `barcode` \| `all` |
| lineAniTime | 扫描线动画时长(单位:ms) | String \| Number | `5000ms` | - |
| enableDing | 是否开启识别成功声音提示 | Boolean | `true` | `true` \| `false` |
| dingFileSrc | 自定义提示声音文件路径 | String | - | - |
| scanOnlyOnce | 是否只扫描一次(与 `continuous` 不可同为 `true`) | Boolean | `false` | `true` \| `false` |
| continuous | 是否连续扫描(与 `scanOnlyOnce` 不可同为 `true`) | Boolean | `false` | `true` \| `false` |
| continuousSleep | 连续扫描间隔时间(单位:ms) | Number | `2000` | - |
| showTorch | 是否显示手电筒按钮,iOS 端不生效 | Boolean | `true` | `true` \| `false` |
| showAlbum | 是否显示相册按钮 | Boolean | `true` | `true` \| `false` |
| showBackButton | 是否显示返回按钮 | Boolean | `true` | `true` \| `false` |
| showTitle | 是否显示标题(隐藏时导航栏两侧的占位按钮同步隐藏) | Boolean | `true` | `true` \| `false` |
| showTip | 是否显示提示文字 | Boolean | `true` | `true` \| `false` |
| showAni | 是否显示扫描线动效 | Boolean | `true` | `true` \| `false` |
| enableZoom | 是否允许手势缩放,iOS 端不生效 | Boolean | `true` | `true` \| `false` |
| initZoomScale | 初始缩放比例,iOS 端不生效 | Number | `0` | - |
| recognizeInterval | 识别间隔(单位:ms,取值 0 ~ 5000,为 `0` 时每帧识别),iOS 端不生效 | Number | `0` | - |
| cameraPermTip | 相机权限请求提示文案 | String | `相机权限默认文案` | - |
| albumPermTip | 相册权限请求提示文案 | String | `相册权限默认文案` | - |
| customDotStyle | 自定义识别点样式 | SnStyleValue | - | - |
| customDotIconStyle | 自定义识别点图标样式 | SnStyleValue | - | - |
| customTitleStyle | 自定义标题样式 | SnStyleValue | - | - |
| customTipStyle | 自定义提示文字样式 | SnStyleValue | - | - |
| customStyle | 自定义组件根节点样式 | SnStyleValue | - | - |
| customClass | 自定义组件根节点类名 | String | - | - |
## 事件
| 名称 | 类型 | 说明 |
| --- | --- | --- |
| button-click | (name: string) => Void | 点击界面按钮时触发,`name` 可选值为 `return`(返回)、`album`(相册)、`torch`(手电筒) |
| scanned | (res: SnScanResult) => Void | 扫码成功时触发,结构见下方类型 |
| goin | (value: string) => Void | 选择识别点时触发,`value` 为识别的文本数据 |
## 方法
| 名称 | 参数 | 返回值 | 描述 |
| --- | --- | --- | --- |
| rescan | - | - | 重新开始扫描 |
| setTorchStatus | (value: boolean) | - | 设置手电筒开关状态 |
| scanImageByURI | (src: string) | - | 通过图片 URI 识别图片中的码 |
| setZoomRatio | (zoomRatio: number) | - | 设置相机缩放比例 |
| getZoomRatio | - | number | 获取当前相机缩放比例 |
## 类型
> 类型字段:SnScanType(见 https://sinleui.pages.dev/api/types/component#snscantype)
> 类型字段:SnScanMode(见 https://sinleui.pages.dev/api/types/component#snscanmode)
> 类型字段:SnScanDataPosition(见 https://sinleui.pages.dev/api/types/component#snscandataposition)
> 类型字段:SnScanData(见 https://sinleui.pages.dev/api/types/component#snscandata)
> 类型字段:SnScanResult(见 https://sinleui.pages.dev/api/types/component#snscanresult)
`SnScanType`、`SnScanResult` 等类型由扩展插件 `sn-e-scan-provider` 导出;`SnScanParams` 为传参参数类型,由 SinleUI 框架导出(结构同上方属性表)。
# Scankit 华为扫码
> [查看 sn-e-scankit 的 2.0 版本差异](/differences/components/sn-e-scankit)
## 基础用法
基于华为统一扫码服务(Scan Kit)封装的扩展插件,当前仅支持 Android 平台。
- 针对反光、暗光、污损、小码、大角度等复杂场景做了识别优化,扫码成功率较高
- 提供全屏扫码能力,支持相机扫码与导入图片扫码
- 附带码图生成组件,可将字符串转换为一维码 / 二维码
::: info 权限申请
- 相机与相册权限由插件内部申请:未授权时先弹出 `permTip` 说明弹窗,确认后请求系统权限,拒绝后跳转系统权限设置页。
:::
::: details 扫码 API 与码图生成组件
- **扫码 API `scan`**:调用 Scan Kit 的 Default View Mode,弹出华为标准全屏扫码界面(支持相机扫码与导入图片扫码),扫完通过回调返回码值;
- **码图生成组件 `sn-e-scankit-code`**:基于 `ScanUtil.buildBitmap` 将字符串转换为一维码 / 二维码(EAN-8、EAN-13、UPC-A、UPC-E、Codabar、Code 39、Code 93、Code 128、ITF14、QR、DataMatrix、PDF417、Aztec),支持自定义前后景色、容错级别与 QR 中部 Logo。
:::
## 兼容性
| Web | Android |
| --- | ------- |
| × | √ |
> Web 端调用 `scan` 会提示平台不支持;Web 端 `sn-e-scankit-code` 渲染为空节点,请使用 `sn-qrcode` / `sn-barcode` 代替。
**更多演示请下载 demo 查看**
---
## scan() 华为扫码
### **弹出华为标准全屏扫码界面并返回识别结果**
调用华为 Scan Kit Default View Mode 进行扫码,支持相机扫码与导入图片扫码。
### 属性
| 名称 | 类型 | 必备 | 默认值 | 描述 |
| --- | --- | --- | --- | --- |
| configs | UTSJSONObject | 否 | `{}` | 扫码配置,字段见下表 |
| callback | (res: ScanResult) => Void | 是 | - | 扫码结果回调 |
`configs` 支持字段(蒸汽模式下类型化对象经桥接会降级,故此处传入 UTSJSONObject,插件内部解析字段):
| 字段 | 类型 | 默认值 | 描述 |
| --- | --- | --- | --- |
| scanTypes | string 数组 | `全部 14 种码` | 需要识别的码制式(`'QRCODE'` / `'EAN_13'` 等,见[下文类型](#scantype)),限定制式可提高扫码速度 |
| titleType | Number | `0` | 扫码界面标题:`0` = "扫描二维码/条码",`1` = "扫描二维码" |
| permTip | String | ` 本应用正在请求您的相机、相册权限,仅用于条码、二维码识别,且通过系统途径读取数据,不会将任何数据上传至云端。如不提供此权限,则无法正常使用扫码功能。` | 权限申请弹窗提示语,仅在权限未授予时弹出 |
### 返回值
无(结果经 `callback` 返回 `ScanResult`:`format` 为码值类型(text / url / telephone 等),`data` 为码值字符串)。
### 示例
```typescript
import { snu } from '@/uni_modules/sinle-ui'
import { scan } from '@/uni_modules/sn-e-scankit'
import type { ScanResult } from '@/uni_modules/sn-e-scankit'
scan({}, (res: ScanResult) => {
snu.showModal({
title: '扫码结果',
content: `格式:${res.format}\n内容:${res.data}`
})
})
scan({ scanTypes: ['QRCODE'] }, (res: ScanResult) => {
console.log(res.format, res.data)
})
```
---
# ScankitCode 华为码图
`sn-e-scankit-code` 将字符串转换为一维码 / 二维码码图。组件基于 `native-view` 绑定原生 ImageView,按自身尺寸实时生成高清码图,随尺寸变化自动重新生成。使用时需给组件**显式设置宽高**。
```vue
```
## 属性
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
| --- | --- | --- | --- | --- |
| data | 需要编码的数据,内容变化时码图实时刷新 | String | `''` | - |
| type | 码图类型(`MULTI_FUNCTIONAL` 仅用于扫码识别,生成码图无效) | ScanType | `'QRCODE'` | 见[下文类型](#scantype) |
| margin | 码图边框宽度 | Number | `1` | - |
| bgColor | 码图背景色(具体色值,由原生 `Color.parseColor` 解析) | String | `'#ffffff'` | - |
| frontColor | 码图前景色 | String | `'#000000'` | - |
| qrErrorLevel | QR 码容错级别,仅对 QR 码生效 | String | `'M'` | `'L'` \| `'M'` \| `'Q'` \| `'H'` |
| qrLogo | QR 码中部 Logo 图片路径(支持项目内路径 / 绝对路径 / `file://`),仅 QR 码生效 | String | `''` | - |
| customStyle | 根节点自定义样式 | SnStyleValue | `''` | - |
| customClass | 根节点外部样式类 | String | `''` | - |
## 方法
| 名称 | 参数 | 返回值 | 描述 |
| --- | --- | --- | --- |
| refresh | - | - | 手动触发重新生成码图 |
---
# ScanType
> 类型字段:ScanType(见 https://sinleui.pages.dev/api/types/component#scantype)
> 类型字段:ScanTypes(见 https://sinleui.pages.dev/api/types/component#scantypes)
> 类型字段:ScanTitleType(见 https://sinleui.pages.dev/api/types/component#scantitletype)
> 类型字段:ScanConfigs(见 https://sinleui.pages.dev/api/types/component#scanconfigs)
> 类型字段:ScanResultFormat(见 https://sinleui.pages.dev/api/types/component#scanresultformat)
> 类型字段:ScanResult(见 https://sinleui.pages.dev/api/types/component#scanresult)
## 环境要求
- HBuilderX 5.21+,uni-app x 蒸汽模式项目。
- 插件依赖 `com.huawei.hms:scanplus:2.12.0.301` 与华为 maven 仓 https://developer.huawei.com/repo/ ,依赖变更需重新打包自定义基座后生效。
- Scan Kit 不强制要求 `agconnect-services.json`;仅当应用在 AppGallery Connect 开通了相关服务并已放置该文件时,才需额外配置 AGC 插件。
- 请确保应用未关闭硬件加速(`hardwareAccelerated` 为 `true`),否则个别机型扫码界面可能黑屏。
# Blurview 高斯模糊
> [查看 sn-e-blurview 的 2.0 版本差异](/differences/components/sn-e-blurview)
## 基础用法
毛玻璃(高斯模糊)容器,对组件背后的内容进行模糊处理。
- 插槽内的内容悬浮在毛玻璃之上,本身不会被模糊
- 一般需设置为固定或绝对定位,并配合半透明背景色,模糊效果才明显
- 圆角、宽高、边距等样式可自由定制
```vue
```
**更多演示请下载 demo 查看**
## 实现机制
不同平台与引擎下自动采用不同实现(编译期确定,运行时零开销):
| 场景 | 实现 |
| --- | --- |
| Web 等非 APP 端 | CSS `backdrop-filter: blur(radius)` |
| Android · 非蒸汽模式(VDOM) | `com.eightbitlab:blurview` + `RenderScriptBlur` 原生模糊 |
| Android · 蒸汽模式(uniVersion < 5.25) | 退化为普通 view(不引入原生代码,避免崩溃) |
| Android · 蒸汽模式(uniVersion >= 5.25) | CSS `backdrop-filter: blur(radius)` |
> 注意:Android 非蒸汽(VDOM)分支依赖 `com.eightbitlab:blurview`,使用该分支的工程需打包自定义基座。
## 属性
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
| --- | --- | --- | --- | --- |
| radius | 模糊半径(px) | Number | `15` | - |
| customStyle | 根节点自定义样式 | SnStyleValue | `''` | - |
| customClass | 根节点外部样式类 | String | `''` | - |
## 插槽
| 名称 | 说明 |
| --- | --- |
| default | 放置毛玻璃上的内容,不会被模糊处理 |
# Gesture 手势
> [查看 sn-gesture 的 2.0 版本差异](/differences/components/sn-gesture)
## 基础用法
SinleUI 手势库组件,基于 AlloyFinger 实现,Web 与 Android 均可用。
- 内置点击、双击、长按、手指按下 / 移动 / 抬起 / 打断、双指缩放与滑动等手势识别
- 事件回调返回框架定义的具名类型,而非普通对象
```vue
内容
```
**更多演示请下载 demo 查看**
## 属性
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
| --- | --- | --- | --- | --- |
| customStyle | 自定义根节点样式 | SnStyleValue | - | - |
| customClass | 自定义根节点类名 | String | - | - |
## 事件
| 名称 | 类型 | 说明 |
| --- | --- | --- |
| click | (event: `SnPointerEvent`) => Void | 单击事件 |
| dbclick | (event: `SnPointerEvent`) => Void | 双击事件(250ms 内两次点击且位移小于阈值) |
| longpress | (event: `SnTouchEvent`) => Void | 长按事件(按下 750ms 触发) |
| touchstart | (event: `SnTouchEvent`) => Void | 手指落下事件 |
| touchmove | (event: `SnTouchEvent`) => Void | 手指移动事件 |
| touchend | (event: `SnTouchEvent`) => Void | 手指抬起事件 |
| touchcancel | (event: `SnTouchEvent`) => Void | 触摸打断事件 |
| scale | (event: `SnScaleEvent`) => Void | 双指缩放事件 |
| fling | (event: `SnFlingEvent`) => Void | 滑动事件(位移超过阈值触发) |
> 类型字段:SnPointerEvent(见 https://sinleui.pages.dev/api/types/component#snpointerevent)
> 类型字段:SnTouchEvent(见 https://sinleui.pages.dev/api/types/component#sntouchevent)
> 类型字段:SnScaleEvent(见 https://sinleui.pages.dev/api/types/component#snscaleevent)
> 类型字段:SnFlingEvent(见 https://sinleui.pages.dev/api/types/component#snflingevent)
## 插槽
| 名称 | 说明 |
| --- | --- |
| default | 放置手势监听区域内的内容 |
## 类型
> 类型字段:SnTouch(见 https://sinleui.pages.dev/api/types/component#sntouch)
# Markdown 富文本
> [查看 sn-e-markdown 的 2.0 版本差异](/differences/components/sn-e-markdown)
## 基础用法
Markdown 渲染组件,Web 端与 Android 端使用各自的解析与渲染引擎。
- 支持标题、列表、表格、引用、代码块等基础 Markdown 语法
- 内置上标 / 下标 / 高亮、自定义容器、脚注、数学公式、任务列表与 Emoji 等扩展语法
- 两端语法保持一致
::: info 平台差异
- Web 端使用 UTS 移植的 markdown-it 解析引擎(含插件机制)渲染为 HTML;
- Android 端使用 Markwon 原生库渲染为原生 TextView(链接可点击);
:::
::: details 支持的完整语法
- 支持基础 Markdown:标题(ATX / Setext)、段落、强调(粗体 / 斜体 / 粗斜体)、删除线、有序 / 无序 / 嵌套列表、链接(行内 / 引用式 / 自动链接)、图片、行内代码、代码块、表格(含对齐)、引用(含嵌套)、分割线、转义、硬换行。
- 内置扩展语法:上标 `x^2^`、下标 `H~2~O`、标记 `==高亮==`、自定义容器 `::: tip 标题`(支持嵌套)、对齐 `::: center`(left / center / right / justify)、脚注 `[^label]` 与 `^[行内脚注]`、数学公式 `$e^{i\pi}$` / `$$公式$$`(KaTeX 语法,轻量等宽渲染)、GFM 任务列表 `- [ ]` / `- [x]`、Emoji(直接 Unicode 与 `:smile:` 等常见短码自动替换)以及多语言代码高亮(js / ts / uts / uvue / ucss / html / xml / vue / svg / css / scss / less / json / yaml / python / java / kotlin / c / cpp / go / bash / php / powershell / rust / swift / lua / c# / r / perl / objective-c / sql)。
:::
```vue
```
**更多演示请下载 demo 查看**
## 自定义样式
通过 `baseFontSize` 控制基础字号(标题、代码等按比例缩放),`lineHeight` 控制行高倍数;`textColor` 与 `linkColor` 支持 `$primary`、`$text` 主题色简写及 `var(--sn-*)` 写法,留空时分别使用主题文字色与主题主色。
```vue
```
## 链接点击事件
点击 Markdown 中的链接时触发 `linkclick` 事件(Android 端同时会用系统浏览器打开链接)。
```vue
```
## 属性
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
| --- | --- | --- | --- | --- |
| text | Markdown 源文本 | String | `''` | - |
| baseFontSize | 基础字号(px),标题 / 代码等按比例缩放 | String \| Number | `15` | - |
| textColor | 正文颜色,支持 `$主题色` 简写 | String | `$text` | - |
| linkColor | 链接颜色,支持 `$主题色` 简写 | String | `$primary` | - |
| lineHeight | 行高倍数 | String \| Number | `1.6` | - |
| customStyle | 根节点自定义样式 | SnStyleValue | `''` | - |
| customClass | 根节点外部样式类 | String | `''` | - |
## 事件
| 名称 | 类型 | 说明 |
| --- | --- | --- |
| linkclick | (value: SnMarkdownLinkEvent) => Void | 点击 Markdown 链接时触发,`value.href` 为链接地址 |
## 类型
- `SnMarkdownLinkEvent`:`{ href: string }`,链接点击事件回调参数。
- `SnMarkdownOptions`:渲染配置(`text`、`baseFontSize`、`textColor`、`linkColor`、`lineHeight`),一般由组件内部使用。
> 说明:Android 端自定义容器以 Blockquote 风格呈现、对齐使用原生对齐 Span;Web 端输出更完整的样式。数学公式为轻量渲染,如需 KaTeX / JLaTeXMath 深度渲染可自行接入。
# Scan Provider 扫码核心
> [查看 sn-e-scan-provider 的 2.0 版本差异](/differences/components/sn-e-scan-provider)
## 基础用法
SinleUI 扫码插件的核心模块,基于 CameraX + ML Kit 实现摄像头预览与扫码解析,仅支持 Android 平台。
- 支持二维码、条形码全格式识别,并可返回识别点坐标
- 支持图片扫码、手势缩放、双击对焦与手电筒
- 扫码成功后停止预览并释放相机资源,继续扫描需调用方法重新启动
::: danger 必须打包自定义基座
插件使用了第三方依赖,导入插件后必须打包自定义基座后运行。
:::
::: info 自定义界面
如需自带界面的扫码场景,可参考 `sn-scan` 对本组件进行再封装。
:::
```vue
```
## 兼容性
| Web | Android |
| --- | ------- |
| × | √ |
**更多演示请下载 demo 查看**
## 属性
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
| --- | --- | --- | --- | --- |
| scanType | 扫码类型 | SnScanType | `'all'` | `'qrcode'` \| `'barcode'` \| `'all'` |
| enableDing | 是否开启扫码成功提示音 | Boolean | `true` | `true` \| `false` |
| dingFileSrc | 自定义提示音音频路径,使用内置提示音 | String | - | - |
| enableZoom | 是否允许手势缩放(捏合缩放、双击对焦并复位缩放) | Boolean | `true` | `true` \| `false` |
| initZoomScale | 初始缩放比例(线性缩放,0 ~ 1) | Number | `0` | - |
| autoStart | 组件初始化后是否自动启动相机并请求权限 | Boolean | `true` | `true` \| `false` |
| cameraPermTip | 相机权限请求说明文案 | String | ` 本应用正在请求您的相机权限,仅用于条码、二维码识别,且不会将任何数据上传至云端。如不提供此权限,则无法正常使用扫码功能。` | - |
| customStyle | 根节点自定义样式 | SnStyleValue | `''` | - |
| customClass | 根节点外部样式类 | String | `''` | - |
## 事件
| 名称 | 类型 | 说明 |
| --- | --- | --- |
| scanned | (result: SnScanResult) => Void | 扫码成功时触发,`result` 结构见[下文类型](#类型) |
| error | (error: SnScanProviderErrorImpl) => Void | 扫码出错时触发(权限被拒、相机初始化失败、图片识别失败等),错误码见[下文错误码](#错误码) |
## 方法
| 名称 | 参数 | 返回值 | 描述 |
| --- | --- | --- | --- |
| start | - | - | 启动相机开始扫码(自动请求相机权限);auto-start 为 false 时需手动调用 |
| stop | - | - | 停止扫码并释放相机资源 |
| rescan | - | - | 扫码成功画面静止后,重新启动相机继续扫描 |
| setTorchStatus | (status: boolean) | - | 设置手电筒开关状态 |
| scanImageByURI | (uri: String) | - | 识别指定图片中的一 / 二维码,相对路径会自动转为绝对路径 |
| setZoomRatio | (zoomRatio: number) | - | 设置缩放比例,自动约束在相机支持的最小 / 最大变焦范围内 |
| getZoomRatio | - | Number | 获取当前缩放比例,未启动相机时返回 1 |
## 类型
`@scanned` 事件返回 `SnScanResult` 对象,相关类型均由本插件导出:
> 类型字段:SnScanType(见 https://sinleui.pages.dev/api/types/component#snscantype)
> 类型字段:SnScanMode(见 https://sinleui.pages.dev/api/types/component#snscanmode)
> 类型字段:SnScanDataPosition(见 https://sinleui.pages.dev/api/types/component#snscandataposition)
> 类型字段:SnScanData(见 https://sinleui.pages.dev/api/types/component#snscandata)
> 类型字段:SnScanResult(见 https://sinleui.pages.dev/api/types/component#snscanresult)
```typescript
import { SnScanResult } from '@/uni_modules/sn-e-scan-provider'
```
## 错误码
`@error` 事件返回 `SnScanProviderErrorImpl`(`UniError` 子类),错误码定义:
| 错误码 | 说明 |
| --- | --- |
| 1602001 | 相机权限被拒绝 |
| 1602002 | 相机初始化失败 |
| 1602003 | 图片扫码失败 |
| 1602004 | 无效的图片 URI |
| 1602005 | 内部错误 |
# SnUI 工具库
`snu` 是 SinleUI 提供的工具库聚合门面(facade)。它把分布在多个分组静态类中的工具方法统一收敛到一个入口,使用户只需从一个地方导入即可调用全部工具方法,无需关心各方法所属的分组。
## 导入方式
```typescript
import { snu } from '@/uni_modules/sinle-ui'
// 调用示例
let id = snu.randomComId()
let rounded = snu.roundAmount('123.456', 2, 'round')
let isUrl = snu.isURL('https://example.com')
```
## 分组结构
`snu` 门面下的方法按业务/功能划分为以下分组(对应 `uni_modules/sinle-ui/core/utils/` 下的分组静态类)。组件内部通常直接导入分组类调用;用户侧则统一经 `snu` 门面调用。本页只介绍各分组的定位,具体方法清单见各分组文档。
| 分组静态类 | 模块文件 | 功能描述 | 文档 |
| --- | --- | --- | --- |
| `Random` | `random.ts` | 提供各类随机数据的生成能力,供界面开发与测试场景取用 | [Random](/libs/utils/random) |
| `Basic` | `basic.ts` | 提供节流、防抖与数值范围约束等基础控制能力,服务于高频交互与数值收窄场景 | [Basic](/libs/utils/basic) |
| `Easing` | `easing.ts` | 提供缓动函数集合,供动画与过渡的插值计算使用 | [Easing](/libs/utils/easing) |
| `ObjectUtils` | `object.ts` | 提供对象与数组的通用处理能力,覆盖数值格式化、拷贝、类型判断与元素 dataset 读写 | [ObjectUtils](/libs/utils/object) |
| `System` | `platform.ts` | 封装系统级能力(链接、提示、剪贴板、主题等),屏蔽各平台差异 | [System](/libs/utils/platform) |
| `Sort` | `sort.ts` | 提供常用排序算法的实现,供列表数据排序使用 | [Sort](/libs/utils/sort) |
| `Text` | `text.ts` | 提供文本处理能力,覆盖命名风格转换、金额处理、敏感信息脱敏与数字分段 | [Text](/libs/utils/text) |
| `Ui` | `ui.ts` | 提供界面开发辅助能力,覆盖单位换算、几何计算、节点查找与全局弹窗调用 | [Ui](/libs/utils/ui) |
| `Perm` | `perm.ts` | 负责系统权限的检查、申请、设置页跳转,以及权限提示气泡的内容配置、样式配置和申请监听 | [Perm](/libs/utils/permission) |
| `Verify` | `verify.ts` | 提供常见数据格式的合法性校验能力,覆盖日期、网络、号码、证件等类型 | [Verify](/libs/utils/verify) |
# ColorLib 颜色库
颜色库是 SinleUI 内置的一套轻量级颜色处理工具,基于 TinyColor 思路实现,提供颜色的解析、计算、格式转换、变换与配色方案生成等能力,并附带 APCA 对比度计算与基于主色的色板生成功能。
## 特性
- **统一入口**:ColorLib 静态类提供 5 个便捷静态方法;TinyColor 类可独立操作单个颜色。
- **强大解析**:支持 HEX、RGB、HSL、HSV/HSB、百分比 RGB、CSS 颜色名、数字等多种格式输入。
- **色彩变换**:提供变亮/变暗、混合、饱和度调整、色调旋转等变换方法。
- **配色方案**:内置类似色、互补色、单色、分裂互补、三色、四色等色轮配色算法。
- **可访问性**:内置 APCA 对比度计算,辅助选择可读性良好的前景/背景组合。
## 导入方式
颜色库从插件统一入口导出,可直接按需引入:
```typescript
import { ColorLib, TinyColor } from '@/uni_modules/sinle-ui'
```
- `ColorLib`:静态工具类,包含 `tinyColor`、`calcAPCA`、`generate`、`mean`、`random` 五个静态方法(详见 [methods](./methods))。
- `TinyColor`:颜色实例类,封装对单个颜色的解析、计算与变换(详见 [tinycolor](./TinyColor))。
## ColorLib 静态方法
| 名称 | 参数 | 返回值 | 描述 |
| --- | --- | --- | --- |
| tinyColor | color: any = '' / opts?: LColorOptions | TinyColor | 创建 TinyColor 实例,传入 TinyColor 时返回其克隆 |
| calcAPCA | frontColor: any / bgColor: any / round? : boolean = true | number | 计算两个颜色之间的 APCA 对比度 |
| generate | color: any / opts?: LGenerateOptions | string[] | 基于主色生成一组色板(HEX 数组) |
| mean | colors: any[] | TinyColor | 计算一组颜色的平均颜色 |
| random | - | TinyColor | 生成一个随机颜色 |
每个方法的详细说明见 [ColorLib 方法文档](./methods)。
## TinyColor 类
`TinyColor` 是一个封装单个颜色的实例类,所有计算后的方法返回新实例(不修改原对象)。主要能力包括:
- **明暗亮度**:`isDark` / `isLight` / `getBrightness` / `getLuminance` / `isMonochrome`。
- **格式输出**:`toRgb` / `toHex` / `toHsl` / `toHsv` / `toHsb` / `toRgbString` / `toHexString` / `toName` / `toNumber` 等。
- **颜色变换**:`lighten` / `darken` / `brighten` / `tint` / `shade` / `saturate` / `desaturate` / `greyscale` / `spin` / `mix` / `onBackground`。
- **色轮配色**:`analogous` / `complement` / `monochromatic` / `splitcomplement` / `triad` / `tetrad` / `polyad`。
完整方法清单见 [TinyColor 类文档](./TinyColor)。
## 类型定义
颜色库内置若干类型别名,详见 [类型定义](./types):
- `LColorOptions`:`TinyColor` 构造选项(`format`、`gradientType`)。
- `LGenerateOptions`:`ColorLib.generate` 色板生成选项(`theme`、`backgroundColor`)。
- 相关颜色结构类型:`RGB` / `RGBA` / `HSLA` / `HSVA` / `HSBA` 等。
# TinyColor 颜色实例
`TinyColor` 是颜色库中对单个颜色的实例化封装,用于颜色的解析、计算与变换。构造后可读取 r/g/b/a 等通道,并调用方法获取指定格式或完成颜色运算。
```typescript
import { TinyColor } from '@/uni_modules/sinle-ui'
let c = new TinyColor('rgb(255, 0, 0)', {})
```
实例方法按功能可分为六类:**解析与比较**(`toString` / `equals`)、**明暗与亮度**(`isDark` / `isLight` / `getBrightness` / `getLuminance` / `isMonochrome`)、**Alpha 通道**(`getAlpha` / `setAlpha`)、**格式输出**(`toRgb` / `toHex` / `toHsl` / `toHsv` / `toHsb` / `toName` / `toNumber` 等系列)、**颜色变换**(明暗与饱和度调整、混合叠加)、**色轮配色**(类似色、互补色、三角/四角色等)。除颜色变换与色轮配色类方法返回新实例(不修改原对象)外,其余方法仅读取计算或返回自身。
## 属性
以下实例属性在构造时解析填充:
| 名称 | 类型 | 描述 |
| --- | --- | --- |
| r | number | 红色通道(0-255) |
| g | number | 绿色通道(0-255) |
| b | number | 蓝色通道(0-255) |
| a | number | 透明度(0-1) |
| format | LColorFormats? | 输入颜色格式 |
| originalInput | LColorInput | 原始输入值 |
| isValid | boolean | 输入是否为有效颜色 |
| gradientType | string? | 渐变类型 |
| roundA | number | 舍入后的透明度值 |
## 方法
| 名称 | 参数 | 返回值 | 描述 |
| --- | --- | --- | --- |
| toString | format?: LColorFormats | string | 解析与比较。按指定格式输出字符串,缺省时用解析到的 format;未识别格式时回退为 `#hex` |
| equals | other?: LColorInput | boolean | 解析与比较。判断两个颜色是否相等 |
| isDark | - | boolean | 明暗与亮度。是否为深色(亮度 < 128) |
| isLight | - | boolean | 明暗与亮度。是否为浅色(!isDark) |
| getBrightness | - | number | 明暗与亮度。感知亮度(加权 RGB 亮度,0-255) |
| getLuminance | - | number | 明暗与亮度。相对亮度(WCAG 相对亮度 0-1) |
| isMonochrome | - | boolean | 明暗与亮度。是否单色(饱和度 0) |
| getAlpha | - | number | Alpha 通道。获取透明度(0-1) |
| setAlpha | alpha?: string \| number | TinyColor | Alpha 通道。设置透明度,返回自身,可链式调用 |
| toRgb | - | RGBA | 格式输出。输出 RGB 对象(r/g/b/a) |
| toRgbString | - | string | 格式输出。输出 `rgb()` / `rgba()` 字符串 |
| toPercentageRgb | - | RGBAString | 格式输出。输出百分比 RGB 对象 |
| toPercentageRgbString | - | string | 格式输出。输出百分比 `rgb()%` / `rgba()%` 字符串 |
| toHex | allow3Char = false | string | 格式输出。输出 HEX(可选 3 位缩写) |
| toHexString | allow3Char = false | string | 格式输出。输出带 `#` 的 HEX 字符串 |
| toHex8 | allow4Char = false | string | 格式输出。输出含透明度的 8 位 HEX |
| toHex8String | allow4Char = false | string | 格式输出。输出 `#` + 8 位 HEX |
| toHexShortString | allowShortChar = false | string | 格式输出。根据透明度输出 6 或 8 位 HEX |
| toHsl | - | HSLA | 格式输出。输出 HSL 对象 |
| toHslString | - | string | 格式输出。输出 `hsl()` / `hsla()` 字符串 |
| toHsv | - | HSVA | 格式输出。输出 HSV 对象 |
| toHsvString | - | string | 格式输出。输出 `hsv()` / `hsva()` 字符串 |
| toHsb | - | HSBA | 格式输出。输出 HSB 对象 |
| toHsbString | - | string | 格式输出。输出 `hsb()` / `hsba()` 字符串 |
| toName | - | string \| null | 格式输出。输出 CSS 颜色名(无对应名称时为 null) |
| toNumber | - | number | 格式输出。输出数字(0xRRGGBB) |
| lighten | amount = 10 | TinyColor | 颜色变换。提高明度(amount 为百分比数值) |
| darken | amount = 10 | TinyColor | 颜色变换。降低明度 |
| brighten | amount = 10 | TinyColor | 颜色变换。向白方向提亮 |
| tint | amount = 10 | TinyColor | 颜色变换。与白色混合 amount% |
| shade | amount = 10 | TinyColor | 颜色变换。与黑色混合 amount% |
| saturate | amount = 10 | TinyColor | 颜色变换。提高饱和度 |
| desaturate | amount = 10 | TinyColor | 颜色变换。降低饱和度 |
| greyscale | - | TinyColor | 颜色变换。转为灰度(desaturate 100) |
| spin | amount: number | TinyColor | 颜色变换。旋转色相(按角度,支持负值) |
| mix | color: LColorInput / amount = 50 | TinyColor | 颜色变换。与另一颜色按比例混合(amount 为混合比例) |
| onBackground | background: LColorInput | TinyColor | 颜色变换。将当前色叠加到背景色上(alpha 合成) |
| clone | - | TinyColor | 颜色变换。克隆当前实例 |
| analogous | results = 6 / slices = 30 | TinyColor[] | 色轮配色。类似色(相邻色相配色) |
| complement | - | TinyColor | 色轮配色。互补色(色相 +180°) |
| monochromatic | results = 6 | TinyColor[] | 色轮配色。单色系(同色相不同亮度) |
| splitcomplement | - | TinyColor[] | 色轮配色。分裂互补色(含当前色的 3 色) |
| triad | - | TinyColor[] | 色轮配色。三色配色 |
| tetrad | - | TinyColor[] | 色轮配色。四色配色 |
| polyad | n: number | TinyColor[] | 色轮配色。多色配色(按 n 均分色相环) |
> 备注:`toHexString()` 默认只取 r/g/b;含透明度时请使用 `toHex8String()` / `toHexShortString()` 获取带 alpha 的 HEX。
## 示例
```typescript
let c = new TinyColor('rgb(255, 0, 0)')
c.toString() // 'rgb(255, 0, 0)'
c.toString('hex') // '#ff0000'
c.equals('#ff0000') // true
let dark = new TinyColor('#333333')
dark.isDark() // true
dark.getBrightness() // 约 51
dark.getLuminance() // 约 0.04
let alpha = new TinyColor('#ff0000')
alpha.getAlpha() // 1
alpha.setAlpha(0.5).toString() // 返回自身,可链式调用
let rgba = new TinyColor('rgba(255, 0, 0, 0.5)')
rgba.toRgbString() // 'rgba(255, 0, 0, 0.5)'
rgba.toHexString() // 默认只取 r/g/b:'#ff0000'
rgba.toHslString() // 'hsla(0, 100%, 50%, 0.5)'
rgba.toName() // null(含透明度时无颜色名)
let base = new TinyColor('#1890ff')
base.lighten(20) // 变亮
base.darken(10) // 变暗
base.saturate(20) // 更饱和
base.spin(120) // 色相旋转 120°
base.mix('#0000ff', 50) // 与蓝色各半混合
base.onBackground('#ffffff') // 叠加到白色背景
base.clone() // 克隆实例
let wheel = new TinyColor('#ff0000')
wheel.complement() // 青色
wheel.analogous() // 6 个类似色
wheel.triad() // 3 个三色配色
wheel.polyad(5) // 5 个均分布配色
wheel.splitcomplement() // 3 个分裂互补色
wheel.monochromatic() // 6 个单色系
```
# LColorOptions
### **TinyColor 构造选项**
`TinyColor` 构造函数与 `ColorLib.tinyColor()` 方法可接收的选项对象,用于指定颜色格式与渐变类型。
| 字段 | 类型 | 描述 |
| --- | --- | --- |
| format | LColorFormats? | 输入颜色的格式,影响 `toString()` 的默认输出 |
| gradientType | string? | 渐变类型描述 |
`format` 可选值与含义:
| 值 | 含义 |
| --- | --- |
| rgb | RGB 格式(rgb()/rgba()) |
| prgb | 百分比 RGB 格式 |
| hex | HEX 格式 |
| hex3 | 3/4/6/8 位 HEX 格式 |
| hex4 | 3/4/6/8 位 HEX 格式 |
| hex6 | 3/4/6/8 位 HEX 格式 |
| hex8 | 3/4/6/8 位 HEX 格式 |
| name | CSS 颜色名 |
| hsl | HSL 格式 |
| hsv | HSV 格式 |
| hsb | HSB 格式(与 HSV 同义) |
---
# LGenerateOptions
### **色板生成选项**
`ColorLib.generate()` 方法可接收的选项对象,用于控制色板主题与暗色背景。
| 字段 | 类型 | 描述 |
| --- | --- | --- |
| theme | 'dark' \| 'default'? | 色板主题:`'default'` 返回常规色阶;`'dark'` 返回适配暗色背景的色阶 |
| backgroundColor | string? | 暗色主题下混合用的背景色(默认 `'#141414'`) |
> 说明:`backgroundColor` 仅在 `theme: 'dark'` 时参与计算,用于将色阶与所选背景色混合。
# 日期库 Date
SinleUI 内置的日期/时间处理库,基于 uni-app x 原生能力构建,提供日期解析、格式化、加减、区间计算、相对时间、国际化等能力。整个库分为三层:
- **`Dayuts` 类**:核心日期实例,封装所有日期运算与格式化方法。
- **`dayuts()` 工厂函数**:创建 `Dayuts` 实例的入口,支持多种日期入参。
- **`DateLib` 静态工具类**:提供 `toDate`/`fmtDate`/`now`/`today`/`weeks` 等面向业务场景的便捷方法。
- **`dayutsIntl`**:语言注册与切换的国际化管理器,内置 `en`、`zh-cn` 两套语言。
## 导出项
| 导出名 | 类型 | 说明 |
| --- | --- | --- |
| `Dayuts` | 类 | 日期实例类,含全部日期运算与格式化方法 |
| `dayuts` | 函数 | 工厂函数,创建 `Dayuts` 实例 |
| `isDayuts` | 函数 | 判断传入值是否为 `Dayuts` 实例 |
| `dayutsIntl` | 对象 | 国际化管理器(语言注册/切换) |
| `DateLib` | 类 | 静态日期工具类 |
| `DayutsConfig` | 类型 | 创建实例的配置对象类型 |
| `DayutsUnit` | 类型 | 时间单位联合类型 |
| `DayutsFormats` | 类型 | 本地化格式模板类型 |
| `DayutsRelativeTime` | 类型 | 相对时间文案类型 |
| `DayutsLocale` | 类型 | 语言包类型 |
| `DayutsObject` | 类型 | `toObject()` 返回的对象类型 |
## 导入方式
```typescript
import {
Dayuts,
dayuts,
isDayuts,
dayutsIntl,
DateLib
} from '@/uni_modules/sinle-ui'
```
## 基本用法
### 创建实例
```typescript
const now = dayuts() // 当前时间
const d1 = dayuts('2024-05-20 10:30:00') // 解析日期字符串
const d2 = dayuts(1716191400000) // 时间戳(毫秒)
const d3 = dayuts([2024, 5, 20, 10, 30, 0]) // 数组 [年, 月, 日, 时, 分, 秒]
const d4 = dayuts('2024-05-20', 'YYYY-MM-DD', 'zh-cn') // 指定格式与语言
```
### 格式化
```typescript
const d = dayuts('2024-05-20 10:30:00', undefined, 'zh-cn')
d.format('YYYY-MM-DD HH:mm:ss') // "2024-05-20 10:30:00"
d.format('YYYY年M月D日 dddd') // "2024年5月20日 星期一"
```
### 加减与区间
```typescript
const d = dayuts('2024-05-20')
d.add(3, 'day') // 2024-05-23
d.subtract(1, 'month') // 2024-04-20
d.startOf('week') // 本周一(zh-cn 语言下周一为周起始)
d.endOf('month') // 2024-05-31
```
### 相对时间
```typescript
const d = dayuts().subtract(3, 'day')
d.fromNow(true) // "3 天"(zh-cn 语言,不带前后缀)
d.fromNow() // "3 天前"
```
### 工具方法
```typescript
const lib = new DateLib()
lib.now() // "2024-05-20 10:30:00"
lib.today(-1) // 昨天 "2024-05-19"
lib.toDate('2024-05-20') // Date 对象
lib.fmtDate('2024-05-20', 'yyyy年MM月dd日') // "2024年05月20日"
```
## 语言
库默认语言为 `en`,内置 `zh-cn`。可通过 `dayutsIntl.locale` 切换全局默认语言,也可在创建实例时通过第三个参数指定语言。
```typescript
dayutsIntl.locale = 'zh-cn'
dayuts('2024-05-20').format('YYYY年MM月DD日') // "2024年05月20日"
```
# 日期库 Dayuts
`Dayuts` 是 SinleUI 日期库的核心实例类,封装了日期解析、格式化、读取/设置、加减运算、区间计算、相对时间、类型转换与本地化等全部能力。推荐通过 `dayuts()` 工厂函数创建实例,而非直接 `new Dayuts()`。
```typescript
import { dayuts, Dayuts, isDayuts } from '@/uni_modules/sinle-ui'
```
实例方法按功能可分为七类:**创建与克隆**(`clone`)、**有效性判断**(`isValid` / `isSame` / `isAfter` / `isBefore` / `isSameOrBefore` / `isSameOrAfter` / `isBetween` / `isLeapYear` / `isToday` / `unix` / `utcOffset`)、**格式化**(`format`)、**读取与设置**(`get` / `set` / `year` / `month` / `day` / `date` / `hour` / `minute` / `second` / `millisecond` / `dayOfYear` / `daysInMonth`)、**加减与区间边界**(`add` / `subtract` / `startOf` / `endOf`)、**时间差与相对时间**(`diff` / `from` / `to` / `fromNow` / `toNow`)、**类型转换与本地化**(`toDate` / `toJSON` / `toISOString` / `toObject` / `toArray` / `valueOf` / `toString` / `locale`)。所有返回新实例的方法均不修改原实例。
---
# Dayuts
### 属性
| 名称 | 类型 | 只读 | 描述 |
| :--- | :--- | ---- | :--- |
| $L | String | 否 | 当前实例使用的语言名(如 `'en'`、`'zh-cn'`) |
### 方法
| 名称 | 参数 | 返回值 | 描述 |
| :--- | :--- | :--- | :--- |
| clone | - | Dayuts | 创建与克隆。返回当前实例的深拷贝,共享相同的时间戳与语言 |
| isValid | - | Boolean | 有效性判断。是否为有效日期,解析失败(如无法识别的字符串)时无效 |
| isSame | input: any, units: DayutsUnit = `'millisecond'` | Boolean | 有效性判断。按指定时间单位判断是否与目标时间处于同一区间,未传单位时按毫秒精确比较;目标值支持 `string` / `Number` / `Date` / `Dayuts` / 普通对象 |
| isAfter | input: any, units: DayutsUnit = `'millisecond'` | Boolean | 有效性判断。当前实例是否晚于目标时间 |
| isBefore | input: any, units: DayutsUnit = `'millisecond'` | Boolean | 有效性判断。当前实例是否早于目标时间 |
| isSameOrBefore | input: any, units: DayutsUnit = `'millisecond'` | Boolean | 有效性判断。是否相同于或早于目标时间(`isSame \|\| isBefore`) |
| isSameOrAfter | input: any, units: DayutsUnit = `'millisecond'` | Boolean | 有效性判断。是否相同于或晚于目标时间(`isSame \|\| isAfter`) |
| isBetween | input: any, input2: any, units: DayutsUnit = `'millisecond'`, interval: String = `'()'` | Boolean | 有效性判断。是否落在 `input` 与 `input2` 构成的区间内;`interval` 遵循数学区间记法:`'('` / `')'` 开区间(不含端点)、`'['` / `']'` 闭区间(含端点) |
| isLeapYear | - | Boolean | 有效性判断。所在年份是否为闰年 |
| isToday | - | Boolean | 有效性判断。日期部分(`YYYY-MM-DD`)是否与今天相同 |
| unix | - | Number | 有效性判断。Unix 秒级时间戳(`Math.floor(毫秒值 / 1000)`) |
| utcOffset | - | Number | 有效性判断。相对 UTC 的分钟偏移量;Web 端由 `getTimezoneOffset` 计算,APP-ANDROID / APP-IOS 端恒为 `0` |
| format | formatStr: string \| null = `'YYYY-MM-DDTHH:mm:ssZ'` | String | 格式化。按格式模板输出字符串,模板中英文字母识别为 token(详见 [format 模板说明](./format)),可使用中文作为字面量;无效日期返回 `'Invalid Date'` |
| get | units: DayutsUnit | Number | 读取与设置。按时间单位读取对应数值,如 `'year'` / `'month'` / `'day'` / `'date'` / `'hour'` / `'minute'` / `'second'` / `'millisecond'` / `'week'` |
| set | units: DayutsUnit, int: Number | Dayuts | 读取与设置。设置指定时间单位的值,返回新实例 |
| year / month / date / day / hour / minute / second / millisecond | 无参读取 / 传参写入 | Number / Dayuts | 读取与设置。同名读写方法:不传参数返回对应单位数值,传参设置并返回新实例。注意 `day()` 读的是星期几(0 起,0=周日),`date()` 读的是日(1 起),`month()` 月份 0 起 |
| dayOfYear | input: number \| null = null | Number / Dayuts | 读取与设置。不传参数返回当年第几天(1 起),传参设置并返回新实例 |
| daysInMonth | - | Number | 读取与设置。当月总天数 |
| add | number: Number, units: DayutsUnit | Dayuts | 加减与区间边界。增加指定数量的时间单位,返回新实例;如 `add(1, 'month')` 自动封顶到月末 |
| subtract | number: Number, units: DayutsUnit | Dayuts | 加减与区间边界。减少指定数量的时间单位,等价于 `add(number * -1, units)` |
| startOf | units: DayutsUnit, startOf: Boolean = `true` | Dayuts | 加减与区间边界。归一到指定单位的起始点(`startOf` 为 `false` 时取终点),支持 `year` / `month` / `week` / `day` / `hour` / `minute` / `second` 等,周以语言配置的 `weekStart` 为起始(zh-cn 为周一) |
| endOf | units: DayutsUnit | Dayuts | 加减与区间边界。归一到指定单位的结束点,等价于 `startOf(units, false)` |
| diff | input: any, units: DayutsUnit = `'millisecond'`, float: Boolean = `false` | Number | 时间差。计算与目标时间的差值;月份差按日历月、年份差按 12 个月计算,其余单位按毫秒差转换;`float` 为 `true` 时返回浮点值,否则取整 |
| from | input: any, withoutSuffix: Boolean = `false` | String | 相对时间。返回相对目标时间的人类可读描述,`withoutSuffix` 为 `true` 时省略「前 / 后」等前后缀,文案随语言变化(zh-cn 如 `"3 天前"`) |
| to | input: any, withoutSuffix: Boolean = `false` | String | 相对时间。从目标时间视角描述当前实例,语义与 `from` 相反 |
| fromNow | withoutSuffix: Boolean = `false` | String | 相对时间。描述当前实例相对此刻的时间(等价于 `from(dayuts(), withoutSuffix)`) |
| toNow | withoutSuffix: Boolean = `false` | String | 相对时间。描述从现在到当前实例的相对时间(等价于 `to(dayuts(), withoutSuffix)`) |
| toDate | - | Date | 类型转换。返回对应的原生 `Date` 对象(新实例,互不影响) |
| toObject | - | DayutsObject | 类型转换。返回含各时间单位字段的 `DayutsObject` 对象 |
| toArray | - | Number[] | 类型转换。返回 `[年, 月(0起), 日, 时, 分, 秒, 毫秒]` 数值数组 |
| valueOf | - | Number | 类型转换。毫秒时间戳(`getTime()`) |
| toISOString | - | String | 类型转换。ISO 8601 字符串;Web 端为标准 `toISOString()`,APP-ANDROID / APP-IOS 端返回 `Date.toString()` |
| toJSON | - | String \| null | 类型转换。有效日期返回 ISO 字符串(等价于 `toISOString()`),无效日期返回 `null` |
| toString | - | String | 类型转换。返回 `Date.toString()` 字符串表示 |
| locale | preset: string \| DayutsLocale, object: DayutsLocale \| null = null | Dayuts | 本地化。以当前实例为基础返回指定语言副本;`preset` 为已注册语言名或语言包对象,`object` 为配套语言包(传字符串语言名时可选) |
### 示例
```typescript
const d = dayuts('2024-05-20 15:30:00')
d.clone() // 克隆实例
d.isValid() // true
d.isSame('2024-05-20 20:00:00', 'day') // true
d.isAfter('2024-05-19') // true
d.isBetween('2024-05-19', '2024-05-21', 'day', '[)') // true
d.format('YYYY年M月D日 dddd') // "2024年5月20日 星期一"
d.get('year') // 2024
d.month() // 4(0 起,5 月为 4)
d.day() // 1(周一)
d.date() // 20
d.hour(22) // 2024-05-20 22:30:00
d.add(1, 'month') // 2024-06-20
d.subtract(1, 'month') // 2024-04-20
d.startOf('day') // 2024-05-20 00:00:00
d.endOf('month') // 2024-05-31 23:59:59.999
dayuts('2024-05-23').diff('2024-05-20', 'day') // 3
d.from('2024-05-23') // "3 天前"
d.subtract(3, 'day').fromNow() // "3 天前"
d.toArray() // [2024, 4, 20, 15, 30, 0, 0]
d.valueOf() // 毫秒时间戳
dayuts('2024-05-20').locale('zh-cn').format('dddd') // "星期一"
dayuts('2020-01-01').isLeapYear() // true
dayuts().isToday() // true
dayuts('2024-05-20').unix() // 1716163200
dayuts('2024-02-01').daysInMonth() // 29
dayuts('2024-01-01').dayOfYear() // 1
```
---
# dayuts()
### **创建 Dayuts 实例**
工厂函数,根据传入的日期值创建一个新的 `Dayuts` 实例。支持字符串、时间戳、日期数组、原生 `Date`、普通对象、`Dayuts` 及空值(当前时间)等多种入参。若传入的是 `Dayuts` 实例,则返回其克隆。
原生端(APP-ANDROID / APP-IOS)`fact.format` 参数不生效;Web 端 `format` 参数参与字符串解析。
### 属性
| 名称 | 类型 | 必备 | 默认值 | 描述 |
| ---- | ---- | ---- | ------ | ---- |
| date | any \| null | 否 | `null` | 日期值。支持 `string`、`Date`、`Number`(毫秒时间戳)、日期数组、普通对象、`Dayuts`;为 `null` 时取当前时间 |
| format | string \| null | 否 | `null` | 解析格式(仅 Web 端生效) |
| locale | string \| null | 否 | `null` | 指定实例语言,未指定时使用全局默认语言 |
### 返回值
| 类型 | 必备 | 描述 |
| ---- | ---- | ---- |
| Dayuts | 是 | 返回一个 `Dayuts` 实例 |
### 示例
```typescript
dayuts() // 当前时间
dayuts('2024-05-20 10:30:00') // 解析日期字符串
dayuts(1716191400000) // 毫秒时间戳
dayuts([2024, 5, 20, 10, 30, 0]) // [年, 月, 日, 时, 分, 秒]
dayuts('2024-05-20', 'YYYY-MM-DD') // 指定格式(Web 端)
dayuts('2024-05-20', undefined, 'zh-cn') // 指定语言
```
---
# isDayuts()
### **判断是否 Dayuts 实例**
判断传入值是否为 `Dayuts` 实例。
### 属性
| 名称 | 类型 | 必备 | 默认值 | 描述 |
| ---- | ---- | ---- | ------ | ---- |
| date | any \| null | 否 | `null` | 待判断的值 |
### 返回值
| 类型 | 必备 | 描述 |
| ---- | ---- | ---- |
| Boolean | 是 | 是 `Dayuts` 实例返回 `true`,否则 `false` |
### 示例
```typescript
isDayuts(dayuts()) // true
isDayuts('2024') // false
```
# format 格式模板说明
`Dayuts.format(formatStr)` 通过格式模板将日期渲染为字符串。模板中的英文字母序列会被识别为 token,其余字符(中文、`-`、` `、`:`、`/`、`年` 等)作为原样字面量输出。
未传模板时使用默认模板 `'YYYY-MM-DDTHH:mm:ssZ'`。
同一种 token 的不同长度控制补零(`MM`/`MM`)与完整/缩写形式(`MMMM`/`MMM`)等细节,具体见下表。以下示例均以 `2024-05-20 15:03:07`(zh-cn 语言,周一)为例。
## Token 表
### 年 Y
| Token | 输出示例 | 说明 |
| --- | --- | --- |
| `YYYY` | `2024` | 4 位年份,不足补 0 |
| `YY` | `24` | 年份后两位 |
### 月 M
| Token | 输出示例 | 说明 |
| --- | --- | --- |
| `MMMM` | `五月` | 月份全名(zh-cn 为 `五月`,en 为 `May`) |
| `MMM` | `5月` | 月份缩写,取全名后 3 位 / 本地化缩写 |
| `MM` | `05` | 2 位月份,不足补 0 |
| `M` | `5` | 月份,不补 0 |
### 日 DD 与星期 d
| Token | 输出示例 | 说明 |
| --- | --- | --- |
| `DD` | `20` | 2 位日期,不足补 0 |
| `D` | `20` | 日期,不补 0 |
| `dddd` | `星期一` | 星期全名 |
| `ddd` | `周一` | 星期缩写 |
| `dd` | `一` | 星期最小形式 |
| `d` | `1` | 星期几数字(`getDay()`,0=周日,6=周六) |
### 时 24 小时制 H 与 12 小时制 h
| Token | 输出示例 | 说明 |
| --- | --- | --- |
| `HH` | `15` | 24 小时制,不足补 0 |
| `H` | `15` | 24 小时制,不补 0 |
| `hh` | `03` | 12 小时制(`${H % 12 == 0 ? 12 : H % 12}`),不足补 0 |
| `h` | `3` | 12 小时制,不补 0 |
### 分 m、秒 s、毫秒 SSS
| Token | 输出示例 | 说明 |
| --- | --- | --- |
| `mm` | `03` | 分钟,不足补 0 |
| `m` | `3` | 分钟,不补 0 |
| `ss` | `07` | 秒,不足补 0 |
| `s` | `7` | 秒,不补 0 |
| `SSS` | `007` | 毫秒,3 位补 0 |
### 上午/下午 A a
| Token | 输出示例 | 说明 |
| --- | --- | --- |
| `A` | `下午` | 上午/下午,随语言变化(en 为 `AM`/`PM`) |
| `a` | `下午` | 上午/下午小写形式(en 为 `am`/`pm`) |
zh-cn 语言的 `A`/`a` 按时间段输出本地称谓:凌晨(<6点)、早上(<9点)、上午(<11点)、中午(<13点)、下午(<18点)、晚上(其余)。
### 时区 Z
| Token | 输出示例 | 说明 |
| --- | --- | --- |
| `Z` | `+08:00` | UTC 偏移,格式 `±HH:mm`(如 `+08:00`、`-05:00`) |
### 转义 [ ]
在模板中使用 `[方括号]` 包裹的内容按字面量输出,不参与 token 解析。
| Token | 输出示例 | 说明 |
| --- | --- | --- |
| `[YYYY]` | `YYYY` | 方括号内按字面量输出 |
## 用法示例
```typescript
const d = dayuts('2024-05-20 15:03:07', undefined, 'zh-cn')
d.format('YYYY-MM-DD HH:mm:ss') // "2024-05-20 15:03:07"
d.format('YYYY年M月D日 dddd') // "2024年5月20日 星期一"
d.format('MM/DD [Year] YYYY') // "05/20 Year 2024"
d.format('YYYY-MM-DDTHH:mm:ssZ') // "2024-05-20T15:03:07+08:00"
d.format('hh:mm a') // "03:07 下午"
```
## 与 DateLib.fmtDate 的区别
> 注意:`DateLib.fmtDate` 使用另一套**小写** token 体系(`y`/`M`/`d`/`H`/`m`/`s`),默认模板为 `'yyyy-MM-dd'`,并额外支持在模板中出现 `周`/`星期`/`礼拜` 时追加星期文案。两套 token 互不通用,详见 [DateLib 方法](./methods.md)。
# 日期库 dayutsIntl
`dayutsIntl` 是日期库的国际化管理器,负责语言包的注册与全局默认语言的切换。库内置 `en`(默认)与 `zh-cn` 两套语言包,除通过 `dayutsIntl` 管理外,也可在创建实例时用第三个参数临时指定语言,或用 `Dayuts.locale()` 为单个实例切换语言。
```typescript
import { dayutsIntl } from '@/uni_modules/sinle-ui'
```
---
# DayutsIntl
全局单例 `dayutsIntl` 为 `DayutsIntl` 类的实例。
### 属性
| 名称 | 类型 | 只读 | 描述 |
| :--- | :--- | ---- | :--- |
| locale | String | 否 | 全局默认语言名,读取当前语言,赋值即切换全局语言 |
> 说明:`locale` 是 `DayutsIntl` 的读/写属性。读取返回当前默认语言(初始为 `'en'`);赋值时若该语言已注册则切换为默认语言,若未注册则打印警告并列出已注册语言、不生效。
### 方法
| 名称 | 参数 | 返回值 | 描述 |
| ---- | ---- | ------ | ---- |
| `use` | (locale: DayutsLocale) | DayutsIntl | 注册一个语言包,返回自身以支持链式调用 |
| `set` | (name: string, locale: DayutsLocale) | Void | 以指定名称注册一个语言包 |
| `has` | (name: string) | Boolean | 判断指定语言是否已注册 |
---
# dayutsIntl.use()
### **注册语言包**
注册一个 `DayutsLocale` 语言包,以该语言包的 `name` 字段作为注册名,返回 `dayutsIntl` 自身以便链式调用。注册后可通过 `locale` 赋值或 `locale()` 使用。
### 属性
| 名称 | 类型 | 必备 | 默认值 | 描述 |
| ---- | ---- | ---- | ------ | ---- |
| locale | DayutsLocale | 是 | - | 语言包对象,含 `name` 及各文案字段 |
### 返回值
| 类型 | 必备 | 描述 |
| ---- | ---- | ---- |
| DayutsIntl | 是 | 返回自身(支持链式调用) |
### 示例
```typescript
dayutsIntl.use({
name: 'zh-tw',
weekdays: ['星期日', ...],
months: [...],
ordinal: (n: number, period: string): string => `${n}日`
} as DayutsLocale)
```
---
# dayutsIntl.set()
### **按名称注册语言包**
以显式传入的名称注册一个语言包(`name` 参数不必与语言包内 `name` 字段一致)。
### 属性
| 名称 | 类型 | 必备 | 默认值 | 描述 |
| ---- | ---- | ---- | ------ | ---- |
| name | String | 是 | - | 注册使用的语言名 |
| locale | DayutsLocale | 是 | - | 语言包对象 |
### 返回值
无
### 示例
```typescript
dayutsIntl.set('zh-tw', zhTwLocale)
```
---
# dayutsIntl.has()
### **判断语言是否已注册**
判断指定语言名是否已在 `dayutsIntl` 中注册。
### 属性
| 名称 | 类型 | 必备 | 默认值 | 描述 |
| ---- | ---- | ---- | ------ | ---- |
| name | String | 是 | - | 语言名 |
### 返回值
| 类型 | 必备 | 描述 |
| ---- | ---- | ---- |
| Boolean | 是 | 已注册返回 `true`,否则 `false` |
### 示例
```typescript
dayutsIntl.has('en') // true
dayutsIntl.has('zh-cn') // true
dayutsIntl.has('ja') // false
```
---
# dayutsIntl.locale(属性)
### **切换全局默认语言**
读取当前默认语言,或通过赋值切换默认语言。仅当目标语言已注册时切换生效。
### 示例
```typescript
dayutsIntl.locale // "en"(初始)
dayutsIntl.locale = 'zh-cn' // 切换全局默认语言为中文
dayuts('2024-05-20').format('YYYY年M月D日') // "2024年5月20日"
```
## 内置语言包
| 语言名 | 说明 |
| --- | --- |
| `en` | 英文(默认语言) |
| `zh-cn` | 简体中文 |
# 日期库 类型定义
本篇列出日期库导出的全部类型定义。类型从 `@/uni_modules/sinle-ui` 导入:
```typescript
import type {
DayutsConfig,
DayutsUnit,
DayutsFormats,
DayutsRelativeTime,
DayutsLocale,
DayutsObject
} from '@/uni_modules/sinle-ui'
```
---
# DayutsConfig
创建 `Dayuts` 实例时使用的配置对象类型。
| 字段 | 类型 | 描述 |
| --- | --- | --- |
| date | any \| null | 日期值,支持 `string`/`Date`/`Number`/数组/普通对象/`Dayuts`;`null` 表示当前时间 |
| format | string \| null | 解析格式(仅 Web 端生效) |
| locale | string \| null | 实例语言名 |
---
# DayutsUnit
时间单位联合类型,用于 `add`/`subtract`/`diff`/`startOf`/`endOf`/`get`/`set` 等方法。
值为以下字符串之一:
- `'year'` — 年
- `'month'` — 月
- `'day'` — 日
- `'week'` — 周
- `'date'` — 日期(同日)
- `'hour'` — 时
- `'minute'` — 分
- `'second'` — 秒
- `'millisecond'` — 毫秒
- `'quarter'` — 季度
> 在方法调用时也接受对应单字符别名(如 `'y'`·`'M'`·`'d'`·`'w'`·`'h'`·`'m'`·`'s'`·`'ms'`·`'Q'`),并自动忽略末尾的 `s`。
---
# DayutsFormats
本地化预设格式模板类型,供语言包 `formats` 字段使用。
| 字段 | 类型 | 描述 |
| --- | --- | --- |
| LT | String | 时间格式,如 `HH:mm` |
| LTS | String | 带秒时间格式,如 `HH:mm:ss` |
| L | String | 短日期格式,如 `YYYY/MM/DD` |
| LL | String | 长日期格式,如 `YYYY年M月D日` |
| LLL | String | 长日期+时间格式,如 `YYYY年M月D日Ah点mm分` |
| LLLL | String | 完整日期+时间格式,如 `YYYY年M月D日ddddAh点mm分` |
| l | String | 更短日期格式,如 `YYYY/M/D` |
| ll | String | 精简长日期格式 |
| lll | String | 精简长日期+时间格式 |
| llll | String | 精简完整日期+时间格式 |
---
# DayutsRelativeTime
相对时间文案类型,供语言包 `relativeTime` 字段使用。除 `future`/`past` 外,各字段可使用 `%d` 占位符表示数字。
| 字段 | 类型 | 描述 |
| --- | --- | --- |
| future | String | 未来时间前缀模板,如 `in %s` / `%s内` |
| past | String | 过去时间前缀模板,如 `%s ago` / `%s前` |
| s | String | 几秒(`a few seconds` / `几秒`) |
| m | String | 1 分钟 |
| mm | String | 多分钟,如 `%d minutes` / `%d 分钟` |
| h | String | 1 小时 |
| hh | String | 多小时 |
| d | String | 1 天 |
| dd | String | 多天 |
| M | String | 1 个月 |
| MM | String | 多个月 |
| y | String | 1 年 |
| yy | String | 多年 |
---
# DayutsLocale
语言包类型,传入 `dayutsIntl.use()` / `dayutsIntl.set()` 或 `Dayuts.locale()` 使用。
| 字段 | 类型 | 描述 |
| --- | --- | --- |
| name | String | 语言名(注册名) |
| weekdays | String[] | 星期全名数组(7 项,周日起始) |
| weekdaysShort? | String[] | 星期缩写数组 |
| weekdaysMin? | String[] | 星期最小形式数组 |
| months | String[] | 月份全名数组(12 项) |
| monthsShort? | String[] | 月份缩写数组 |
| ordinal | (number: Number, period: String) => String | 序数格式化函数 |
| weekStart? | Number | 周起始日(0=周日),如 zh-cn 为 `1`(周一) |
| yearStart? | Number | 年初所在周(1-4 月),如 zh-cn 为 `4` |
| formats? | [DayutsFormats](#dayutsformats) | 预设格式模板 |
| relativeTime? | [DayutsRelativeTime](#dayutsrelativetime) | 相对时间文案 |
| meridiem? | (hour: Number, minute: Number, isLowercase: Boolean) => String | 上午/下午文案函数 |
---
# DayutsObject
`Dayuts.toObject()` 的返回类型。
| 字段 | 类型 | 描述 |
| --- | --- | --- |
| years | Number | 年 |
| months | Number | 月(0 起) |
| date | Number | 日 |
| hours | Number | 时 |
| minutes | Number | 分 |
| seconds | Number | 秒 |
| milliseconds | Number | 毫秒 |
# Store 状态管理库
一个轻量简洁的全局响应式状态管理库。以键值对形式存储应用状态,支持**持久化存储**(重启后恢复)与**过期机制**(自动清理失效数据),并提供变更订阅能力。框架简单状态管理无需引入 pinia,直接使用本库即可。
## 导入方式
```typescript
import { store, frameStore, StoreLib } from '@/uni_modules/sinle-ui'
```
与 `ColorLib` / `DateLib` 等核心库一致,store 不再挂载在 `$snui` 上,请直接按命名导入使用。
### 内置实例
| 实例 | storeKey | 使用场景 |
| --- | --- | --- |
| `store` | `app_store` | 应用全局状态,推荐在业务中使用 |
| `frameStore` | `sinle_ui_store` | 框架内部状态(主题、风格、灰模等),不建议业务直接使用 |
固定 Tabbar 的高度登记也保存在 `frameStore`:每个 `sn-page` 使用独立的 `tabbarHeights:<实例 uid>` 键,存储纯数值与归属记录,不持久化;页面或登记组件卸载时清理。业务通过 [useTabbarHeights](/api/hooks/use-tabbar-heights) 获得当前页面的高度字典,不直接修改内部记录。不同页面的同名 Tabbar key 互不影响。
## 快速上手
```typescript
import { store } from '@/uni_modules/sinle-ui'
// 存储数据(不持久化,仅内存响应式)
store.set('count', 10)
// 存储数据(持久化,App 重启后自动恢复)
store.set('userName', 'Aaron', true)
// 读取数据;不存在时返回 null,也可指定默认值
let name = store.get('userName')
let score = store.get('score', 0)
// 判断是否存在
let exists = store.has('userName')
// 删除数据(持久化数据会同步从本地存储移除)
store.delete('userName')
// 订阅指定键的变化,set 时收到新值,delete 时收到 null
const unsubscribe = store.subscribe('count', (value: any | null, key: string) => {
// value: 变更后的值;delete 时为 null
})
unsubscribe()
```
## 核心特性
### 响应式
数据存放在响应式存储中,页面模板或 `computed` 中读取该键时,后续对该键的修改会自动驱动界面更新,无需手动刷新:
```vue
{{ count }}
```
### 持久化(lasting)
`set(key, value, true, ...)` 将数据写入本地 Storage(基于 uni-app x 的 [storage API](https://doc.dcloud.net.cn/uni-app-x/api/storage.html))。持久化键以 `snui_store_{storeKey}_` 为前缀,不同实例互不干扰。需要移除持久化数据时调用 `delete(key)`,会同步清理本地存储。
### 过期机制(expire)
`set(key, value, lasting, expire)` 的第 4 个参数为过期秒数(`0` 表示永不过期)。过期判断采用**惰性删除**策略:仅在访问(`get` / `has` / `keys`)或初始化时检查并清理过期键,不依赖定时器,兼顾性能:
```typescript
// 设置 10 秒后过期(不持久化)。过期后 get 返回 null
store.set('captcha', '123456', false, 10)
// 已存在过期的键被重新 set 且不传过期时间时,旧过期记录会被清除,变为永不过期
store.set('captcha', '234567')
```
### 变更订阅(subscribe)
对不渲染到界面的逻辑(如接口联动、界面外状态同步),可通过 `subscribe` 监听指定键的变更。订阅返回取消函数,组件销毁时请及时取消,避免内存泄漏。
## 创建自定义实例
应用内需要多个互不干扰的存储库时,可创建新的 `StoreLib` 实例:
```typescript
import { StoreLib } from '@/uni_modules/sinle-ui'
const myStore = new StoreLib('my_own_storelib')
```
- `storeKey` 仅允许字母、数字、下划线、中划线,且不能与已有实例重复,否则创建无效并输出警告日志。
- 每个实例的持久化键、过期列表、持久化列表均独立命名空间,互不影响。
## 注意事项
- **复杂对象类型**:Storage 序列化后读取到的复杂类型为普通对象,若原值为自定义 `type` 对象,回读后需自行转换(如 `JSON.parse(JSON.stringify(obj))`,可参考 [类型数据的存取说明](https://doc.dcloud.net.cn/uni-app-x/api/storage.html#gettypedata))。
- **空字符串持久化**:持久化读取依赖同步 storage API,空字符串按「未存储」处理;请勿将空字符串作为持久化值。
- **过期时间以秒为单位**;`expire` 与 `lasting` 相互独立,可组合使用。
## 更多文档
- [用法](/libs/store/usage):典型使用场景与最佳实践
- [过期策略](/libs/store/expire):过期机制详解
- [方法](/libs/store/methods):StoreLib 全量方法说明
# Store 用法
本文档介绍 `StoreLib` 的典型使用场景与最佳实践。所有示例均以 `store`(`@/uni_modules/sinle-ui` 导出的应用级实例)演示。
## 基础存取(仅内存)
默认情况下数据只保存在内存中,适合临时状态:
```typescript
import { store } from '@/uni_modules/sinle-ui'
store.set('count', 10)
let count = store.get('count', 0) // 默认值兜底
store.delete('count')
```
## 持久化存储
需要 App 重启后依然保留的数据(用户偏好、业务配置等),将第三个参数 `lasting` 置为 `true`:
```typescript
store.set('userName', 'Aaron', true)
store.set('themePreference', 'dark', true)
// 删除时会同步清理本地存储
store.delete('userName')
```
持久化底层依赖 uni-app 的本地 [storage API](https://doc.dcloud.net.cn/uni-app-x/api/storage.html),以 `snui_store_{storeKey}_` 前缀隔离各实例,不同 `StoreLib` 之间互不干扰。
## 过期数据
一次性、有时效的数据(验证码、临时票据等)可设置过期秒数,过期后自动视为不存在:
```typescript
// 10 秒后过期
store.set('captcha', '123456', false, 10)
// 过期后返回 null(或指定的默认值)
let v = store.get('captcha')
```
过期策略的详细说明见[过期策略](/libs/store/expire)。
## 跨页面共享状态
`store` 是全局单例,任意页面读写同一键即可实现跨页面状态共享,替代手动传参或 `storage` 中转:
```vue
{{ nick }}
```
## 订阅数据变化
不依赖界面渲染的逻辑(如接口联动、缓存刷新、事件转发),可通过 `subscribe` 监听键的变更:
```typescript
const unsubscribe = store.subscribe('userInfo', (value: any | null, key: string) => {
if (value != null) {
// value 为写入的新值
refreshUser(value as UserInfo)
} else {
// 键被 delete 时 value 为 null
onUserLogout()
}
})
// 不需要时务必取消订阅
unsubscribe()
```
### 组件中使用规范
订阅返回的取消函数应在组件卸载时调用,避免内存泄漏:
```vue
```
## 独立实例管理模块状态
不同业务模块之间需要彻底隔离时,可创建专属的 `StoreLib` 实例(含独立的持久化命名空间与过期列表):
```typescript
import { StoreLib } from '@/uni_modules/sinle-ui'
const cartStore = new StoreLib('cart_store')
cartStore.set('items', [], true)
```
`storeKey` 仅允许 `[A-Za-z0-9_-]`,且不能与已有实例重名(重名或非法时创建无效并输出警告日志)。
## 与框架状态的配合
框架自身的状态(主题、风格、灰模等)已统一由 `frameStore` 管理并通过 `$snui` 暴露,业务代码直接读写 `$snui` 即可,无需操作存储细节。业务侧如需沿用框架的持久化能力,推荐使用 `store` 实例而不要直接调用 `uni.setStorageSync`。
# Store 过期策略
Store 库内置数据过期机制,用于管理验证码、临时票据、限时缓存等带时效性的数据。
## 设置过期
`set` 的第 4 个参数为过期秒数,`0`(默认)表示永不过期:
```typescript
// 10 秒后过期
store.set('captcha', '123456', false, 10)
// 30 分钟后过期的持久化数据
store.set('accessToken', token, true, 1800)
// 不传 expire,永不过期
store.set('userName', 'Aaron', true)
```
过期时间点 = 写入时刻 + `expire × 1000` 毫秒,写入后不可修改;如需调整,重新 `set` 写入新的过期时间即可。
## 惰性删除
过期判断采用**惰性删除**策略:库内不设任何定时器,仅在以下时机检查并清理过期键:
- 访问该键时(`get` / `has`)
- 遍历键名时(`keys` / `size`)
- 存储库初始化时(一次性清理全部过期项)
因此:
- 已过期的键在**被访问前仍存在于内存中**,但访问时会被清理并视为不存在;
- `get` 对过期键返回默认值(无默认值时为 `null`),`has` 返回 `false`;
- 该策略无定时器开销,适合数据量小、偶发访问的轻量状态库。
## 初始化清理
每次应用启动、`StoreLib` 实例被创建时,会先恢复持久化数据,再遍历过期列表,将已过期的键(含其持久化对应条目)一次性清除,避免过期数据在启动后被残留读取。
## 重新写入清除过期
对存在过期记录的键执行 `set` 且不带 `expire` 时,旧的过期记录会被自动清除,该键恢复为永不过期:
```typescript
store.set('captcha', '123456', false, 10)
store.set('captcha', '234567') // 清除过期记录,此后永不过期
```
只有显式传入 `expire > 0` 才重新建立过期记录。
## 持久化与过期组合
`lasting` 与 `expire` 相互独立,可自由组合:
| lasting | expire | 行为 |
| --- | --- | --- |
| `false` | 0 | 仅内存,不持久化、不过期 |
| `true` | 0 | 持久化,重启后恢复 |
| `false` | > 0 | 仅内存,存活期内可读 |
| `true` | > 0 | 持久化且有过期时间;重启后若仍在存活期内则恢复,否则清除 |
持久化 + 过期时,过期列表同样会随实例持久化保存,重启后过期判断依然生效。
## 注意事项
- 过期的清理只发生在库的访问路径上(惰性),不要依赖「立刻消失」:读取前即使已过期,也需通过 `get` / `has` / `keys` 等 API 才会触发清除。
- 过期时间不随系统时间校准;与所有本地存储一致,清理精度受应用运行生命周期影响。
- 请通过 Store 库 API 读写数据;绕过库直接操作底层 storage 键不会建立/清除过期记录。
# 更新日志
## 2.0.0(2026-09-19)
- 【重要】插件推荐运行版本为 HBuilder X Alpha 5.25 及以上(蒸汽模式在此版本之前存在比较严重的问题)
- 【重要】新增 框架全面重构为 uni-app x 蒸汽模式(vapor),VDOM 模式由于性能原因不再支持。
- 新增 多风格(Style)系统:内置 default / ink / chinese / new-year / morandi-green / orange 六套风格,支持自由修改增删内置风格,或者为应用添加自定义风格,并支持一键切换。
- 新增 五乘数体系(`fontsizeFactor` / `radiusFactor` / `marginFactor` / `paddingFactor` / `aniTimeFactor`)与三基础动画时长 `baseAniTimeShort` / `Normal` / `Long`,修改自动持久化并实时驱动页面
- 新增 `SnColorBase.shadow` 阴影色字段,随主题自动切换
- 新增 全局弹窗 `showLoading` / `hideLoading`;`showToast` 新增 `title` 兼容写法与 `passThrough` 点击穿透,`showModal` / `showActionsheet` 新增 `openAnimation` / `closeAnimation` 自定义开合动画
- 新增 `snu` 金额工具 `roundAmount` / `numToUpperAmount`(字符串级舍入,规避浮点陷阱)与全新 Resolve、Perm 方法分组
- 新增 `$snui.logging` 日志开关与 `log` / `info` / `debug` / `warn` / `error` 统一日志接口,组件内部不再直接 `console` 来报日志。
- 新增 Utils 工具库 `hideToast` 隐藏轻提示
- 新增 Utils 工具库 `clamp` 夹具函数,对所给值限制范围
- 新增 `$snui.colors` 颜色 `light`,与 `dark` 相对应。亮色模式下,`light` 即 `#fff`,`dark` 即 `#000`;暗黑模式下,两者颜色互换,`light` 即 `#000`,`dark` 即 `#fff`
- 新增 `syncStatusBarColor` / `createCalendarDayPaint` / `createCalendarDayContent` 全局函数与 `SN_DEFAULT_STYLE_ID` 常量
- 新增 `sn-agreement` 协议勾选:支持链接文本与勾选状态双向绑定
- 新增 `sn-album` 相册:网格宫格展示图片组并支持点击预览
- 新增 `sn-amount` 金额展示:字符串级精确舍入、千分位分隔与中文大写金额
- 新增 `sn-arc-progress` 环形进度:基于 canvas 绘制,支持自定义起止角度
- 新增 `sn-arc-slider` 圆弧滑块:圆弧形态滑动选择器,含 hue 颜色模式
- 新增 `sn-calendar` 日历选择器:底部弹出,支持单选 / 区间 / 多选三种模式
- 新增 `sn-calendar-view` 月历视图:可滑动的月历面板,供日历系列组件复用
- 新增 `sn-calendar-punch` 打卡日历:签到打卡记录日历
- 新增 `sn-calendar-week` 周日历:一次展示一周并支持滑动切周
- 新增 `sn-cascader` 级联选择:支持静态 data 与异步 loadData 双数据源
- 新增 `sn-cell` 列表项:通用单元格组件,框架内部列表布局统一复用
- 新增 `sn-clipper` 图片裁剪:可视裁剪框拖拽缩放,导出区域与预览一致
- 新增 `sn-code-input` 验证码输入:支持掩码、光标与粘贴识别
- 新增 `sn-color-picker` 颜色选择器:支持 alpha 透明度与预设色
- 新增 `sn-color-picker-view` 颜色视图:颜色选择的滑动面板视图
- 新增 `sn-drag` 拖拽排序:长按拖拽交换排序
- 新增 `sn-drag-item` 拖拽项:配合 `sn-drag` 使用的可拖拽子项
- 新增 `sn-drawer-list` 抽屉长列表:底部抽屉形态的长列表容器
- 新增 `sn-ellipsis` 文本省略:超长文本省略并支持展开 / 收起
- 新增 `sn-footer` 页脚:Logo + 导航链接 + 版权三段式布局
- 新增 `sn-fullscreen` 全屏:原位展开全屏容器
- 新增 `sn-form-field` 表单项容器:标签、内容、必填标与校验注册的基座
- 新增 `sn-input-field` 标签输入框:表单项 + 输入框组合,内置错误提示
- 新增 `sn-textarea-field` 标签文本域:表单项 + 文本域组合,含字数统计
- 新增 `sn-highlight-text` 高亮文本:关键词高亮显示
- 新增 `sn-keyboard` 安全键盘:数字 / 整数 / 密码 / 身份证 / 车牌五种类型
- 新增 `sn-mention` 提及输入:@ 提及选择输入框
- 新增 `sn-message` 消息条:全局消息队列,六方向弹出与分组计数
- 新增 `sn-notification` 通知:带标题内容与类型图标,支持进度条与拖动关闭
- 新增 `sn-pagination` 分页器:简洁 / 完整两种模式,支持快速跳转
- 新增 `sn-popover` 气泡卡片:锚点定位的轻量气泡弹层
- 新增 `sn-post-card` 帖子卡片:动态 / 帖子信息展示卡片
- 新增 `sn-region-picker` 省市区选择:内置中国区划数据,省 / 市 / 县模式
- 新增 `sn-scroll-view` 滚动容器:与长列表共用刷新 / 加载更多 / 回到顶部机制
- 新增 `sn-slide-captcha` 滑块验证:拖拽滑块完成验证
- 新增 `sn-slider-double` 双向滑块:区间范围选择
- 新增 `sn-sorter` 排序:字段排序选择器
- 新增 `sn-steps` 步骤条:横 / 竖排布,圆点 / 点状两种形态
- 新增 `sn-step` 步骤项:配合 `sn-steps` 的步骤节点
- 新增 `sn-table` 表格:支持固定表头与固定列
- 新增 `sn-tr` 表格行:配合 `sn-table` 的行节点
- 新增 `sn-td` 表格单元格:配合 `sn-table` 的单元格节点
- 新增 `sn-tree` 树:多模式选择与懒加载
- 新增 `sn-watermark` 水印:页面或局部水印覆盖,不影响其他组件,无副作用。
- 新增 `Demo` 手势库实例,结合可视化元素演示手势库应用
- 新增 `sn-e-toast` 插件:替换 `snu.showToast` 基于 `dialogPage ` 实现的不可透穿手势的 Toast 轻提示,原生弹层实现同官方 `uni.showToast` 基本一致的体验。同时相对于官方的 UI 新增了动画和丰富的样式支持。
- 优化 `$` 动态变量解析,在原有的仅支持基础上支持解析任意尺寸,自动计算符合当前框架尺寸乘数的结果。新增 `Resolve` 相关解析 API (详见文档)暴露给开发者使用以适配框架样式。
- 优化 动画统一由 UniElement DOM animate / transition + `--ani-time-*` 变量实现,支持 `$` 简写并随 `aniTimeFactor` 全局调速
- 优化 点击态统一为 `useHover` + `hover-style` 机制,替代旧 `hover-class`,配套 `hover-start-time` / `hover-stay-time` / `hover-trans-time`
- 优化 内部列表项 / 子项布局统一复用 `sn-cell`,子元素样式经 `itemStyle` / `itemHoverStyle` / `itemTextStyle` / `itemIconStyle` / `itemClass` / `itemBorder` 传递链透传
- 优化 长列表组件(`sn-list-view` / `sn-waterflow`)改为数据驱动 + 作用域插槽渲染,条目按数据项 type 分组复用回收,避免了直接传入 `list-item` / `flow-item` 组件被渲染为普通view 而引发的内存泄露问题
- 优化 重新设计了 `sn-input` 和 `sn-textarea` 的默认样式。如需原来的样式可以通过丰富的属性来实现。
- 优化 跟手组件触摸交互改为 DOM 直操作,APP 端拖动更顺滑
- 优化 `sn-select`、`sn-menu` 支持触底上移,即如果触发点位于页面底部,将自动将弹出层上移,避免触底。
- 优化 各组件尺寸类统一支持联合类型 `String | Number`
- 优化 `sn-datetime-picker` 的性能问题。
- 优化 禁用态统一使用主题禁用色,Web 端条件编译设置 `cursor: not-allowed`
- 优化 `sn-select` 滚动模式下打开将自动定位到当前选中项。
- 优化 sn-waterflow Web 端启用虚拟滚动,长列表滚动更流畅
- 优化 sn-picker-view 在 APP端使用拍平,极大提升了载入大量数据时的性能,卡顿大幅减轻
- 优化 sn-upload-media 及 sn-upload-media-unicloud 在非 Web 端平台改用系统提供的选择器,无需再向系统申请媒体权限
- 优化 sn-scan 从相册中选择图片时改用系统提供的选择器,无需再向系统申请媒体权限,且不会产生大量缓存文件而导致占用空间膨胀
- 优化 Demo 新特性速览跳转到工具库 Demo 时出现的卡顿问题
- 优化 `sn-e-markdown` 改 Android 原生渲染,消除 WebView 卡顿
- 优化 按钮 / 输入框 / 开关加载态指示器延迟 100ms 显示,避免闪烁
- 优化 `sn-rate` 只读态改为双层裁剪渲染,提升性能
- 【重要】更改【破坏性变更】重构原有 API 架构,具体见文档。
- 更改【破坏性变更】 全部组件样式扩展统一为 `customStyle` + `{语义}Style` / `Class` 透传体系,适配蒸汽模式样式隔离 2.0
- 更改 【破坏性变更】错误体系统一为 uni 错误规范:`SnError` 移除,统一改用 `UniError`(errSubject / errCode / errMsg / cause),多级模块 errSubject 以 `::` 分割;日志与错误码查询迁至 `sinle-logger` 插件
- 更改 【破坏性变更】`$snui.setColorSet` 更名 `setColorBase`,颜色键校验更严格
- 更改 组件 v-model 规范化:旧 `vModel` / `modelValue` 统一为 `v-model`(`sn-checkbox` / `sn-radio` / `sn-switch` / `sn-rate` / `sn-slider` / `sn-progress` 等)
- 更改 【破坏性变更】弹出层组件 `open` / `close` 事件改为六段动画生命周期事件 `beforeenter` / `enter` / `afterenter` / `beforeleave` / `leave` / `afterleave`,`clickMask` 统一更名 `clickoverlay`
- 更改 【破坏性变更】扩展插件收编为内置组件:`sn-e-gesture` → `sn-gesture`、`sn-e-qrcode` → `sn-qrcode`、`sn-e-barcode` → `sn-barcode`
- 更改 【破坏性变更】 `sn-waterfall` 更名重写为 `sn-waterflow`,并进行了重构。在APP 端封装官方内置组件 `waterflow`,在 `Web` 端采用自实现的虚拟列表。
- 更改 【破坏性变更】`sn-markdown` 迁移为独立插件 `sn-e-markdown`
- 更改 【破坏性变更】 `sn-longlist` 重构为 `sn-list-view`,`refresher-triggered` 改为 v-model 双向绑定
- 更改 【破坏性变更】 `sn-form-item` 拆分为 `sn-form-field` / `sn-input-field` / `sn-textarea-field`,`submited` 事件更名 `submit`
- 更改 【破坏性变更】`sn-menu` 菜单类组件的子组件从 `sn-menu-item` 改为 `sn-cell` ,移除插槽并新增 `select` 事件。
- 更改 重新设计 `sn-signature` 组件布局,适配横屏模式。
- 更改 尺寸 / 时间类 props 统一放宽为 `String | Number` 并接入 `$` 乘数语法,颜色类 props 使用 `String` 支持 `$` 主题色
- 更改 【破坏性变更】字号板(`font.baseSize` + size 等级)、圆角等级板、动画等级板,改为乘数体系
- 更改 【破坏性变更】各组件 `customXxxStyle`(UTSJSONObject)更名去 `custom` 前缀为 `{语义}Style` 并成对新增 `{语义}Class`,`customStyle` 类型放宽为 `UTSJSONObject | String`
- 更改 【破坏性变更】`$snui.configs` 六大子配置体系,改为 `$snui` 扁平属性直接读写
- 修复 Android 端跟手组件拖动卡顿问题,触摸交互改 DOM 直写保证帧率
- 修复 `sn-notice` 组件在横屏或宽屏场景下文字完全隐藏后需要等待较长时间才会再次显示的问题
- 修复 `sn-notice` 组件过长文本会被截断的问题
- 修复 弹出层类组件未置于 `sn-page` 根节点时 `--sn-*` 颜色与 `--ani-time-*` 动画时长变量失效的问题
- 修复 非法 type / level 导致异常的问题,当前自动回退默认主题
- 修复 sn-timer / sn-countdown 等组件类型过度收窄导致的传参报错
- 修复 Date 日期库部分情况下报空指针异常的问题
- 修复 Utils 工具库 isDate 在高版本 uni-app x 上报空指针异常的问题
- 修复 sn-scan 图片扫描成功后预览图与识别点错位的问题
- 修复 sn-scan 手指在扫描线上无法触发缩放事件的问题(即缩放具有明显的卡顿感的问题)
- 更改 【破坏性变更】Store 状态管理库回归:旧版挂载于 `$snui.store` 的实现废弃重建,2.0 改为独立导出 `StoreLib` / `store` / `frameStore`,不再挂载 `$snui`(蒸汽模式也可直接使用 `pinia`)。
- 移除 【破坏性变更】`configs.font.mainFamily` 内置字体配置与 `configs.app.grayMode` 哀悼置灰模式
- 移除 【破坏性变更】`snu` 方法:`makePhoneCall`、`vibrate`、`addPx`、`share`、`chooseMedia`、`previewImage`、`showToasty`。上述方法官方基本已有实现或已不实用。
- 移除 废弃类型:`SnShareConfig`、`SnChooseMediaOptions`、`SnPreviewImageConfig`、`SnPreviewImageLongPressActions`、`SnToastyConfig`
- 移除 【破坏性变更】 栅格布局组件 `sn-col` / `sn-row` 与过渡组件 `sn-transition`。上述组件已不实用。
- 移除 【破坏性变更】SVG 组件 `sn-e-svg`。官方内置 `image` 已支持 `svg` 格式。
- 移除 `sn-list-item`、`sn-list-chat` 、 `sn-menu-item` 静态列表子组件,改由 `sn-cell` 实现
- 移除 【破坏性变更】 `sn-perm-listener` 组件标签形态,权限提示能力迁移为 `snu.setPermTips` / `registerPermListener` 等全局 API。
# API 新旧版本差异
## 总览
SinleUI 2.0 对框架 API 做了**结构性重构**:旧版以 `$snui` 挂载 `configs / utils / store / libs` 四大子对象;新版改为**扁平化属性 + 独立命名导出**。核心变化:
- `$snui.utils` → 独立导出 `snu`(工具库门面)
- `$snui.libs.color` / `$snui.libs.date` → 独立导出 `ColorLib/TinyColor` 与 `DateLib/Dayuts/dayuts/isDayuts/dayutsIntl`
- `$snui.store` → **独立导出 `store` / `frameStore` / `StoreLib`**(不再挂载 `$snui`,与 `snu` / `ColorLib` / `DateLib` 一致)
- `$snui.configs`(App/Page/Font/Radius/AniTime/zIndex 六大子配置)→ **移除**,改为 `$snui` 上的扁平属性直接读写(theme、autoTheme、currentStyleId、topbarHeight 等),并新增多风格切换与乘数体系
- 入口导出:旧版根 `index.uts` 几乎只导出 `$snui` 与少量类型;新版导出 18 个值(对象/hooks/工具/常量/函数)+ 大量类型
## $snui 差异明细
| 旧版 | 新版 | 说明 |
| :--- | :--- | :--- |
| `colors`(只读) | `colors`(只读) | 保留,语义不变 |
| `utils` | 移除 | 改为独立导出 `snu` |
| `store` | 独立导出 | Store 库重建为独立导出(`store` / `frameStore` / `StoreLib`),不再挂载 `$snui` |
| `libs` | 移除 | 颜色/日期库改为独立导出 |
| `configs` | 移除 | 见下方配置体系差异 |
| - | `theme`(可写) | 新增,切换亮/暗主题,自动关闭 autoTheme |
| - | `autoTheme`(可写) | 新增,跟随系统外观 |
| - | `currentStyleId`(可写) | 新增,多风格切换 |
| - | `topbarHeight` / `lightBgColor` / `darkBgColor`(可写) | 新增,旧 PageConfig 扁平化 |
| - | `topbarHeightResolved`(只读) | 新增,当前平台实际渲染的导航栏高度:Web 端为 `topbarHeight` + 8px,其他端等于 `topbarHeight` |
| - | `logging`(可写) | 新增,框架日志开关 |
| - | `marginFactor` / `paddingFactor` / `radiusFactor` / `fontsizeFactor` / `aniTimeFactor`(可写) | 新增,五尺寸/动画乘数体系 |
| - | `aniTimeShort` / `aniTimeNormal` / `aniTimeLong`(可写) | 新增,基础时长 × 加速乘数的计算结果;赋值按当前乘数反算写入基础时长并持久化 |
| - | `baseAniTimeShort` / `baseAniTimeNormal` / `baseAniTimeLong`(可写) | 新增,三个基础动画时长(150/250/400ms) |
| `setColorSet(theme, colorSet)` | `setColorBase(theme, colorBase)` | **更名**,功能一致(整体替换某主题颜色集) |
| - | `syncSystemTheme()` | 新增,autoTheme 开启时应用系统主题,一般不需要开发者调用,框架内部会自动管理 |
## 导出清单变化
旧版插件入口仅导出 `$snui`、及各种类型。
新版 `@/uni_modules/sinle-ui` 直接导出:
- **对象**:`$snui`、`snu`
- **核心库**:`ColorLib`、`TinyColor`、`DateLib`、`Dayuts`、`dayuts`、`isDayuts`、`dayutsIntl`
- **钩子**:`useTheme`、`useStyle`、`useFactors`、`useHover`
- **全局函数**:`syncStatusBarColor`、`createCalendarDayPaint`、`createCalendarDayContent`
- **常量**:`SN_DEFAULT_STYLE_ID`(`'default'`)
- **错误**:`UniError`(uni-app x 运行时内置,遵循 uni 错误规范;日志与错误码查询经 `sinle-logger`)
- **类型**:`SnColorBase`、`SnStyle`、`SnThemeMode`、`SnFunctionalColor`、`UseHoverOptions`、全部手势事件类型、全局弹窗配置类型等 90+ 个
钩子体系为 2.0 全新引入:`useTheme` / `useStyle` / `useFactors` / `useHover` 让组件与开发者以组合式方式响应式获取框架状态,详见 [钩子](/api/hooks/index)。
相关差异:- [配置体系差异](./config.md) - [类型差异](./types.md) - [错误体系差异](./error.md)
# 配置体系差异
## 总览
旧版将全局配置收敛在 `$snui.configs` 下的六个子配置对象中(`app / page / font / radius / aniTime / zIndex`),其中字号、圆角、动画采用"基本值 + 固定等级板"的静态结构。
新版**移除了 `Configs` 体系**,全部配置改为 `$snui` 直接属性,并且:
- 由"子配置对象 + 等级板"改为"**全局乘数 + 基础值**"的响应式体系
- 新增**多风格(Style)切换**维度(`currentStyleId`),配置项归属到 `SnStyle` 对象并整体持久化
- 配置修改自动持久化并实时生效:乘数与动画时长变量由 `sn-page` 差量写入,颜色变量随系统外观媒体查询切换
## 逐项差异
| 旧版配置 | 旧版内容 | 新版对应 | 说明 |
| :--- | :--- | :--- | :--- |
| `configs.app.theme` | 主题模式 | `$snui.theme` | 直接属性,写法变化 |
| `configs.app.autoTheme` | 跟随系统 | `$snui.autoTheme` | 直接属性,默认开启 |
| `configs.app.grayMode` | 哀悼置灰模式(1.1.4 新增) | `$snui.grayMode`(+ `$snui.grayLevel`) | 改为 `$snui` 直接属性;旧版写 `$snui.configs.app.grayMode`,新版写 `$snui.grayMode`;另新增 `$snui.grayLevel`(0-100)控制灰度程度,默认 `100` 全灰 |
| `configs.page.topbarHeight` | 导航栏高度,默认 `80px` | `$snui.topbarHeight` | 默认值改为 **`48px`**(Web 端导航栏实际渲染高度再 +8px) |
| `configs.page.lightBgColor` | 亮色页面背景,默认 `#f9f9f9` | `$snui.lightBgColor` | 默认值改为 `#EEF2FF` |
| `configs.page.darkBgColor` | 暗色页面背景,默认 `#262628` | `$snui.darkBgColor` | 默认值改为 `#0F172A` |
| `configs.font.baseSize` + `size(level)` | 基础字号 `14px` + 11 级字号板 | `$snui.fontsizeFactor` | **字号板移除**,改为全局字号乘数 |
| `configs.font.mainFamily` | 全局字体名(misans-normal) | - | **移除**(内置字体已不再随框架分发) |
| `configs.radius.baseSize` + 8 固定等级 | 基础圆角 `12px` + xxsmall~xxlarge/circle 等级板 | `$snui.radiusFactor` | **等级板移除**,改为全局圆角乘数 |
| `configs.aniTime.baseTime` + short/normal/long/xlong | 基础时长 `100ms` + 4 级 | `$snui.baseAniTimeShort/Normal/Long` + `aniTimeFactor` | 4 级改 3 级(short/normal/long),新增时长乘数 |
| `configs.zIndex` | navTabBar/badge/float/overlay/popup/toast 六项层级 | - | **移除**,层级改由组件自身控制 |
## 初始化方式差异
- **旧版**:在 `main.uts` 中通过 `$snui.configs.xxx = xxx` 逐项配置初始化,如:
```typescript
$snui.configs.page.topbarHeight = '88px'
$snui.configs.font.baseSize = '16px'
```
- **新版**:直接读写 `$snui` 属性,或切换整套风格:
```typescript
$snui.fontsizeFactor = 1.2
$snui.radiusFactor = 1
$snui.setColor('light', 'primary', '#4d82ff')
$snui.currentStyleId = 'ink'
```
## 行为变化要点
- 旧版 configs 修改**不持久化**(仅 app.theme/autoTheme 例外);新版所有属性修改(theme、autoTheme、style、factors、baseAniTime 等)**一律自动写入 storage**,重启恢复。
- 旧版字号/圆角/动画为固定等级板(离散取值);新版为连续乘数(任意数值),且 `$` 动态尺寸语法(`resolveSize`)可直接按组件 props 乘以对应乘数。
- 多风格切换为新版独有能力:`currentStyleId` 可从内置 6 套风格(default/ink/chinese/new-year/morandi-green/orange)或自定义风格间切换。
# 类型体系差异
## 导入方式变化
| 旧版 | 新版 |
| :--- | :--- |
| 框架本体类型从 `@/uni_modules/sinle-ui` 导入;**组件专属类型从组件自身 `interface.uts` 导入**(如 `SnActionsheetItem` 等) | 全部类型统一**从 `@/uni_modules/sinle-ui` 重导出**,不再要求从组件目录导入 |
| 旧版部分类型需手动 `import` 或 `as` 处理(如 `SnToastConfig` 从 `sn-native` 导入) | 新版编译器可自动推导,类型经插件入口统一导出 |
## SnColorBase 差异
字段整体保持不变,仅 **新增 `shadow`(阴影色)字段**:
> 旧版 `transparent / page / front / dark / disabled / disabledText / disabledDark / disabledDarkText / line / lineDark / lineText / title / text / textLight` + 五功能色 × 9 + `toast`
>
> 新版相同 + **`shadow`**
5 种功能色(`primary/info/success/error/warning`)× 亮/暗两套颜色集、每种含原色/`Light`/`Dark` + `Active`/`Text` 的结构完全保留,未变。
## 手势事件类型差异
| 类型 | 变化 |
| :--- | :--- |
| `SnPointerEvent` | 保留(type/x/y/event) |
| `SnTouch` | 保留(x/y/diffX/diffY/direction/id),旧版 **direction 字段为独立 `SnTouch` 属性、含义为"手指移动方向"**,保持不变 |
| `SnTouchEvent` | 保留 |
| `SnScaleEvent` | 保留 |
| `SnRotateEvent` | **不再单独导出**,旋转事件在新版中由组件事件内联携带角度(以组件文档为准) |
| `SnFlingEvent` | 保留 |
## 全局弹窗配置类型差异
| 类型 | 变化 |
| :--- | :--- |
| `SnShowToastConfig` | 保留并扩展:新增 `title` 兼容字段(仅有 `title` 时当 `text` 用)、`passThrough`(点击穿透);余字段基本一致 |
| `SnShowModalConfig` | 保留并扩展:新增 `openAnimation` / `closeAnimation`(`SnModalAnimationFn` 自定义开合动画);新增 `position` 支持 `left/right` |
| `SnShowActionsheetConfig` | `actions` 类型由旧 `SnActionsheetItem[]` 改为 **`SnDataItem[]`**;新增 `wrapStyle/wrapClass`、`panelStyle/panelClass`、`itemStyle/itemBorder/itemHoverStyle` 样式链字段;新增 `openAnimation/closeAnimation` |
| `SnShowLoadingConfig` | 新增(旧版仅有 `showLoading` 但未独立成文档类型) |
| `SnToastParams` | 新增(`sn-toast` 参数型轻提示配置) |
| `SnModalAnimationFn` | 新增(自定义动画函数类型) |
## 废弃类型清理
旧版已标注废弃的类型在新版中**全部移除**:
- `SnShareConfig`(1.1.5 废弃,`snu.share` 移除)
- `SnChooseMediaOptions`(1.1.7 废弃,`snu.chooseMedia` 移除)
- `SnPreviewImageLongPressActions`、`SnPreviewImageConfig`(1.1.7 废弃,`snu.previewImage` 移除)
- `SnToastyConfig`(旧 showToasty 参数类型)
## 权限类型
`SnRequestSystemPermissionOptions`、`SnRequestMediaPermissionOptions`、`SnRequestMediaPermissionOptionsType` 完全保留,现由 `sinle-api` 定义、`sinle-ui` 重导出。
## 新增类型(新版独有)
- 通用数据项 `SnDataItem`、`SnTime`(计时/倒计时事件返回)
- 权限提示:`SnPermTipConfig`、`SnPermTipsStyleConfig`
- 消息与通知:`SnMessageType/Level/Position/Params`、`SnNotificationType/Level/Position/Params`
- 核心类型:`SnStyle`(完整风格对象)、`SnColorBases`、`SnThemeMode`、`SnFunctionalColor`、`SnResolveType`、`UseHoverOptions`、`SN_DEFAULT_STYLE_ID`
- 组件专属类型大量扩充(`SnAvatarConfig`、`SnTreeData`、`SnCalendar*`、`SnRegion*`、`SnFormItemRule`、`SnFooterLink`、`SnBarcodeFormat`、`QrEncodeOptions`、`SnSignatureBrush` 等),均随组件文档说明
# 错误与日志体系差异
## 错误类型迁移至 UniError(破坏性变更)
旧版错误类型为 `SnError`(自定义类),2.0 起移除,统一遵循 [uni 错误规范](https://doc.dcloud.net.cn/uni-app-x/err-spec.html) 使用运行时内置 `UniError` 对象。
| 项目 | 旧版(1.x) | 新版(2.0 beta) |
| :--- | :--- | :--- |
| 错误类型 | `SnError`(自定义类) | `UniError`(uni-app x 运行时内置) |
| 构造 | `new SnError(moduleName, apiname, errCode, cause?)` | `new UniError(errSubject, errCode, errMsg)` |
| 属性 | `errSubject`(`moduleName-apiname` 拼接) / `errMsg` / `cause` | `errSubject` / `errCode` / `errMsg` / `cause` / `data` |
| errSubject 规则 | 单段拼接(如 `'ui-showToast'`) | 多级模块以 `::` 分割(如 `'sinle-ui::component::sn-avatar'`、`'sinle-ui::api::utils::showToast'`) |
| 源错误 | `cause` 为 `Error` | `cause` 为 `SourceError`(多个时为 `UniAggregateError`) |
| 导入来源 | `@/uni_modules/sinle-ui`(重导出) | 无需导入(运行时全局对象) |
> **兼容性影响**:所有依赖 `SnError` 类型、构造参数与 `errSubject` 拼接规则的代码全部失效,需迁移为 `UniError` 构造与 `::` 分割的 errSubject。
## 插件收敛至 sinle-logger(破坏性变更)
旧版错误与日志由 `sinle-error` 插件提供,2.0 起收敛为 `sinle-logger` 插件统一管理:
| 项目 | 旧版(1.x) | 新版(2.0 beta) |
| :--- | :--- | :--- |
| 日志开关 | `$snui.configs` 无专门日志开关 | `$snui.logging`(默认开启),`setLogging` / `getLogging` |
| 日志方法 | `log / info / debug / warn / error`(`[Snui]` 前缀) | 同左(经 `sinle-logger` 提供,`warn` / `error` 接收 `UniError` 并抛出) |
| 错误码查询 | `getErrMsg` 语义错误码表 | 保留(迁至 `sinle-logger`) |
| 使用约束 | 组件内可随意 | **禁止组件内直接 `console`**,一律经框架日志接口(`core/private/logger.ts`) |
## 错误码标准
错误码对照表(成功、撤销、权限、文件、平台、组件参数、Store key 重复、扫描等场景)仍保留,见[错误码对照表](/api/error/standard)。2.0 起各模块失败时通过 `UniError.errMsg` 直接提供错误信息,亦可经 `sinle-logger` 的 `getErrMsg(errCode)` 查询。
## 对应关系
- 旧 `snu.showToasty` → 新版 `snu.showSysToast`(调用系统原生 Toast)
- 全局弹窗(`showToast/showModal/showActionsheet/showLoading`)失败回调统一返回 `UniError`
# 组件差异索引
SinleUI 2.0 各组件相对 1.x 版本的差异说明索引。各组件的完整用法请见[组件文档](/components/index)。
## 已有组件差异
以下组件在 1.x 中已存在,2.0 对其进行了属性、事件、方法或行为上的调整。
- [sn-actionsheet](./sn-actionsheet)
- [sn-alert](./sn-alert)
- [sn-avatar](./sn-avatar)
- [sn-backtop](./sn-backtop)
- [sn-badge](./sn-badge)
- [sn-barcode](./sn-barcode)
- [sn-button](./sn-button)
- [sn-card](./sn-card)
- [sn-checkbox](./sn-checkbox)
- [sn-collapse](./sn-collapse)
- [sn-countdown](./sn-countdown)
- [sn-countto](./sn-countto)
- [sn-dateformat](./sn-dateformat)
- [sn-datetime-picker](./sn-datetime-picker)
- [sn-drawer](./sn-drawer)
- [sn-e-blurview](./sn-e-blurview)
- [sn-e-markdown](./sn-e-markdown)
- [sn-e-scan-provider](./sn-e-scan-provider)
- [sn-e-scankit](./sn-e-scankit)
- [sn-empty](./sn-empty)
- [sn-float-board](./sn-float-board)
- [sn-float-button](./sn-float-button)
- [sn-form](./sn-form)
- [sn-gap](./sn-gap)
- [sn-gesture](./sn-gesture)
- [sn-grid](./sn-grid)
- [sn-icon](./sn-icon)
- [sn-image](./sn-image)
- [sn-input](./sn-input)
- [sn-label-checkbox](./sn-label-checkbox)
- [sn-label-radio](./sn-label-radio)
- [sn-line](./sn-line)
- [sn-link](./sn-link)
- [sn-list-view](./sn-list-view)
- [sn-loading](./sn-loading)
- [sn-loading-page](./sn-loading-page)
- [sn-loadmore](./sn-loadmore)
- [sn-menu](./sn-menu)
- [sn-modal](./sn-modal)
- [sn-more](./sn-more)
- [sn-notice-bar](./sn-notice-bar)
- [sn-overlay](./sn-overlay)
- [sn-page](./sn-page)
- [sn-perm-listener](./sn-perm-listener)
- [sn-picker](./sn-picker)
- [sn-popup](./sn-popup)
- [sn-progress](./sn-progress)
- [sn-qrcode](./sn-qrcode)
- [sn-radio](./sn-radio)
- [sn-rate](./sn-rate)
- [sn-refresher](./sn-refresher)
- [sn-result](./sn-result)
- [sn-scan](./sn-scan)
- [sn-search](./sn-search)
- [sn-select](./sn-select)
- [sn-sidebar](./sn-sidebar)
- [sn-signature](./sn-signature)
- [sn-skeleton](./sn-skeleton)
- [sn-slider](./sn-slider)
- [sn-stepper](./sn-stepper)
- [sn-subsection](./sn-subsection)
- [sn-swipe-action](./sn-swipe-action)
- [sn-switch](./sn-switch)
- [sn-tabbar](./sn-tabbar)
- [sn-tabs](./sn-tabs)
- [sn-tag](./sn-tag)
- [sn-text](./sn-text)
- [sn-textarea](./sn-textarea)
- [sn-timer](./sn-timer)
- [sn-toast](./sn-toast)
- [sn-tooltip](./sn-tooltip)
- [sn-topbar](./sn-topbar)
- [sn-upload-media](./sn-upload-media)
- [sn-view](./sn-view)
- [sn-waterflow](./sn-waterflow)
## 已删除组件
以下组件在 1.x 中存在,2.0 已移除。点击可查看删除原因与替代方案。
- [sn-col](./sn-col)
- [sn-e-svg](./sn-e-svg)
- [sn-form-item](./sn-form-item)
- [sn-list](./sn-list)
- [sn-list-chat](./sn-list-chat)
- [sn-list-item](./sn-list-item)
- [sn-longlist](./sn-longlist)
- [sn-markdown](./sn-markdown)
- [sn-menu-item](./sn-menu-item)
- [sn-row](./sn-row)
- [sn-transition](./sn-transition)
- [sn-waterfall](./sn-waterfall)
- [sn-waterfall-item](./sn-waterfall-item)
## 说明
- 2.0 新增的组件不属于「差异」范畴,其用法请直接查阅[组件文档](/components/index),本索引不再收录。
- 被更名或重构的组件(如 `sn-longlist` → `sn-list-view`、`sn-waterfall` → `sn-waterflow`、`sn-form-item` → `sn-form-field`)在新旧两侧名称下均有说明:新名称页面描述差异明细,旧名称页面描述删除原因与替代方案。
# 工具库(snu)差异
## 使用方式变化
| 项目 | 旧版 | 新版 |
| :--- | :--- | :--- |
| 获取入口 | `import { $snui } from '@/uni_modules/sinle-ui'` → `const snu = $snui.utils` | `import { snu } from '@/uni_modules/sinle-ui'`(独立命名导出) |
| 分组 | 分组不对外强调 | 10 个分组静态类 + `snu` 聚合门面,三层架构 |
## 方法级差异
### 保留不变(全部同签名)
| 分组 | 方法 |
| :--- | :--- |
| Random | `randint` / `randomNumber` / `uuid` |
| Basic | `throttle(fun, wait, id='default')` / `debounce` / `clamp(value, min, max=null)` |
| Easing | 全部 31 个缓动方法(sine~bounce 缓入/缓出/缓入缓出 + linear) |
| ObjectUtils | `formatNumber` / `deepClone` / `reArray` / `shuffle` / `isNumber` / `setDataset` / `getDataset` |
| System | `openLink` / `showSysToast` / `viewUrlByWebview` / `getOsTheme` / `setClipboardData` / `getClipboardData` |
| Sort | 8 个排序算法(冒泡/选择/插入/快排/归并/堆/希尔/桶) |
| Text | `isEmpty` / `len` / `kebabCaseToCamelCase` / `camelCaseToKebabCase` / `numToUpper` / `encryptName` / `encryptPhone` / `encryptIDCard` / `encryptEmail` / `encryptBankCard` / `separateNumber` |
| Ui | `getPx` / `addUnit` / `getInnerRadius` / `getDistance` / `getRotateAngle` / `findParent` / `findBrother` / `showToast` / `hideToast` / `showModal` / `showActionsheet` |
| Verify | 全部 17 个校验方法(isDate~isFloat) |
### 新增方法
| 分组 | 新增 | 说明 |
| :--- | :--- | :--- |
| Text | `roundAmount(value, decimals=2, mode='round')` | 字符串级金额舍入(round/ceil/floor/trunc),避免 toFixed 浮点陷阱 |
| Text | `numToUpperAmount(value)` | 金额中文大写转换(符合央行票据规范) |
| Ui | `showLoading(config)` / `hideLoading()` | 全局加载弹层(旧版无独立 loading 弹窗 API) |
| [useResolve](/api/hooks/use-resolve)(钩子) | `resolveSize` / `resolveSizeNum` / `resolveColor` | **2.0 起由 Utils 分组迁移为钩子**(`core/private/use-resolve.ts`),不再属于 `snu` 分组;`$` 动态尺寸/颜色解析(驱动组件尺寸乘数与主题色语法) |
| Perm | `setPermTips` / `setPermTipsStyle` / `registerPermListener` / `unregisterPermListener` / `hidePermTips` | **全新分组**,权限用途提示配置与监听(配套 `sn-perm-listener` 插件);另有自 platform 分组迁入的 `checkSystemPermissionGranted` / `getSystemPermissionDenied` / `requestSystemPermission` / `gotoSystemPermissionActivity` / `requestMediaPermission` / `checkMediaPermission`(签名不变) |
### 移除方法
| 方法 | 旧版状态 | 新版 | 替代建议 |
| :--- | :--- | :--- | :--- |
| `makePhoneCall` | platform 分组 | 移除 | 使用 `uni.makePhoneCall` |
| `vibrate` | os 分组 | 移除 | 使用 `uni.vibrateLong` / `uni.vibrateShort` |
| `addPx` | ui 分组 | 移除 | 使用 `getPx` / `addUnit` |
| `share` | os 分组(1.1.5 已废弃) | 移除 | `uni.shareWithSystem` |
| `chooseMedia` | os 分组(1.1.7 已废弃) | 移除 | `uni.chooseMedia` |
| `previewImage` | 全局(1.1.7 已废弃) | 移除 | `uni.previewImage` |
| `showToasty` | 全局(更名产物) | 移除 | 新版统一为 `showSysToast`(系统 Toast)与 `showToast`(框架轻提示) |
### 更名/归属调整
- `randomComId`:旧版归入 Basic 分组,新版归入 **Random** 分组(对外用法不变)。
- `getOsTheme`:旧 platform 分组,新版归入 System 分组(`core/utils/platform.ts`)。
- 权限相关方法旧版分散在 `permission.md`/`platform.md`,新版统一归入 **Perm 分组**(`core/utils/perm.ts`)。
## 行为变化要点
- `resolveColor`/`resolveSize` 由新版组件内部大量依赖,配合 `sn-page` CSS 变量注入实现 `$primary` 等 $ 语法(旧版组件无此机制)。
- 全局弹窗配置类型签名有变(见 API 类型差异):`showActionsheet` 的 `actions` 改为 `SnDataItem[]`,并新增样式链字段。
# 颜色库(Color)差异
## 使用方式变化
| 项目 | 旧版 | 新版 |
| :--- | :--- | :--- |
| 获取入口 | `$snui.libs.color`(文档以 `colorLib` 代称) | `import { ColorLib, TinyColor } from '@/uni_modules/sinle-ui'` |
| 实现基础 | 基于第三方 `lime-color` | **完全自研**(`core/color/`,无三方依赖) |
## ColorLib 静态方法差异
| 方法 | 旧版 | 新版 | 说明 |
| :--- | :--- | :--- | :--- |
| `tinyColor(input, opts)` | √ | √ | 创建 TinyColor 实例 |
| `calcAPCA(...)` | √ | √ | APCA 对比度计算 |
| `generate(...)` | √ | √ | 色板生成(默认 10 阶 + 暗色模式支持) |
| `mean(...)` | √ | √ | 颜色平均 |
| `random()` | √ | √ | 随机颜色 |
方法名与主要行为保留,实现全部重写。
## TinyColor 方法差异
### 保留(签名不变或以等价实现保留)
`getBrightness` / `getLuminance` / `isLight` / `isDark` / `getAlpha` / `setAlpha` / `toHsv` / `toHsl` / `toRgb` / `toHex` / `toName` / `toNumber` / `toString` / `clone` / `lighten` / `brighten` / `darken` / `tint` / `shade` / `desaturate` / `saturate` / `greyscale` / `spin` / `mix` / `analogous` / `monochromatic` / `splitcomplement` / `complement` / `equals` / `onBackground` / `triad` / `tetrad` / `polyad`
### 新增
| 方法 | 说明 |
| :--- | :--- |
| toRgbString | 各类格式字符串输出(旧版仅 toString 间接支持) |
| toHslString | 各类格式字符串输出(旧版仅 toString 间接支持) |
| toHsvString | 各类格式字符串输出(旧版仅 toString 间接支持) |
| toHsbString | 各类格式字符串输出(旧版仅 toString 间接支持) |
| toPercentageRgbString | 各类格式字符串输出(旧版仅 toString 间接支持) |
| toHex8 | 含透明度 8 位 HEX 输出(旧版须自行处理 alpha) |
| toHex8String | 含透明度 8 位 HEX 输出(旧版须自行处理 alpha) |
| toHexShortString | 含透明度 8 位 HEX 输出(旧版须自行处理 alpha) |
| toHsb | HSB 对象输出 |
| toPercentageRgb | 百分比 RGB 对象输出 |
| isMonochrome | 判断是否单色(饱和度 0) |
### 移除
| 方法 | 旧版状态 | 说明 |
| :--- | :--- | :--- |
| `contrasting` | 旧版存在(返回对比色) | 新版移除(可用 `onBackground`、`getLuminance` 组合实现或自取色调) |
### 输出行为差异
- `toHexString()` 默认仅取 r/g/b,含透明度时需使用 `toHex8String()` / `toHexShortString()`(旧版行为未严格区分)。
## 类型差异
- 旧版颜色类型从 `libs/color/types` 引入;新版 `LColorOptions`、`LGenerateOptions` 等颜色类型经 `sinle-ui` 插件入口重导出,`TinyColor` 内部结构类型(`RGBA`/`HSLA`/`HSVA`/`RGBAString` 等)命名保持不变。
# 日期库(Date)差异
## 使用方式变化
| 项目 | 旧版 | 新版 |
| :--- | :--- | :--- |
| 获取入口 | `$snui.libs.date.dayuts(...)` | `import { dayuts, DateLib, Dayuts, isDayuts, dayutsIntl } from '@/uni_modules/sinle-ui'` |
| 实现基础 | 旧版封装 | **完全自研**(`core/date/`) |
> 旧版统一经 `dateLib.dayuts()` 创建 `Dayuts` 实例;新版提供同名 `dayuts()` 工厂函数直接导出,同时暴露 `DateLib` 静态工具入口。
## DateLib 静态方法(新增,旧版无此类入口)
| 方法 | 说明 |
| :--- | :--- |
| `dayuts(input, config)` | 创建 Dayuts 实例 |
| `newDate(...)` | 创建原生 Date |
| `toDate(...)` | 多种入参解析为 Date(支持字符串/数字/Date/Dayuts 等) |
| `fmtDate(...)` | 小写 token 格式化(`yyyy/MM/dd HH:mm` 风格,支持 周/星期/礼拜) |
| `now()` / `today()` | 当前时间 / 今日实例 |
| `weeks(...)` / `weekName(...)` | 周相关工具 |
## Dayuts 方法差异
### 保留不变
`isValid` / `isSame` / `isAfter` / `isBefore` / `isSameOrBefore` / `isSameOrAfter` / `isBetween` / `isLeapYear` / `isToday` / `unix` / `startOf` / `endOf` / `set` / `get` / `year` / `month` / `day` / `date` / `hour` / `minute` / `second` / `millisecond` / `add` / `subtract` / `format` / `utcOffset` / `diff` / `toDate` / `toJSON` / `toISOString` / `toObject` / `toArray` / `valueOf` / `daysInMonth` / `locale` / `clone` / `toString` / `dayOfYear` / `to` / `from` / `toNow` / `fromNow`
### 移除
| 方法 | 说明 |
| :--- | :--- |
| `fromToBase` | 从基础时间点计算相对时间的内部辅助方法,新版不再暴露 |
### format 模板差异
| 项目 | 旧版 | 新版 |
| :--- | :--- | :--- |
| token 体系 | 大写 token(`YYYY-MM-DD HH:mm:ss` 等,token 较少) | 大写 token 保留并扩展;**新增 `DateLib.fmtDate` 小写 token 体系**(`yyyy/MM/dd` 风格),支持 `周` / `星期` / `礼拜` 中文星期表述 |
| 相对时间 | 英文文案 | **支持本地化文案**(经语言包) |
## 国际化(新增)
- **`dayutsIntl`**:新版独有。提供 locale 注册(`use`)、切换(`set`)、检测(`has`),内置中文(zh-cn)与英文(en)语言包,驱动 `format` 中的周/月名称与相对时间文案。
- `Dayuts` 实例提供 `locale()` 设置实例语言。
## 类型差异
`DayutsConfig` / `DayutsUnit` / `DayutsFormats` / `DayutsRelativeTime` / `DayutsLocale` / `DayutsObject` 类型保留(字段以新版为准),经 `sinle-ui` 入口重导出。
## 平台行为说明
- `utcOffset`:原生端恒为 `0`(仅 Web 有实际含义)——与旧版同平台差异。
- `toISOString`:原生端走 `toString` 实现。
# Store 状态管理库差异
## 结论
旧版的 Store 状态管理库在 SinleUI 2.0 中以 **新实现回归**(此前曾随 2.0 重构整体移除)。核心 API(`get / set / delete`、持久化、过期机制)保持兼容,同时修复了旧版的安全风险与若干 bug,并拓展了订阅、批量查询等能力。框架自身的状态持久化(主题 / 风格 / 灰模等)也已重构为基于新 store 库管理。
## 使用方式变化
| 项目 | 旧版 | 新版 |
| :--- | :--- | :--- |
| 入口 | `$snui.store`(另有插件内 `store` / `frameStore` 导出) | `import { store, frameStore, StoreLib } from '@/uni_modules/sinle-ui'` 独立导出,不再挂载 `$snui`(与 `ColorLib` / `DateLib` 一致) |
| 内置实例 | `store`(`app_store`)、`frameStore`(`sinle_ui_store`) | 同旧版 |
| 存储键前缀 | `sinle_ui_store_lib_*`、`{storeKey}_key_*` | `snui_store_{storeKey}_*`(实例级隔离) |
## 方法差异
### 保留(签名兼容)
`get(key)` / `set(key, value, lasting?, expire?)` / `delete(key)` 行为与旧版一致。
| 方法 | 旧版 | 新版 | 说明 |
| :--- | :--- | :--- | :--- |
| `get(key)` | √ | √ | 新增可选 `defaultValue` 参数 |
### 新增
| 方法 | 说明 |
| :--- | :--- |
| `get(key, defaultValue)` | 支持指定键不存在/过期时返回的默认值 |
| `has(key)` | 判断键是否存在且未过期 |
| `keys()` | 返回全部未过期键名 |
| `clear()` | 清空全部数据(含持久化数据) |
| `size` | 当前未过期键数量 |
| `subscribe(key, listener)` | 订阅指定键变更,返回取消函数 |
| `unsubscribe(key, listener)` | 手动取消订阅 |
### 移除
无(旧版三个方法全部保留)。
## 修复的旧版问题
| 问题 | 旧版表现 | 新版处理 |
| :--- | :--- | :--- |
| 多实例持久化键冲突 | 过期/持久化列表使用全局固定键 `sinle_ui_store_lib_expireslist` / `...lastinglist`,多个 `StoreLib` 实例互相同步互踩,与「互不干扰」承诺相悖 | 各实例的元数据键按 `snui_store_{storeKey}_*` 独立命名空间 |
| 初始化异步竞态 | `init()` 内 `uni.getStorage` 异步回调链读取列表,存在初始化未完成即被访问、持续数据丢失的风险 | 改为同步 storage API,初始化确定性完成 |
| 异步写入乱序 | `uni.setStorage` 异步写入,连续写入同键可能乱序丢失 | 改为 `uni.setStorageSync` 同步写入,保证顺序 |
| 过期键重新 set 残留旧过期 | 已过期/设过过期时间的键以 `expire=0` 重新 set 后,旧过期记录未清除 | 重新 set 不带过期时间时自动清除旧过期记录 |
| 过期后取值为 `''` | `getStorageSync` 缺键返回 `''`,`data ?? ''` 兜底失效,缺键被当作空串值写入 | 缺键/空串按「未存储」处理,持久化列表自愈清理 |
| H5 风格恢复失效 | 读取风格用 `UTSJSONObject.hasKey`(H5 不可用)导致已保存风格无法恢复 | 改用直接属性访问,全平台一致恢复 |
| 空值判断污染 | `getStorageSync` 缺键返回 `''`,`loadBoolean` 会误把 `''` 当 `true` | store 缺键返回 `null`,避免隐式误判 |
| storeKey 无校验 | 任意非法字符可注入存储键 | storeKey 仅允许 `[A-Za-z0-9_-]`,非法/重复实例创建无效并告警 |
## 行为差异
- 持久化存储键命名空间变化,旧版(`sinle_ui_store_lib_*`)持久化数据不会被新版自动读取;框架配置类状态由 `state.ts` 提供**一次性旧键迁移**。
- 过期与持久化判断为惰性(访问时清理),与旧版一致,无定时器开销。
- 持久化复杂 `type` 对象回读仍为普通对象,需自行转换(与旧版一致,属 storage API 固有行为)。
## 迁移建议
- 原使用 `$snui.store.get / set / delete` 的代码改为 `import { store } from '@/uni_modules/sinle-ui'` 后直接调用(`$snui.store` 已移除),方法签名兼容,仅注意持久化键命名空间变化导致的旧数据不可见。
- 若使用过 `storeKeys` 之外的旧版持久化键名,需手动迁移一次数据。
- 框架内部(主题 / 风格 / 灰模、dialog 弹窗配置)已统一使用 `frameStore` 或基于 `StoreLib` 的实例管理,无需业务介入。