Skip to content

About

水印相机 uni-app 原生插件,支持拍照和录制视频,自动叠加位置、公司、部门、姓名、时间、日期等水印,支持前后摄像头切换、自定义视频时长、预览删除与缓存清理,适用于打卡考勤、外勤巡检、现场取证等场景,Android / iOS 双端可用。

Resources

Stars

2 stars

Watchers

0 watching

Forks

Repository files navigation

水印相机插件

水印相机插件,支持拍照和录制视频,自动添加水印信息(位置、公司、部门、姓名、时间等),支持前后摄像头切换,可用于打卡、考勤、外勤等场景。

功能特性

  • ✅ 支持拍照和录制视频
  • ✅ 自动添加水印信息(位置、公司、部门、姓名、时间等)
  • ✅ 支持前后摄像头切换
  • ✅ 支持设置视频最大录制时长
  • ✅ 支持预览和删除已拍摄的照片/视频
  • ✅ 支持清除缓存

平台支持

  • ✅ Android(最低版本:23)
  • ✅ iOS(最低版本:13.0)

安装

  1. 在 uni-app 项目中,通过 HBuilderX 导入插件
  2. 或手动将 uni_modules/watermark_camera 目录复制到项目的 uni_modules 目录下

权限配置

使用前请确保在 manifest.json 中配置了以下权限:

Android

{
  "app-plus": {
    "distribute": {
      "android": {
        "permissions": [
          "<uses-permission android:name=\"android.permission.CAMERA\"/>",
          "<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>",
          "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
          "<uses-feature android:name=\"android.hardware.camera\"/>",
          "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>"
        ]
      }
    }
  }
}

iOS

在 manifest.json 的 app-plus -> distribute -> ios 中配置:

{
  "NSCameraUsageDescription": "需要使用相机进行拍照和录制视频",
  "NSMicrophoneUsageDescription": "需要录制视频时使用麦克风"
}

使用方法

SDK初始化(必须)

重要: 在使用其他功能之前,必须先初始化SDK并设置许可证密钥。

在 App.vue 的 onLaunch 生命周期中自动初始化SDK:

<script>
  import { init } from "@/uni_modules/watermark_camera"
  
  export default {
    onLaunch: function() {
      // #ifdef APP-PLUS
      // 仅在App平台初始化
      
      // #ifdef APP-PLUS-ANDROID
      // Android 平台的 license(注意:Android 和 iOS 需要使用不同的 license)
      const androidLicenseKey = `-----BEGIN RLICENSE-----
version: 1
issuer: R
platforms: android
identifiers: your.android.bundle.id
description: 水印相机许可证(仅限Android平台)
tps_limit: -1
not_before: 1766897395
not_after: 1769489395
not_before_utc: 2025-12-28T04:49:55Z
not_after_utc: 2026-01-27T04:49:55Z
features: watermark_camera
device_ids: 
aes_keys: 0,9,68
xor_key: your-xor-key
blob:
your-license-blob-here
-----END RLICENSE-----
      `;
      init(androidLicenseKey).then((result) => {
        if (result.code === 0) {
          console.log('Android SDK初始化成功');
        } else {
          console.error('Android SDK初始化失败:', result.msg);
        }
      }).catch((error) => {
        console.error('Android SDK初始化异常:', error);
      });
      // #endif
      
      // #ifdef APP-PLUS-IOS
      // iOS 平台的 license(注意:Android 和 iOS 需要使用不同的 license)
      const iosLicenseKey = `-----BEGIN RLICENSE-----
version: 1
issuer: R
platforms: ios
identifiers: com.your.bundle.id
description: 水印相机许可证(仅限iOS平台)
tps_limit: -1
not_before: 1766927103
not_after: 1769519103
not_before_utc: 2025-12-28T13:05:03Z
not_after_utc: 2026-01-27T13:05:03Z
features: watermark_camera
device_ids:
blob:
your-license-blob-here
-----END RLICENSE-----
      `;
      init(iosLicenseKey).then((result) => {
        if (result.code === 0) {
          console.log('iOS SDK初始化成功');
        } else {
          console.error('iOS SDK初始化失败:', result.msg);
        }
      }).catch((error) => {
        console.error('iOS SDK初始化异常:', error);
      });
      // #endif
      
      // #endif
    }
  }
</script>

注意事项:

  • 必须在应用启动时(App.vue 的 onLaunch)初始化SDK
  • 重要:Android 和 iOS 必须使用不同的 license 密钥,因为 license 中包含平台标识(platforms: android 或 platforms: ios)
  • 许可证密钥必须包含 watermark_camera 功能授权
  • Android license 的 identifiers 字段应填写 Android 应用的包名(bundle ID)
  • iOS license 的 identifiers 字段应填写 iOS 应用的 Bundle Identifier
  • 如果许可证验证失败,会返回错误码 -1 和错误信息
  • 初始化失败时,后续调用 openMediaCamera 也会失败(iOS 会返回 LICENSE_NOT_ACTIVATED 或 LICENSE_INVALID 错误)

