更新记录

1.0.0(2026-06-01)

首次发布,包含基础弹窗、自定义按钮、高亮文本、链接跳转等功能


平台兼容性

uni-app(3.7.8)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
-
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
- - - - - - - -

Agreement Popup 组件

组件介绍

Agreement Popup 是一个用于展示协议内容并获取用户同意的弹窗组件,支持以下特性:

  • 自动识别并处理《书名号》内的链接文本
  • 支持自定义高亮文本(可配置颜色和点击事件)
  • 可自定义标题、按钮文本和样式
  • 支持点击遮罩关闭功能

安装方法

将组件文件夹 agreement-popup 复制到项目的 components 目录下。

基本使用

引入组件

<template>
  <view class="container">
    <button @click="showDialog">显示协议弹窗</button>

    <agreementPopup
      ref="privacyDialog"
      title="用户协议"
      :content="agreementContent"
      :linkKeyMap="linkKeyMap"
      disagree-text="不同意"
      agree-text="同意"
      :mask-click="false"
      @agree="onAgree"
      @disagree="onDisagree"
      @linkClick="onLinkClick">
    </agreementPopup>
  </view>
</template>

<script setup>
import { ref } from 'vue'
import agreementPopup from '@/components/agreement-popup/agreement-popup.vue'

const privacyDialog = ref(null)
const agreementContent = ref('请您仔细阅读《用户服务协议》和《隐私政策》,并充分理解协议内容。')
const linkKeyMap = ref({
  '用户服务协议': 'service',
  '隐私政策': 'privacy'
})

const showDialog = () => {
  privacyDialog.value?.open()
}

const onAgree = () => {
  console.log('用户点击了同意')
  // 处理同意逻辑
}

const onDisagree = () => {
  console.log('用户点击了不同意')
  // 处理不同意逻辑
}

const onLinkClick = (linkKey) => {
  console.log('用户点击了链接:', linkKey)
  // 根据链接key执行相应操作
  const pageMap = {
    'service': '/pages/sys/agreement/index?type=service',
    'privacy': '/pages/sys/agreement/index?type=privacy'
  }
  if (pageMap[linkKey]) {
    uni.navigateTo({ url: pageMap[linkKey] })
  }
}
</script>

API 说明

Props

参数 类型 默认值 说明
title String '隐私协议' 弹窗标题
titleType String 'primary' 标题类型,可选值:primary, del, success, warning
content String '' 弹窗内容,支持《书名号》链接和{{高亮文本}}语法
linkKeyMap Object {} 链接文本到标识的映射,如:{"用户协议": "service"}
disagreeText String '不同意' 不同意按钮文字
agreeText String '同意' 同意按钮文字
maskClick Boolean false 是否允许点击遮罩关闭弹窗
btnType String 'primary' 同意按钮类型,可选值:primary, no-background
defaultHighlightColor String '#FF4444' 高亮文本的默认颜色
buttons Array [] 按钮配置数组,优先级高于默认按钮,格式:[{text: '按钮文本', type: 'primary secondary outline', action: 'agree disagree custom', customAction: '自定义事件名'}]

Events

事件名 参数 说明
agree - 点击同意按钮时触发
disagree - 点击不同意按钮时触发
linkClick linkKey: String 点击《书名号》链接时触发,参数为链接标识
highlightClick { text, key, color } 点击可点击的高亮文本时触发
change show: Boolean 弹窗显示/隐藏状态变化时触发
buttonClick { action, button } 点击自定义按钮时触发,参数包含动作标识和按钮配置

方法

方法名 说明
open() 打开弹窗
close() 关闭弹窗

高级用法

高亮文本语法

组件支持以下高亮文本语法:

