Ver código fonte

feat(privacy): 添加隐私协议弹窗组件

新增隐私协议弹窗组件 privacy-popup,用于处理微信小程序的隐私授权需求。组件包含同意/拒绝按钮,并支持打开隐私协议链接。同时在全局组件声明中添加了相关组件注册。
```

这个提交消息:
1. 使用了正确的类型 `feat` 表示新增功能
2. 添加了适当的范围 `(privacy)` 表明是隐私相关功能
3. 简洁描述了新增的功能(隐私协议弹窗组件)
4. 在正文中补充说明了组件的用途和主要功能点
5. 符合中文语言要求
6. 遵循了50字符限制(标题部分)
7. 使用了命令式语气
feige996 11 meses atrás
pai
commit
a7795a9b98

+ 47 - 0
src/components/privacy-popup/index.scss

@@ -0,0 +1,47 @@
+@import 'wot-design-uni/components/wd-button/index.scss';
+:deep(.wd-privacy-popup) {
+  width: 600rpx;
+  padding: 0 24rpx;
+  box-sizing: border-box;
+  border-radius: 32rpx;
+  overflow: hidden;
+}
+
+.wd-privacy-popup {
+  &__header {
+    width: 100%;
+    height: 128rpx;
+    line-height: 128rpx;
+    color: rgba(0, 0, 0, 0.85);
+    font-size: 30rpx;
+    padding: 0 12rpx;
+    box-sizing: border-box;
+  }
+
+  &__container {
+    width: 100%;
+    box-sizing: border-box;
+    padding: 0 12rpx;
+    margin-bottom: 32rpx;
+
+    font-size: 28rpx;
+    line-height: 1.8;
+    color: #3e3e3e;
+    text-align: left;
+    font-weight: 550;
+    &-protocol {
+      color: #4d80f0;
+    }
+  }
+
+  &__footer {
+    display: flex;
+    justify-content: space-between;
+    padding-bottom: 36rpx;
+
+    button {
+      border: none;
+      outline: none;
+    }
+  }
+}

+ 144 - 0
src/components/privacy-popup/privacy-popup.vue

@@ -0,0 +1,144 @@
+<template>
+  <view>
+    <wd-popup
+      v-model="showPopup"
+      :close-on-click-modal="false"
+      custom-class="wd-privacy-popup"
+      @close="handleClose"
+    >
+      <view class="wd-privacy-popup__header">
+        <!--标题-->
+        <view class="wd-picker__title">{{ title }}</view>
+      </view>
+      <view class="wd-privacy-popup__container">
+        <text>{{ desc }}</text>
+        <text class="wd-privacy-popup__container-protocol" @click="openPrivacyContract">
+          {{ protocol }}
+        </text>
+        <text>{{ subDesc }}</text>
+      </view>
+      <view class="wd-privacy-popup__footer">
+        <button
+          class="wd-privacy-popup__footer-disagree wd-button is-block is-round is-medium is-plain"
+          id="disagree-btn"
+          @click="handleDisagree"
+        >
+          拒绝
+        </button>
+        <button
+          class="wd-privacy-popup__footer-agree wd-button is-primary is-block is-round is-medium"
+          id="agree-btn"
+          open-type="agreePrivacyAuthorization"
+          @agreeprivacyauthorization="handleAgree"
+        >
+          同意
+        </button>
+      </view>
+    </wd-popup>
+  </view>
+</template>
+
+<script lang="ts">
+export default {
+  name: 'privacy-popup',
+  options: {
+    virtualHost: true,
+    addGlobalClass: true,
+    styleIsolation: 'shared',
+  },
+}
+</script>
+
+<script lang="ts" setup>
+import { onBeforeMount, ref } from 'vue'
+
+type Props = {
+  title?: string // 标题
+  desc?: string // 描述
+  subDesc?: string // 字描述
+  protocol?: string // 协议名称
+}
+
+const props = withDefaults(defineProps<Props>(), {
+  title: '用户隐私保护提示',
+  desc: '感谢您使用本应用,您使用本应用的服务之前请仔细阅读并同意',
+  subDesc:
+    '。当您点击同意并开始时用产品服务时,即表示你已理解并同息该条款内容,该条款将对您产生法律约束力。如您拒绝,将无法使用相应服务。',
+  protocol: '《用户隐私保护指引》',
+})
+
+const showPopup = ref<boolean>(false) // 是否展示popup
+
+const privacyResolves = ref(new Set()) // onNeedPrivacyAuthorization的reslove
+
+const privacyHandler = (resolve: any) => {
+  showPopup.value = true
+  privacyResolves.value.add(resolve)
+}
+
+const emit = defineEmits(['agree', 'disagree'])
+
+onBeforeMount(() => {
+  // 注册监听
+  if ((wx as any).onNeedPrivacyAuthorization) {
+    ;(wx as any).onNeedPrivacyAuthorization((resolve: any) => {
+      if (typeof privacyHandler === 'function') {
+        privacyHandler(resolve)
+      }
+    })
+  }
+})
+
+/**
+ * 同意隐私协议
+ */
+function handleAgree() {
+  showPopup.value = false
+  privacyResolves.value.forEach((resolve: any) => {
+    resolve({
+      event: 'agree',
+      buttonId: 'agree-btn',
+    })
+  })
+  privacyResolves.value.clear()
+  emit('agree')
+}
+
+/**
+ * 拒绝隐私协议
+ */
+function handleDisagree() {
+  showPopup.value = false
+  privacyResolves.value.forEach((resolve: any) => {
+    resolve({
+      event: 'disagree',
+    })
+  })
+  privacyResolves.value.clear()
+}
+
+/**
+ * 打开隐私协议
+ */
+function openPrivacyContract() {
+  ;(wx as any).openPrivacyContract({
+    success: (res) => {
+      console.log('openPrivacyContract success')
+    },
+    fail: (res) => {
+      console.error('openPrivacyContract fail', res)
+    },
+  })
+}
+
+/**
+ * 弹出框关闭时清空
+ */
+function handleClose() {
+  privacyResolves.value.clear()
+}
+</script>
+
+<style lang="scss" scoped>
+@import './index.scss';
+</style>

+ 1 - 0
src/layouts/default.vue

@@ -3,6 +3,7 @@
     <slot />
     <wd-toast />
     <wd-message-box />
+    <privacy-popup />
   </wd-config-provider>
 </template>
 

+ 3 - 0
src/types/components.d.ts

@@ -8,5 +8,8 @@ export {}
 declare module 'vue' {
   export interface GlobalComponents {
     FgNavbar: typeof import('./../components/fg-navbar/fg-navbar.vue')['default']
+    FgTabbar: typeof import('./../components/fg-tabbar/fg-tabbar.vue')['default']
+    PrivacyPopup: typeof import('./../components/privacy-popup/privacy-popup.vue')['default']
+    Tabbar: typeof import('./../components/tabbar/tabbar.vue')['default']
   }
 }