导入插件

import { init, openMediaCamera, clearCache } from "@/uni_modules/watermark_camera"

注意: init 方法已在 App.vue 中调用,通常不需要在其他地方再次调用。

API 接口

1. openMediaCamera - 打开水印相机

打开水印相机界面,支持拍照和录制视频。

函数签名:

openMediaCamera(optionsString: string): Promise<MediaResult>

参数说明:

optionsString (string): JSON字符串格式的配置对象,包含以下字段:

参数名 类型 必填 说明
location string 否 位置信息,将显示在水印中
company string 否 公司名称,将显示在水印中
department string 否 部门名称,将显示在水印中
name string 否 姓名,将显示在水印中
videoMaxDuration number 否 视频最大录制时长(秒),默认30秒

返回值:

返回 Promise<MediaResult>,包含以下字段:

字段名 类型 说明
code string 状态码,SUCCESS 表示成功,其他表示失败
msg string 结果描述
photoPaths string[] 照片路径数组
videoPaths string[] 视频路径数组

状态码说明:

状态码 说明
SUCCESS 操作成功
CANCEL 用户取消操作
EXCEPTION 执行异常
CAMERA_PERMISSION_EXCEPTION 相机权限未授予
EXPIRED SDK已过期
LICENSE_NOT_ACTIVATED License未激活(iOS)
LICENSE_INVALID License无效(iOS)

使用示例:

// 注意:SDK已在App.vue中自动初始化,这里直接使用即可

const options = {
  location: "北京市朝阳区",
  company: "示例公司",
  department: "技术部",
  name: "张三",
  videoMaxDuration: 30
};

const result = await openMediaCamera(JSON.stringify(options));

if (result.code === "SUCCESS") {
  console.log("照片路径:", result.photoPaths);
  console.log("视频路径:", result.videoPaths);
} else {
  console.error("操作失败:", result.msg);
}

2. clearCache - 清除缓存

清除插件生成的照片、视频、日志等缓存文件。

函数签名:

clearCache(): Promise<ClearCacheResult>

返回值:

返回 Promise<ClearCacheResult>,包含以下字段:

字段名 类型 说明
code number 状态码,0 表示成功,-1 表示失败
msg string 结果描述

使用示例:

const result = await clearCache();
if (result.code === 0) {
  console.log("缓存清除成功");
} else {
  console.error("缓存清除失败:", result.msg);
}

完整示例

<template>
  <view class="container">
    <view class="form">
      <input v-model="location" placeholder="位置信息" />
      <input v-model="company" placeholder="公司名称" />
      <input v-model="department" placeholder="部门名称" />
      <input v-model="name" placeholder="姓名" />
      <input v-model.number="videoMaxDuration" type="number" placeholder="视频最大时长(秒)" />
    </view>
    
    <button @click="openCamera">打开水印相机</button>
    <button @click="clearCacheData">清除缓存</button>
    
    <view v-if="result" class="result">
      <text>状态:{{ result.code }}</text>
      <text>消息:{{ result.msg }}</text>
      <text v-if="result.photoPaths && result.photoPaths.length > 0">
        照片数量:{{ result.photoPaths.length }}
      </text>
      <text v-if="result.videoPaths && result.videoPaths.length > 0">
        视频数量:{{ result.videoPaths.length }}
      </text>
    </view>
  </view>
</template>

<script lang="ts">
import { openMediaCamera, clearCache } from "@/uni_modules/watermark_camera"

export default {
  data() {
    return {
      location: "北京市朝阳区",
      company: "示例公司",
      department: "技术部",
      name: "张三",
      videoMaxDuration: 30,
      result: null as any
    }
  },
  methods: {
    async openCamera() {
      try {
        const options = {
          location: this.location,
          company: this.company,
          department: this.department,
          name: this.name,
          videoMaxDuration: this.videoMaxDuration
        };
        
        const result = await openMediaCamera(JSON.stringify(options));
        this.result = result;
        
        if (result.code === "SUCCESS") {
          uni.showToast({
            title: "操作成功",
            icon: "success"
          });
          
          // 处理照片和视频
          if (result.photoPaths && result.photoPaths.length > 0) {
            console.log("照片路径:", result.photoPaths);
            // 可以在这里上传照片到服务器
          }
          
          if (result.videoPaths && result.videoPaths.length > 0) {
            console.log("视频路径:", result.videoPaths);
            // 可以在这里上传视频到服务器
          }
        } else if (result.code === "CANCEL") {
          uni.showToast({
            title: "用户取消",
            icon: "none"
          });
        } else {
          uni.showToast({
            title: result.msg || "操作失败",
            icon: "none"
          });
        }
      } catch (error) {
        console.error("打开相机失败:", error);
        uni.showToast({
          title: "打开相机失败",
          icon: "none"
        });
      }
    },
    
    async clearCacheData() {
      try {
        const result = await clearCache();
        if (result.code === 0) {
          uni.showToast({
            title: "缓存清除成功",
            icon: "success"
          });
        } else {
          uni.showToast({
            title: "缓存清除失败",
            icon: "none"
          });
        }
      } catch (error) {
        console.error("清除缓存失败:", error);
        uni.showToast({
          title: "清除缓存失败",
          icon: "none"
        });
      }
    }
  }
}
</script>