语法 效果 行为
{{普通高亮}} 红色文本 不可点击
{{可点击高亮 clickable}} 红色带下划线文本 可点击,触发 highlightClick 事件
{{自定义颜色 #FF6600}} 橙色文本 不可点击
{{橙色可点击 #FF6600 clickable}} 橙色带下划线文本 可点击
{{带标识的可点击 clickable myKey}} 红色带下划线文本 可点击,返回标识 myKey

高亮文本使用示例

<template>
  <agreementPopup
    ref="dialog"
    title="操作确认"
    :content="dialogContent"
    @agree="onAgree"
    @highlightClick="onHighlightClick">
  </agreementPopup>
</template>

<script setup>
import { ref } from 'vue'
import agreementPopup from '@/components/agreement-popup/agreement-popup.vue'

const dialog = ref(null)
const dialogContent = ref(`关闭服务后{{系统将同时删除人脸信息}},校园消费、门禁考勤等设备将{{立即无法使用人脸识别功能|#FF6600|clickable|device_warning}}。{{查看详情|#007AFF|clickable|detail}}确认关闭吗?`)

const onAgree = () => {
  console.log('用户确认关闭')
}

const onHighlightClick = (data) => {
  console.log('高亮文本点击:', data)
  // data = { text: '立即无法使用人脸识别功能', key: 'device_warning', color: '#FF6600' }

  if (data.key === 'device_warning') {
    uni.showModal({
      title: '提示',
      content: '关闭后将无法使用人脸识别功能',
      showCancel: false
    })
  } else if (data.key === 'detail') {
    uni.navigateTo({ url: '/pages/service/detail' })
  }
}
</script>

多行文本和换行

内容支持使用 \n 实现换行:

const agreementContent = ref('尊敬的用户:\n感谢您使用本产品。\n请您仔细阅读《用户协议》。')

完整示例

示例1:隐私协议弹窗(默认按钮)

<template>
  <view class="container">
    <button @click="showPrivacyDialog">显示隐私协议</button>

    <agreementPopup
      ref="privacyDialog"
      title="隐私协议"
      :content="privacyContent"
      :linkKeyMap="linkKeyMap"
      disagree-text="拒绝"
      agree-text="同意并继续"
      :mask-click="false"
      @agree="onAgreePrivacy"
      @linkClick="onLinkClick">
    </agreementPopup>
  </view>
</template>

<script setup>
import { ref } from 'vue'
import agreementPopup from '@/components/agreement-popup/agreement-popup.vue'

const privacyDialog = ref(null)
const privacyContent = ref('尊敬的用户:\n感谢您使用本产品,我们非常注重保护用户的隐私信息。《用户隐私协议》是我们针对用户在使用本产品时,就信息的收集、储存与保护等相关规则所做出的声明。请您仔细阅读充分理解相关内容,若您同意以上协议内容,请点击"同意并继续"开始使用本产品。')
const linkKeyMap = ref({'用户隐私协议': 'privacy'})

const showPrivacyDialog = () => {
  privacyDialog.value?.open()
}

const onAgreePrivacy = () => {
  console.log('用户同意隐私协议')
  // 保存同意状态
  uni.setStorageSync('privacyAgreed', true)
  // 继续下一步操作
}

const onLinkClick = (linkKey) => {
  if (linkKey === 'privacy') {
    uni.navigateTo({ url: '/pages/sys/agreement/index?type=privacy' })
  }
}
</script>

示例2:删除确认弹窗(默认按钮)

<template>
  <view class="container">
    <button @click="showDeleteDialog">删除人脸信息</button>

    <agreementPopup
      ref="deleteDialog"
      title="人脸删除提示"
      title-type="del"
      :content="deleteContent"
      disagree-text="确认删除"
      agree-text="取消"
      btn-type="no-background"
      :mask-click="false"
      @disagree="confirmDelete"
      @agree="cancelDelete">
    </agreementPopup>
  </view>
</template>

<script setup>
import { ref } from 'vue'
import agreementPopup from '@/components/agreement-popup/agreement-popup.vue'

const deleteDialog = ref(null)
const deleteContent = ref('即将删除人脸信息,删除后将无法使用人脸识别相关功能,操作不可逆,确认继续删除吗?')

const showDeleteDialog = () => {
  deleteDialog.value?.open()
}

const confirmDelete = () => {
  console.log('用户确认删除人脸')
  // 执行删除操作
  deleteFaceInfo()
}

const cancelDelete = () => {
  console.log('用户取消删除')
}

const deleteFaceInfo = () => {
  // 调用删除人脸的API
  uni.showToast({ title: '人脸信息已删除', icon: 'success' })
}
</script>

示例3:单个按钮弹窗

<template>
  <view class="container">
    <button @click="showSingleButtonDialog">显示单按钮弹窗</button>

    <agreementPopup
      ref="singleButtonDialog"
      title="操作成功"
      content="您的操作已成功完成"
      :buttons="[
        {
          text: '确定',
          type: 'primary',
          action: 'agree'
        }
      ]"
      :mask-click="false"
      @agree="onAgree">
    </agreementPopup>
  </view>
</template>

<script setup>
import { ref } from 'vue'
import agreementPopup from '@/components/agreement-popup/agreement-popup.vue'

const singleButtonDialog = ref(null)

const showSingleButtonDialog = () => {
  singleButtonDialog.value?.open()
}

const onAgree = () => {
  console.log('用户点击了确定')
  // 处理确定逻辑
}
</script>

示例4:自定义双按钮弹窗

<template>
  <view class="container">
    <button @click="showCustomButtonsDialog">显示自定义按钮弹窗</button>

    <agreementPopup
      ref="customButtonsDialog"
      title="确认操作"
      content="确定要执行此操作吗?"
      :buttons="[
        {
          text: '取消',
          type: 'secondary',
          action: 'disagree'
        },
        {
          text: '确定',
          type: 'primary',
          action: 'agree'
        }
      ]"
      :mask-click="false"
      @agree="onAgree"
      @disagree="onDisagree">
    </agreementPopup>
  </view>
</template>

<script setup>
import { ref } from 'vue'
import agreementPopup from '@/components/agreement-popup/agreement-popup.vue'

const customButtonsDialog = ref(null)

const showCustomButtonsDialog = () => {
  customButtonsDialog.value?.open()
}

const onAgree = () => {
  console.log('用户点击了确定')
  // 处理确定逻辑
}

const onDisagree = () => {
  console.log('用户点击了取消')
  // 处理取消逻辑
}
</script>

示例5:多按钮(包含自定义动作)

<template>
  <view class="container">
    <button @click="showMultiButtonDialog">显示多按钮弹窗</button>

    <agreementPopup
      ref="multiButtonDialog"
      title="选择操作"
      content="请选择您要执行的操作"
      :buttons="[
        {
          text: '查看详情',
          type: 'outline',
          action: 'custom',
          customAction: 'viewDetail'
        },
        {
          text: '删除',
          type: 'secondary',
          action: 'custom',
          customAction: 'delete'
        },
        {
          text: '确定',
          type: 'primary',
          action: 'agree'
        }
      ]"
      :mask-click="false"
      @agree="onAgree"
      @buttonClick="onButtonClick">
    </agreementPopup>
  </view>
</template>

<script setup>
import { ref } from 'vue'
import agreementPopup from '@/components/agreement-popup/agreement-popup.vue'

const multiButtonDialog = ref(null)

const showMultiButtonDialog = () => {
  multiButtonDialog.value?.open()
}

const onAgree = () => {
  console.log('用户点击了确定')
  // 处理确定逻辑
}

const onButtonClick = (data) => {
  console.log('自定义按钮点击:', data)
  if (data.action === 'viewDetail') {
    // 查看详情逻辑
    uni.navigateTo({ url: '/pages/detail/index' })
  } else if (data.action === 'delete') {
    // 删除逻辑
    uni.showToast({ title: '删除成功', icon: 'success' })
  }
}
</script>

注意事项

  1. 组件依赖 uni-popup 组件,确保项目中已安装或引入该组件
  2. 内容文本中的《书名号》会被自动识别为链接,需要在 linkKeyMap 中配置对应的标识
  3. 高亮文本语法使用 {{}} 包裹,可根据需要配置颜色和点击事件
  4. 组件支持通过 ref 调用 open()close() 方法控制弹窗显示/隐藏
  5. 当提供 buttons 属性时,会忽略默认的 agreeTextdisagreeTextbtnType 属性
  6. 按钮类型 type 支持:primary(主按钮)、secondary(次要按钮)、outline(描边按钮)
  7. 按钮动作 action 支持:agree(同意)、disagree(不同意)、custom(自定义动作)
  8. actioncustom 时,需要提供 customAction 属性来标识自定义动作

浏览器兼容性

  • 微信小程序:支持
  • 支付宝小程序:支持
  • H5:支持
  • 其他平台:未测试

更新日志

  • v1.0.0:初始版本,支持基本功能和高亮文本语法

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件不采集任何数据

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

暂无用户评论。