更新记录
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>
注意事项
- 组件依赖
uni-popup 组件,确保项目中已安装或引入该组件
- 内容文本中的《书名号》会被自动识别为链接,需要在
linkKeyMap 中配置对应的标识
- 高亮文本语法使用
{{}} 包裹,可根据需要配置颜色和点击事件
- 组件支持通过
ref 调用 open() 和 close() 方法控制弹窗显示/隐藏
- 当提供
buttons 属性时,会忽略默认的 agreeText、disagreeText 和 btnType 属性
- 按钮类型
type 支持:primary(主按钮)、secondary(次要按钮)、outline(描边按钮)
- 按钮动作
action 支持:agree(同意)、disagree(不同意)、custom(自定义动作)
- 当
action 为 custom 时,需要提供 customAction 属性来标识自定义动作
浏览器兼容性
- 微信小程序:支持
- 支付宝小程序:支持
- H5:支持
- 其他平台:未测试
更新日志
- v1.0.0:初始版本,支持基本功能和高亮文本语法