<style>
.container {
  padding: 20px;
}

.form {
  margin-bottom: 20px;
}

.form input {
  width: 100%;
  padding: 10px;
  margin-bottom: 10px;
  border: 1px solid #ddd;
  border-radius: 4px;
}

button {
  width: 100%;
  padding: 12px;
  margin-bottom: 10px;
  background-color: #007aff;
  color: white;
  border: none;
  border-radius: 4px;
}

.result {
  margin-top: 20px;
  padding: 10px;
  background-color: #f5f5f5;
  border-radius: 4px;
}

.result text {
  display: block;
  margin-bottom: 5px;
}
</style>

使用说明

拍照和录制视频

  • 拍照:点击快门按钮进行拍照
  • 录制视频:长按快门按钮开始录制,松开结束录制
  • 切换摄像头:点击切换按钮切换前后摄像头
  • 预览:点击缩略图可以预览照片或视频
  • 删除:点击缩略图右上角的删除按钮可以删除已拍摄的照片或视频
  • 完成:点击完成按钮返回结果

水印信息

水印会自动添加到拍摄的照片上,包含以下信息:

  • 标题:"外出打卡"
  • 时间:当前时间(HH:mm:ss)
  • 日期:当前日期(yyyy-MM-dd)
  • 位置:传入的位置信息
  • 公司-部门-姓名:传入的公司、部门、姓名信息
  • 声明:"本人办公已验证身份信息真实性"

文件存储

  • 照片和视频存储在应用的私有目录中
  • 照片格式:JPG
  • 视频格式:MP4
  • 文件命名:esand_时间戳.扩展名

注意事项

  1. 权限申请:首次使用需要授予相机和麦克风权限
  2. 文件路径:返回的文件路径是本地路径,需要上传到服务器时请使用 uni.uploadFile 等方法
  3. 视频时长:视频最大录制时长受 videoMaxDuration 参数限制,达到最大时长会自动停止录制
  4. 缓存清理:定期清理缓存可以释放存储空间

常见问题

Q: 为什么返回的文件路径无法直接使用?

A: 返回的文件路径是应用的私有目录路径,如果需要上传到服务器或分享,请使用 uni-app 的文件上传 API。

Q: 如何上传照片和视频到服务器?

A: 可以使用 uni.uploadFile API:

// 上传照片
for (const photoPath of result.photoPaths) {
  uni.uploadFile({
    url: 'https://your-server.com/upload',
    filePath: photoPath,
    name: 'file',
    success: (res) => {
      console.log('上传成功', res);
    }
  });
}

Q: 水印信息可以自定义吗?

A: 当前版本的水印样式是固定的,但可以通过传入不同的参数来改变水印内容(位置、公司、部门、姓名)。

Q: 支持哪些平台?

A: 当前版本支持 Android(最低版本 23)和 iOS(最低版本 13.0)。

Q: iOS 平台如何初始化 SDK?

A: iOS 平台的初始化方式与 Android 完全一致,在 App.vue 的 onLaunch 中使用条件编译分别调用 init(licenseKey) 即可。重要:Android 和 iOS 必须使用不同的 license 密钥,因为 license 中包含平台标识。请确保:

  • Android license 的 platforms 字段为 android
  • iOS license 的 platforms 字段为 ios
  • 两个 license 的 identifiers 字段分别对应各自的包名/Bundle ID

更新日志

详见 changelog.md

许可证

MIT License

联系方式

如有问题或建议,请通过以下方式联系:

  • 微信:esand_info
  • QQ:3626921591
  • 电话:+8613691664797
  • 邮箱:reid.li@foxmail.com
  • Telegram:@R90000000
  • 微信二维码:

微信二维码

扫描上方二维码添加微信,或直接搜索微信号:esand_info

About

水印相机 uni-app 原生插件,支持拍照和录制视频,自动叠加位置、公司、部门、姓名、时间、日期等水印,支持前后摄像头切换、自定义视频时长、预览删除与缓存清理,适用于打卡考勤、外勤巡检、现场取证等场景,Android / iOS 双端可用。

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages