更新记录
1.0.0(2026-10-26)
首个版本:像素级水印绘制、三种布局模板(工程巡检信息栏/简洁时间地点/设备资产记录)、七类内置字段与自定义字段、样式与输出参数配置、EXIF 方向校正、防 OOM 采样解码、长文本折行兜底、相册保存、定位权限与缓存定位读取、时间坐标格式化工具、57 项核心逻辑自动化测试。
平台兼容性
uni-app
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| × | √ | - | - | √ | × | √ | - | - |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| - | - | - | - | - | - | - | - | - | - | - | - |
szhzy-sitecamera 工程巡检水印相机插件
面向工程施工、设备巡检、物业管理、外勤服务、现场验收场景的 Android 水印相机 UTS 插件。
业务系统只需传入业务数据(工单编号、巡检人员、设备编号等),即可对拍照或相册图片叠加像素级水印——水印真实绘制进导出图片的像素中,而非覆盖在预览页面上,分享、下载、二次流转后依然完整保留。
内置三种专业布局:工程巡检信息栏(多字段全量记录)、简洁时间地点水印(轻量遮挡)、设备资产记录水印(设备名突出 + 详情栏)。支持字段显示/隐藏、显示顺序、文字字号、文字颜色、背景透明度、位置与边距配置。
⚠️ 使用前必读
- 本插件仅支持 Android App 平台(面向传统 uni-app Vue3 项目开发与验证;uni-app x 端按兼容模式编写但未实测)。iOS、鸿蒙、Web、小程序均不支持。
- 水印真实性边界(重要):水印中的拍摄时间与经纬度取自设备本地时钟与系统定位缓存,不构成不可篡改证据、司法级取证或可信时间戳认证。如业务需要防篡改存证,请在服务端另行建设(哈希固化、三方时间戳等)。
- 定位为可选能力:插件读取系统最近缓存定位(不发起定位请求、不伪造坐标)。权限被拒绝、定位服务关闭或无缓存结果时返回明确错误码,由业务层决定降级文案(如显示「定位不可用」或隐藏坐标字段)。
- 真机运行必须制作自定义基座:UTS 插件不能在 HBuilderX 标准基座上直接运行(见下文环境要求)。
- 诚实的验证状态:水印布局与配置处理核心逻辑已经过 57 项自动化测试;图片像素级绘制、EXIF 方向处理、相册保存等平台链路按 Android 官方 API 标准模式实现,插件作者未在真机上完成全量回归(开发期无 Android 测试机),使用前请先用 Demo 工程在你的目标机型上实测。
- 付费版授权与打包规则(DCloud 市场机制):本插件为付费插件,由插件市场自动加密——普通授权版买家不可见插件源码,需要阅读或修改源码请购买源码授权版;加密插件仅支持云端传统打包,不支持离线打包与安心打包;试用版仅可用于打包自定义基座调试,不能用于正式发布;授权绑定 AppID 与包名,购买后更换任一信息需重新购买授权。
环境要求
| 项 | 要求 |
|---|---|
| HBuilderX | 3.99+(建议使用最新 4.x 版本) |
| 项目类型 | uni-app(Vue3,主要支持目标);uni-app x(兼容模式编写,未实测) |
| Android 最低版本 | 6.0(API 23) |
| 权限 | 定位:FINE/COARSE LOCATION(运行时申请,插件内负责);相册保存:Android 9- 需 WRITE_EXTERNAL_STORAGE(插件内自动申请),Android 10+ 无需权限;相机:由宿主工程 manifest 管理 |
| 其他 | 无第三方 SDK 依赖、无付费地图或定位服务依赖、不访问网络 |
真机运行提示:导入插件后,请在 HBuilderX 中执行「运行 → 运行到手机或模拟器 → 制作自定义基座」,基座制作完成后选择「使用自定义基座运行」;正式打包请使用云打包。Android 编译环境配置见 DCloud 官方文档《uts插件Android运行配置》。
快速开始
1. 安装
通过 HBuilderX 导入插件到项目的 uni_modules 目录。插件自带的 utssdk/app-android/AndroidManifest.xml 已声明定位与存储权限,云打包时自动合并。
2. 拍照 / 选图 + 绘制水印 + 保存相册(完整流程)
import {
processImage, saveToAlbum, getLocation,
requestLocationPermission, formatCoordinate
} from '@/uni_modules/szhzy-sitecamera'
// ① 请求定位权限并读取缓存定位(可选步骤;也可由业务系统传入自有定位)
const loc = await requestLocationPermission()
let locationText = '' // 定位不可用时的降级文案,由业务层决定
if (loc.ok) {
const pos = getLocation()
if (pos.ok) {
// N22.54321°, E113.95432°(5 位小数约 1.1 米精度)
locationText = formatCoordinate(pos.latitude, pos.longitude)
} else {
locationText = '定位不可用'
}
} else {
locationText = '定位未授权'
}
// ② 拍照或从相册选择(系统拍照能力,sourceType 控制来源)
uni.chooseImage({
count: 1,
sizeType: ['compressed'],
sourceType: ['camera', 'album'], // camera 拍照 / album 相册
success: async (res) => {
// ③ 传入业务数据,绘制像素级水印
const result = await processImage(res.tempFilePaths[0], {
template: 'inspection', // 工程巡检信息栏布局
fields: [
{ key: 'projectName', label: '项目', value: '科技园二期机电安装工程' },
{ key: 'serialNo', label: '工单编号', value: 'GD-20261011-0012' },
{ key: 'personName', label: '巡检人', value: '张三' },
{ key: 'deviceName', label: '设备', value: '3F配电柜A-07' },
{ key: 'time', label: '时间', value: '' }, // 留空 + time.auto 自动取当前时间
{ key: 'location', label: '坐标', value: locationText },
{ key: 'remark', label: '备注', value: '巡检正常,无异常发热' }
],
style: {
fontSize: 30, // 基准字号(1080px 宽度基准,自动等比缩放)
textColor: '#FFFFFF',
backgroundColor: '#000000',
backgroundOpacity: 0.55, // 背景透明度 0.1-0.95
position: 'bottom', // 信息栏位置 bottom / top
marginX: 24, marginY: 24 // 边距(自动等比缩放)
},
image: { maxSide: 1920, quality: 88 }, // 最长边限制(防大图 OOM)/ JPEG 质量
time: { auto: true, format: 'yyyy-MM-dd HH:mm:ss' },
emptyPolicy: 'hide' // 空值字段隐藏(或 'placeholder' 显示「未提供」)
})
if (result.ok) {
// ④ 水印已真实绘制进图片像素:path / width / height / size
console.log(`输出 ${result.width}x${result.height},${result.size} 字节`)
console.log(`文件:${result.path}`)
// ⑤ 可选:保存到系统相册
const saved = await saveToAlbum(result.path)
if (saved.ok) {
uni.showToast({ title: '已保存到相册', icon: 'none' })
}
} else {
console.error(`[${result.code}] ${result.message}`)
}
}
})
API 参考
所有异步 API 返回 Promise<UTSJSONObject>,统一信封结构,不通过 reject 抛业务错误:
{ ok: boolean, code: string, message: string, ...业务字段 }
图片处理
| API | 说明 | 返回 |
|---|---|---|
processImage(source, config) |
对图片绘制水印并输出新图(JPEG) | { ok, code, message, path, width, height, size, warnings } |
saveToAlbum(path) |
保存图片到系统相册 DCIM 目录 | { ok, code, message, albumPath } |
validateWatermarkConfig(config) |
校验水印配置(不处理图片,表单即时反馈) | { ok, code, message, warnings, fieldCount } |
processImage 的 source 支持:uni.chooseImage 返回的临时路径(_doc/...)、file:// 路径、content:// 路径、文件绝对路径。
处理管线:采样解码(maxSide 限制最长边,4K 大图自动降采样防 OOM)→ EXIF 方向校正(横竖屏 / 镜像翻转全部处理)→ Canvas 像素级绘制 → JPEG 输出到应用缓存目录。输出图片 path 为绝对路径,可直接用于上传(uni.uploadFile)或预览。
定位
| API | 说明 | 返回 |
|---|---|---|
checkLocationPermission() |
检查定位权限状态(同步) | { granted, needRequest, message } |
requestLocationPermission() |
申请定位运行时权限 | { ok, code, message, granted, doNotAskAgain? } |
getLocation() |
读取系统最近缓存定位(同步,不发起定位请求) | { ok, code, message, latitude, longitude, accuracy, provider, time } |
openLocationSettings() |
跳转系统定位设置页 | 无 |
定位语义(如实):
getLocation读取 GPS / Network / Passive 三通道中时间戳最新的缓存定位,即时返回、不耗电等待;- 定位服务关闭返回
LOCATION_SERVICE_OFF;无任何缓存返回LOCATION_UNAVAILABLE——插件绝不伪造坐标,业务层按需展示降级文案或隐藏坐标字段; - 允许业务系统传入自有定位数据(如
uni.getLocation结果、后端下发的作业点坐标)作为水印字段值——这不等于定位真实性认证,水印展示的坐标仅为信息记录; - 插件不做地理编码(坐标 → 地址)。如需地址展示,由业务系统提供地理编码接口并在业务层转换后传入。
格式化工具(纯逻辑,跨平台可用)
| API | 说明 |
|---|---|
formatTimestamp(ms, format) |
毫秒时间戳 → 本地时间文本,占位符 yyyy MM dd HH mm ss,如 2026-10-11 13:41:23 |
formatCoordinate(lat, lng) |
经纬度 → N22.54321°, E113.95432°(5 位小数,坐标越界返回空串) |
formatLatitude(lat) / formatLongitude(lng) |
单轴格式化(N/S、E/W 半球标记) |
getPluginVersion() |
插件版本号 |
错误码
| code | 含义 | 建议处理 |
|---|---|---|
| SUCCESS | 成功 | - |
| INVALID_PARAM | 参数缺失或非法 | 检查 source / config |
| INVALID_CONFIG | 水印配置校验失败 | 查看 message 中的具体字段提示 |
| FILE_NOT_FOUND | 图片路径无法解析或文件不存在 | 检查 chooseImage 返回的路径传递 |
| DECODE_FAILED | 图片解码失败(文件损坏或格式不支持) | 更换图片验证 |
| SAVE_FAILED | 水印绘制或文件输出失败 | 查看 message,多为磁盘空间不足 |
| PERMISSION_DENIED | 定位 / 存储权限被拒绝 | 引导授权或前往系统设置 |
| LOCATION_SERVICE_OFF | 系统定位服务未开启 | 引导开启(openLocationSettings) |
| LOCATION_UNAVAILABLE | 无缓存定位结果 | 展示降级文案或由业务系统传入定位 |
| NO_ACTIVITY | 无法获取当前 Activity | 环境异常,重启页面 |
水印配置详解
三种布局模板
inspection 工程巡检信息栏(默认)
底部(或顶部)全宽半透明信息栏,全部字段按传入顺序逐行展示,每行格式「标签:值」。适合巡检工单、施工记录等需要全量信息留痕的场景。
simple 简洁时间地点水印
小字号信息条,仅展示时间与坐标两类字段(其余字段自动忽略并给出警告)。适合不希望水印遮挡画面主体的日常记录场景。
asset 设备资产记录水印
顶部黑色标题条突出显示设备名称(1.3 倍字号),底部详情栏展示其余字段。适合设备点检、资产盘点等以设备为主体的场景。position 配置作用于底部详情栏位置,标题条恒在顶部。
字段体系
内置七类字段 key(label 不传时使用默认标签,也可完全自定义):
| key | 默认标签 | 说明 |
|---|---|---|
projectName |
项目 | 项目名称 |
deviceName |
设备 | 设备名称(asset 模板中作为标题条) |
personName |
人员 | 巡检 / 操作人员姓名 |
time |
时间 | 拍摄时间;留空 + time.auto: true 自动取当前时间 |
location |
坐标 | 经纬度文本,建议 formatCoordinate 生成 |
serialNo |
编号 | 自定义业务编号(工单号、点检单号等) |
remark |
备注 | 备注信息,长文本自动折行 |
也支持任意自定义 key(如 line 工序、team 班组),传 label 即可。
字段控制:
- 显示 / 隐藏:不传入该字段即隐藏;
value为空时按emptyPolicy处理(hide隐藏 /placeholder显示「未提供」); - 显示顺序:按
fields数组顺序渲染; - 数值 value:自动转字符串(
12→"12",不出现"12.0")。
样式与输出参数
| 字段 | 类型 | 默认 | 说明 |
|---|---|---|---|
style.fontSize |
number | 30 | 基准字号,基于 1080px 宽度自动等比缩放(范围 12-72) |
style.textColor |
string | #FFFFFF | 文字颜色,#RRGGBB / #AARRGGBB |
style.backgroundColor |
string | #000000 | 信息栏背景色,同上格式 |
style.backgroundOpacity |
number | 0.55 | 背景透明度 0.1-0.95 |
style.position |
string | bottom | 信息栏位置 bottom / top |
style.marginX / style.marginY |
number | 24 | 信息栏边距(等比缩放,范围 0-200) |
image.maxSide |
number | 1920 | 输出图最长边像素(640-4096),超出自动降采样 |
image.quality |
number | 88 | JPEG 压缩质量(40-100) |
time.auto |
boolean | false | time 字段缺值时自动取当前设备时间 |
time.format |
string | yyyy-MM-dd HH:mm:ss | 时间格式占位符 |
文本折行与兜底机制
长文本(如备注)按字符宽度估算自动折行(CJK 全角字符与 ASCII 区分宽度系数);绘制时用系统画笔实测每行宽度,估算偏差导致的超宽行自动整行缩放字号(下限 60%),仍超宽则截断加省略号——保证任何配置下水印都不溢出画面。
关于「水印真实性」的说明(请务必阅读)
- 水印真实绘制进图片像素:导出的 JPEG 文件本身携带水印信息,转发、下载、脱离 App 查看时依然存在;
- 但普通照片水印无法防止截图后裁剪、图像编辑软件篡改。本插件输出的水印照片不构成不可篡改证据、司法级取证材料或可信时间戳认证;
- 水印中的时间取自设备本地时钟(可被用户修改系统时间影响),坐标取自系统缓存定位或业务系统传入值,两者均仅为信息记录;
- 如业务需要防篡改能力:图片上传服务端后计算哈希固化、接入可信时间戳服务、或将原始图片与元数据分别存证——这些属于服务端方案,不在本插件范围内。
常见问题
Q:为什么拍照要用 uni.chooseImage,插件不内置相机界面?
首版遵循系统拍照边界(调用系统相机),保证兼容性与稳定性,不引入自定义相机预览框架的机型适配风险。sourceType: ['camera'] 即为拍照,体验与原生一致。视频水印不在本插件范围内。
Q:水印照片在部分手机相册里方向不对? 不会。插件已按 EXIF 方向标记对图片做旋转 / 镜像校正(覆盖 8 种 EXIF 方向值),输出图恒为视觉正立方向。
Q:处理 4K / 大图会崩溃吗?
采样解码机制保证内存可控:按 maxSide(默认 1920px)降采样后才解码像素,4K 拍照图的内存占用降低 4 倍以上;中间位图显式释放。对超大图(如 8000px 航拍图)建议把 maxSide 设为 1920-2560。
Q:连续快速处理多张图片会怎样? 每次处理独立执行(IO 线程 + 主线程回调),无共享可变状态;处理结果各自输出独立文件,不会相互覆盖。
Q:getLocation 返回 LOCATION_UNAVAILABLE?
设备从未有过任何定位记录(常见于刚重启的设备)。引导用户打开系统地图 App 定位一次、或直接开启定位服务后重试;也可由业务系统传入自有定位数据。
Q:保存到相册在 Android 9 及以下失败?
旧系统需要 WRITE_EXTERNAL_STORAGE 运行时权限,插件会自动弹窗申请;被拒绝后引导用户到系统设置开启(PERMISSION_DENIED 错误码)。Android 10+ 走 MediaStore,无需任何权限。
Q:支持 uni-app x 吗?
插件 API 统一以 UTSJSONObject 交互,代码按 uni-app 与 uni-app x 的兼容模式编写;但当前仅在传统 uni-app(Vue3)上完成设计与逻辑级验证,uni-app x 端未实测(市场平台声明中标注为不确定)。在 x 项目中使用请先自行评估。
技术支持
- 使用问题与机型适配反馈请通过插件市场页面联系作者;
- 反馈时请提供:手机型号、HBuilderX 版本、调用代码片段、
code/message与完整日志。
更新记录
见 changelog.md。授权条款见 license.md。

收藏人数:
购买源码授权版(
试用
赞赏(0)
下载 13
赞赏 0
下载 12715951
赞赏 1958
赞赏
京公网安备:11010802035340号