发布日期:2026-10-19
unix-utils v0.2.0 发布!继 toast 模块之后,第二个模块 modal 正式上线------对 uni.showModal 的全端兼容封装,覆盖 Android / iOS / Web / 微信 / 鸿蒙五端,参数与 uni.showModal 完全同构,业务侧统一 import { showModal } from '@/uni_modules/unix-utils'。
这一次我们做得更彻底。v0.1.0 的 toast 已经在 App 端用 UTS 直挂系统窗口实现了「属性全生效」,而 uni.showModal 原生通道在各端长期存在「按钮颜色不生效、alpha 色值表现不一、按钮文案被静默截断、返回值 cancel 字段缺失、editable 输入框初始值与光标行为不受控」的差异------这些残余差异无法在归一化层消除。v0.2.0 起 App 端 modal 不再走原生通道,复用 toast 的直挂窗口基建实现窗口级自绘 ,从根上抹平;微信 / 鸿蒙保留原生通道,自动降级并经 fail 回调结构化留痕。
为什么需要它
拿最常见的「重命名」场景举例:弹一个 editable: true 的确认框,让用户在输入框里改名字。用原生 uni.showModal 你会遇到------
- App 端输入框的光标位置不受控:初始内容想让它光标落在末尾方便续写,原生通道做不到;
- 想给确认按钮一个带透明度的品牌色
#007AFFCC,部分端静默剥离 alpha、部分端直接不生效,还没有任何通知; - 用户点了取消,返回值里可能根本没有
cancel字段 ,你只能靠!res.confirm兜底判断; - 微信端按钮文案超 4 个字符被静默截断,线上才发现按钮变成了「确...」。
每一项都要自己踩一遍、封一遍,换个项目再踩一遍。unix-utils 把这些重复劳动收敛进库里:返回值字段恒定互斥、颜色归一化生效保障、不支持的参数自动降级并留痕,差异可感知、可过滤。
这次更新了什么
modal 模块:与 uni.showModal 完全同构
参数一比一对齐(title / content / showCancel / cancelText / cancelColor / confirmText / confirmColor / editable / placeholderText / success / fail / complete),除回调外均为可选字段,迁移零成本。返回值经库内归一化,ModalResult 的 confirm / cancel 恒存在且互斥 :点确认 { confirm: true, cancel: false }、点取消 { confirm: false, cancel: true },editable 场景点确认时 content 携带输入文本、点取消恒为 null。
uts
import { showModal } from '@/uni_modules/unix-utils'
// 与 uni.showModal 参数完全一致,迁移零成本
showModal({
title: '删除确认',
content: '删除后不可恢复,是否继续?',
confirmColor: '#ff0000',
success: (res) => {
if (res.confirm) doDelete() // confirm / cancel 恒存在且互斥
}
})
双轨 API 与快捷姿势
Promise 式 showModalAsync、单确定按钮的 alert 语义、项目级默认配置一并到位:
uts
import { showModalAsync, showModalAlert, configureModal } from '@/uni_modules/unix-utils'
// Promise 式:点取消不算失败(与 uni 语义一致,正常 resolve)
// 失败 reject ModalFail 结构的 JSON 字符串(全端统一,JSON.parse<ModalFail> 还原)
const res = await showModalAsync({ title: '保存修改', content: '是否保存当前修改?' })
if (res.confirm) save()
// alert 语义(单确定按钮,对齐 HTML alert)
showModalAlert('提示', '操作已完成')
// 全局默认:项目级预设按钮文案与颜色,字段传 null 表示沿用库内置默认 / 平台默认
configureModal({
confirmText: '知道了',
confirmColor: '#00aa00',
cancelText: null,
cancelColor: null
})
App 端窗口级自绘:editable 真实输入框
这是 v0.2.0 最重要的设计决策。原生 uni.showModal 的参数语义在各端基本对齐,文案截断、返回值缺字段这类差异大多能在库内归一化层抹平;但 editable 输入框的初始值与光标控制、alpha 色被剥离 这类表现层差异归一化不了。于是 modal 复用了 toast 的直挂窗口基建------Android 端以独立子窗口分别挂载蒙层与卡片(WindowManager)、iOS 端挂载 UIWindow,免注册、免页面改造,业务侧无感。
自绘通道(App / Web)真实渲染输入框:
content兼作输入框初始值,且光标自动定位在内容末尾------重命名场景打开即可续写;- 正文超过屏高 60%(内置阈值)自动限高滚动,长内容不再溢出屏幕;
- 按钮文案与
#RRGGBBAAalpha 色完整生效,不受原生端「静默剥离 / 不生效」影响。
交互语义跨端对齐
三个容易被忽略、又最容易产生分歧的交互细节,五端行为完全一致:
- 蒙层点击不关闭:对齐微信官方语义,仅按钮可关闭------避免用户误触蒙层丢掉正在输入的内容;
- Android 返回键 :以取消语义关闭(
cancel: true),业务侧与点取消按钮同路处理,不会出现「按了返回键弹窗还在」或「返回值语义不明」; - 连续调用:后一次调用替换前一次弹窗(单例复用),不叠加、不残留。
颜色归一化:降级可感知、可过滤
按钮颜色仅接受 16 进制(#RGB 自动展开 / #RRGGBB / #RRGGBBAA),非法值(命名色、缺 #、长度不对)降级平台默认色并经 fail 回调留痕(errCode 2001,param 指明字段);微信 / 鸿蒙原生通道剥离 alpha 并留痕;微信 / 鸿蒙端按钮文案超 4 字符库内自动截断,App / Web 端完整显示。未配置颜色时库内默认确认色 #007aff / 取消色 #000000。
所有降级都有结构化痕迹(ModalFail:errCode / errSubject / param / platform,类型已对外导出),业务侧可精确感知「哪个参数、哪个端」:
uts
showModal({
title: '提示',
confirmColor: 'blue', // 非法颜色:原生通道不支持命名色
fail: (err) => {
// errCode: 2001(PLATFORM_UNSUPPORTED)
// param: 'confirmColor' ------ 触发降级的参数名
// platform: 'mp-weixin' ------ 当前端标识
}
})
破坏性变更:showToastAsync 的 reject 值改为 JSON 字符串
0.1.0 中 showToastAsync 失败 reject ToastFail 对象;实测 App 端运行时 async 代理仅将 reject 值按字符串透传(对象字段全部丢失,业务侧拿到的是对象 toString 形态)。为全端契约一致,0.2.0 起统一 reject ToastFail 结构的 JSON 字符串:
uts
// 迁移前(0.1.0):直接访问对象字段(App 端实测已丢失)
} catch (err) {
const fail = err as ToastFail
console.error(fail.errCode)
}
// 迁移后(0.2.0):JSON.parse 还原(全端统一)
} catch (err) {
const fail = JSON.parse<ToastFail>(err as string)
if (fail != null) console.error(fail.errCode)
}
回调式 showToast 的 fail 回调仍收到结构化对象,不受影响;ToastFail 类型 0.2.0 起对外导出。
快速开始
bash
pnpm add @meng-xi/unix-utils
mkdir -p uni_modules && cp -R node_modules/@meng-xi/unix-utils uni_modules/unix-utils
或在 HBuilderX 插件市场搜索 unix-utils 导入到工程 uni_modules/,然后从上面的任意一段示例开始。
平台兼容性
| 平台 | 通道 | 说明 |
|---|---|---|
| App-Android | UTS 直挂系统窗口自绘(WindowManager) |
全参数生效:editable 真实输入框、#RRGGBBAA 全生效、蒙层点击不关闭、返回键以取消语义关闭 |
| App-iOS | UTS 直挂系统窗口自绘(UIWindow) |
同 Android |
| Web | DOM 单例自绘 | 全参数生效,#RRGGBBAA 保留 alpha |
| 微信小程序 | uni.showModal 原生通道 + 归一化 |
颜色不干预随平台、8 位色值剥 alpha 并留痕;文案超 4 字符库内截断 |
| App-HarmonyOS | uni.showModal 原生通道 + 归一化 |
同微信 |
微信 / 鸿蒙保留原生通道是经过权衡的选择:小程序端自绘会遇到原生组件(video / map / camera)及原生弹窗的遮挡问题,而原生 modal 的参数语义本身对齐,库内归一化足以抹平差异。
文档与反馈
- 📖 完整文档(中英双语):mengxi-studio.github.io/unix-utils/(英文 · 更新日志)
- 🐛 反馈与需求:GitHub Issues
modal 表现细节的真机复核持续进行中(Android 返回键、editable 光标与 IME、滚动阈值、蒙层交互),欢迎试用反馈。