Jelajahi Sumber

开发授权弹窗

bayi 1 tahun lalu
induk
melakukan
bc8550eaa8

+ 2 - 1
app.json

@@ -58,5 +58,6 @@
     "resolveAlias": {
         "~/*": "/*"
     },
-    "sitemapLocation": "sitemap.json"
+    "sitemapLocation": "sitemap.json",
+    "__usePrivacyCheck__": true
 }

+ 107 - 104
components/navigationBar/index.js

@@ -1,119 +1,122 @@
 const app = getApp()
 import {
-  setUserInfo
+    setUserInfo
 } from '~/api/user'
 import {
-  storeBindingsBehavior
+    storeBindingsBehavior
 } from 'mobx-miniprogram-bindings'
 import {
-  store
+    store
 } from '~/store/index'
 let timer
 Component({
-  // 自动绑定
-  behaviors: [storeBindingsBehavior],
-  storeBindings: {
-    store,
-    fields: {
-      userInfo: 'userInfo'
+    // 自动绑定
+    behaviors: [storeBindingsBehavior],
+    storeBindings: {
+        store,
+        fields: {
+            userInfo: 'userInfo'
+        },
+        actions: {
+            setUser: 'setUser'
+        }
     },
-    actions: {
-      setUser: 'setUser'
-    }
-  },
-  properties: {
-    title: {
-      type: String,
-      value: '朗读小咖秀',
-    },
-    showNav: {
-      type: Boolean,
-      value: true
-    }
-  },
-  data: {
-    navBarHeight: app.globalData.navBarHeight,
-    menuRight: app.globalData.menuRight,
-    menuTop: app.globalData.menuTop,
-    menuHeight: app.globalData.menuHeight,
-    isGradeShow: false,
-    temporaryGrade: null
-  },
-  pageLifetimes: {
-    show() {
-      if (!this.data.userInfo.grade) {
-        timer = setInterval(() => {
-          if (this.data.userInfo.uid && !this.data.userInfo.grade) {
-            this.showGrade()
-            clearInterval(timer)
-          } else if (this.data.userInfo.uid && this.data.userInfo.grade) {
-            clearInterval(timer)
-          }
-        }, 500)
-      }
+    properties: {
+        title: {
+            type: String,
+            value: '朗读小咖秀',
+        },
+        showNav: {
+            type: Boolean,
+            value: true
+        }
     },
-    hide() {
-      clearInterval(timer)
-    }
-  },
-  methods: {
-    closeGrade() {
-      if (!this.data.userInfo.grade) {
-        return
-      }
-      this.setData({
+    data: {
+        navBarHeight: app.globalData.navBarHeight,
+        menuRight: app.globalData.menuRight,
+        menuTop: app.globalData.menuTop,
+        menuHeight: app.globalData.menuHeight,
         isGradeShow: false,
-      })
-      if (typeof this.getTabBar === 'function') {
-        this.getTabBar().setData({
-          mask: false
-        })
-      }
-    },
-    // 选择年级
-    selectGrade({
-      target
-    }) {
-      let code = target.dataset.code
-      if (!code) {
-        return
-      }
-      this.setData({
-        temporaryGrade: code
-      })
-    },
-    showGrade() {
-      if (typeof this.getTabBar === 'function') {
-        this.getTabBar().setData({
-          mask: true
-        })
-      }
-      if (this.data.isGradeShow) {
-        return
-      }
-      this.setData({
-        isGradeShow: true,
-        temporaryGrade: this.data.userInfo.grade
-      })
+        temporaryGrade: null
     },
-    // 修改年级
-    async changeGrade(e) {
-      const grade = this.data.temporaryGrade
-      if (!grade) {
-        return wx.showToast({
-          title: '请选择年级',
-          icon: 'none',
-          duration: 2000
-        })
-      }
-      let res = await setUserInfo({
-        grade
-      }, 'put')
-      this.setUser(res)
-      this.closeGrade()
-      setTimeout(() => {
-        this.triggerEvent('reload')
-      }, 300)
+    pageLifetimes: {
+        show() {
+            if (!this.data.userInfo.grade) {
+                timer = setInterval(() => {
+                    if (this.data.userInfo.uid && !this.data.userInfo.grade) {
+                        this.showGrade()
+                        clearInterval(timer)
+                    } else if (this.data.userInfo.uid && this.data.userInfo.grade) {
+                        clearInterval(timer)
+                    }
+                }, 500)
+            }
+        },
+        hide() {
+            clearInterval(timer)
+        }
     },
-  }
+    methods: {
+        closeGrade() {
+            if (!this.data.userInfo.grade) {
+                return
+            }
+            this.setData({
+                isGradeShow: false,
+            })
+            if (typeof this.getTabBar === 'function') {
+                this.getTabBar().setData({
+                    mask: false
+                })
+            }
+        },
+        // 选择年级
+        selectGrade({
+            target
+        }) {
+            let code = target.dataset.code
+            if (!code) {
+                return
+            }
+            this.setData({
+                temporaryGrade: code
+            })
+        },
+        showGrade() {
+            if (typeof this.getTabBar === 'function') {
+                this.getTabBar().setData({
+                    mask: true
+                })
+            }
+            if (this.data.isGradeShow) {
+                return
+            }
+            this.setData({
+                isGradeShow: true,
+                temporaryGrade: this.data.userInfo.grade
+            })
+        },
+        // 修改年级
+        async changeGrade(e) {
+            const grade = this.data.temporaryGrade
+            if (!grade) {
+                return wx.showToast({
+                    title: '请选择年级',
+                    icon: 'none',
+                    duration: 2000
+                })
+            }
+            let res = await setUserInfo({
+                grade
+            }, 'put')
+            this.setUser(res)
+            this.closeGrade()
+            setTimeout(() => {
+                this.triggerEvent('reload')
+            }, 300)
+        },
+        agree(e) {
+            console.log("用户同意隐私授权, 接下来可以调用隐私协议中声明的隐私接口")
+        },
+    }
 })

+ 5 - 3
components/navigationBar/index.json

@@ -1,5 +1,7 @@
 {
-  "component": true,
-  "usingComponents": {},
-  "styleIsolation": "apply-shared"
+    "component": true,
+    "usingComponents": {
+        "privacy-popup": "/components/privacyPopup/index"
+    },
+    "styleIsolation": "apply-shared"
 }

+ 39 - 38
components/navigationBar/index.wxml

@@ -1,48 +1,49 @@
 <!-- 自定义顶部栏 -->
 <block wx:if="{{showNav}}">
-  <view class="nav-bar" style="height:{{navBarHeight}}px;">
-    <view class="view" style="height:{{menuHeight}}px;top:{{menuTop}}px;">
-      <view class="selectGrade" bindtap="showGrade">{{userInfo.gradeName}}</view>
-      <view class="title">{{title}}</view>
+    <view class="nav-bar" style="height:{{navBarHeight}}px;">
+        <view class="view" style="height:{{menuHeight}}px;top:{{menuTop}}px;">
+            <view class="selectGrade" bindtap="showGrade">{{userInfo.gradeName}}</view>
+            <view class="title">{{title}}</view>
+        </view>
     </view>
-  </view>
-  <!-- 
+    <!-- 
   内容区域:
   自定义顶部栏用的fixed定位,会遮盖到下面内容,注意设置好间距
 -->
-  <view class="content" style="margin-top:{{navBarHeight}}px;"></view>
-  <view class="headerBg" style="top:{{navBarHeight}}px;"></view>
+    <view class="content" style="margin-top:{{navBarHeight}}px;"></view>
+    <view class="headerBg" style="top:{{navBarHeight}}px;"></view>
 </block>
 
 <view wx:if="{{isGradeShow}}" class="gradeContainer" catchtouchmove='true' bindtap="closeGrade">
-  <view class="gradeBox zoomIn" catchtap="selectGrade">
-    <view class="title">请选择年级</view>
-    <view class="content">
-      <view class="grade oneRow {{temporaryGrade=='PRESCHOOL'?'check':''}}" data-code="PRESCHOOL">学前班</view>
+    <view class="gradeBox zoomIn" catchtap="selectGrade">
+        <view class="title">请选择年级</view>
+        <view class="content">
+            <view class="grade oneRow {{temporaryGrade=='PRESCHOOL'?'check':''}}" data-code="PRESCHOOL">学前班</view>
+        </view>
+        <view class="content">
+            <view class="grade {{temporaryGrade=='PRIMARY_FIRST_GRADE'?'check':''}}" data-code="PRIMARY_FIRST_GRADE">一年级
+            </view>
+            <view class="grade {{temporaryGrade=='PRIMARY_SECOND_GRADE'?'check':''}}" data-code="PRIMARY_SECOND_GRADE">
+                二年级
+            </view>
+        </view>
+        <view class="content">
+            <view class="grade {{temporaryGrade=='PRIMARY_THREE_GRADE'?'check':''}}" data-code="PRIMARY_THREE_GRADE">三年级
+            </view>
+            <view class="grade {{temporaryGrade=='PRIMARY_SENIOR_GRADE'?'check':''}}" data-code="PRIMARY_SENIOR_GRADE">
+                四年级
+            </view>
+        </view>
+        <view class="content">
+            <view class="grade {{temporaryGrade=='PRIMARY_FIVE_GRADE'?'check':''}}" data-code="PRIMARY_FIVE_GRADE">五年级
+            </view>
+            <view class="grade {{temporaryGrade=='PRIMARY_SIX_GRADE'?'check':''}}" data-code="PRIMARY_SIX_GRADE">
+                六年级
+            </view>
+        </view>
+        <view class="submitBox">
+            <button class="resetBtn submit" bindtap="changeGrade">确定</button>
+        </view>
     </view>
-    <view class="content">
-      <view class="grade {{temporaryGrade=='PRIMARY_FIRST_GRADE'?'check':''}}" data-code="PRIMARY_FIRST_GRADE">一年级
-      </view>
-      <view class="grade {{temporaryGrade=='PRIMARY_SECOND_GRADE'?'check':''}}" data-code="PRIMARY_SECOND_GRADE">
-        二年级
-      </view>
-    </view>
-    <view class="content">
-      <view class="grade {{temporaryGrade=='PRIMARY_THREE_GRADE'?'check':''}}" data-code="PRIMARY_THREE_GRADE">三年级
-      </view>
-      <view class="grade {{temporaryGrade=='PRIMARY_SENIOR_GRADE'?'check':''}}" data-code="PRIMARY_SENIOR_GRADE">
-        四年级
-      </view>
-    </view>
-    <view class="content">
-      <view class="grade {{temporaryGrade=='PRIMARY_FIVE_GRADE'?'check':''}}" data-code="PRIMARY_FIVE_GRADE">五年级
-      </view>
-      <view class="grade {{temporaryGrade=='PRIMARY_SIX_GRADE'?'check':''}}" data-code="PRIMARY_SIX_GRADE">
-        六年级
-      </view>
-    </view>
-    <view class="submitBox">
-      <button class="resetBtn submit" bindtap="changeGrade">确定</button>
-    </view>
-  </view>
-</view>
+</view>
+<privacy-popup bind:agree="agree"></privacy-popup>

+ 61 - 0
components/privacyPopup/index.js

@@ -0,0 +1,61 @@
+Component({
+    properties: {
+
+    },
+    /**
+     * 组件的初始数据
+     */
+    data: {
+        state: false,
+        img: ''
+    },
+    lifetimes: {
+        attached: function () {
+            if (wx.getPrivacySetting) {
+                wx.getPrivacySetting({
+                    success: res => {
+                        console.log("是否需要授权:", res.needAuthorization, "隐私协议的名称为:", res.privacyContractName)
+                        if (res.needAuthorization) {
+                            this.setData({
+                                state: true
+                            })
+                            if (typeof this.getTabBar === 'function') {
+                                this.getTabBar().setData({
+                                    mask: true
+                                })
+                            }
+                        } else {
+                            this.triggerEvent("agree")
+                        }
+                    },
+                    fail: () => {},
+                    complete: () => {},
+                })
+            } else {
+                // 低版本基础库不支持 wx.getPrivacySetting 接口,隐私接口可以直接调用
+                this.triggerEvent("agree")
+            }
+        },
+    },
+    methods: {
+        handleAgree(e) {
+            this.triggerEvent("agree")
+            this.setData({
+                state: false
+            })
+            this.getTabBar().setData({
+                mask: false
+            })
+        },
+        openPrivacyContract() {
+            wx.openPrivacyContract({
+                success: res => {
+                    console.log('openPrivacyContract success')
+                },
+                fail: res => {
+                    console.error('openPrivacyContract fail', res)
+                }
+            })
+        }
+    }
+})

+ 5 - 0
components/privacyPopup/index.json

@@ -0,0 +1,5 @@
+{
+    "component": true,
+    "usingComponents": {},
+    "styleIsolation": "apply-shared"
+}

+ 48 - 0
components/privacyPopup/index.less

@@ -0,0 +1,48 @@
+.mediaBox {
+    position: fixed;
+    z-index: 999;
+    top: 0px;
+    left: 0px;
+    width: 100vw;
+    height: 100vh;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    background: rgba(0, 0, 0, 0.7);
+
+    .media {
+        position: relative;
+        width: 563rpx;
+        height: 590rpx;
+        padding: 40rpx 34rpx;
+        box-sizing: border-box;
+        background-color: white;
+        border-radius: 20rpx;
+        text-align: center;
+
+        .title {
+            margin-bottom: 27rpx;
+        }
+
+        .xieyi {
+            color: blue;
+        }
+
+        .tips {
+            margin-bottom: 14rpx;
+            font-size: 26rpx;
+            letter-spacing: 0;
+            line-height: 47rpx;
+            text-align: left;
+        }
+
+        .confirm {
+            margin-top: 70rpx;
+            padding: 12rpx 50rpx;
+            border-radius: 30rpx;
+            font-size: 30rpx;
+            background-color: #00C657;
+            color: white;
+        }
+    }
+}

+ 13 - 0
components/privacyPopup/index.wxml

@@ -0,0 +1,13 @@
+<view class="mediaBox" wx:if="{{state}}">
+    <view class="media">
+        <view class="title">温馨提示</view>
+        <view class="tips">感谢您使用朗读小咖秀小程序,我们非常重视您的个人信息和隐私保护。为了更好地保障您的个人权益,希望您阅读并同意
+        </view>
+        <view class="tips xieyi" bindtap="openPrivacyContract">《用户隐私政策》</view>
+        <view class="tips">
+            当您同意并继续使用产品时,即表示你已理解并同意该内容。进入朗读小咖秀应用。
+        </view>
+        <button id="agree-btn" type="default" open-type="agreePrivacyAuthorization" class="resetBtn confirm"
+            bindagreeprivacyauthorization="handleAgree">同意,继续使用</button>
+    </view>
+</view>

+ 43 - 0
components/privacyPopup/index.wxss

@@ -0,0 +1,43 @@
+.mediaBox {
+  position: fixed;
+  z-index: 999;
+  top: 0px;
+  left: 0px;
+  width: 100vw;
+  height: 100vh;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  background: rgba(0, 0, 0, 0.7);
+}
+.mediaBox .media {
+  position: relative;
+  width: 563rpx;
+  height: 590rpx;
+  padding: 40rpx 34rpx;
+  box-sizing: border-box;
+  background-color: white;
+  border-radius: 20rpx;
+  text-align: center;
+}
+.mediaBox .media .title {
+  margin-bottom: 27rpx;
+}
+.mediaBox .media .xieyi {
+  color: blue;
+}
+.mediaBox .media .tips {
+  margin-bottom: 14rpx;
+  font-size: 26rpx;
+  letter-spacing: 0;
+  line-height: 47rpx;
+  text-align: left;
+}
+.mediaBox .media .confirm {
+  margin-top: 70rpx;
+  padding: 12rpx 50rpx;
+  border-radius: 30rpx;
+  font-size: 30rpx;
+  background-color: #00C657;
+  color: white;
+}

+ 158 - 157
pages/editUser/index.js

@@ -1,175 +1,176 @@
 import {
-  createStoreBindings
+    createStoreBindings
 } from 'mobx-miniprogram-bindings'
 import {
-  store
+    store
 } from '~/store/index'
 import {
-  setUserInfo,
-  exchangePhone,
-  getMyInfo,
-  bindPhone
+    setUserInfo,
+    exchangePhone,
+    getMyInfo,
+    bindPhone
 } from '~/api/user'
 let storeBindings
 Page({
-  data: {
-    gradeIndex: 0,
-    gradeArray: [{
-        value: 'PRESCHOOL',
-        key: '学前班'
-      }, {
-        value: 'PRIMARY_FIRST_GRADE',
-        key: '一年级'
-      },
-      {
-        value: 'PRIMARY_SECOND_GRADE',
-        key: '二年级'
-      },
-      {
-        value: 'PRIMARY_THREE_GRADE',
-        key: '三年级'
-      },
-      {
-        value: 'PRIMARY_SENIOR_GRADE',
-        key: '四年级'
-      }, {
-        value: 'PRIMARY_FIVE_GRADE',
-        key: '五年级'
-      }, {
-        value: 'PRIMARY_SIX_GRADE',
-        key: '六年级'
-      },
-    ],
-  },
-  onLoad(options) {
-    // 手工绑定 
-    this.storeBindings = createStoreBindings(this, {
-      store,
-      fields: {
-        userInfo: 'userInfo'
-      },
-      actions: {
-        setUser: 'setUser'
-      }
-    })
-    // 立刻更新
-    this.storeBindings.updateStoreBindings()
-    let {
-      grade
-    } = this.data.userInfo
-    let gradeIndex = this.data.gradeArray.findIndex(item => {
-      return item.value == grade
-    })
-    this.setData({
-      gradeIndex
-    })
-  },
-  // 调用清理函数
-  onUnload() {
-    this.storeBindings.destroyStoreBindings()
-  },
-  changeAvatar(e) {
-    const {
-      avatarUrl
-    } = e.detail
-    wx.uploadFile({
-      url: 'https://reader-api.ai160.com/file/upload',
-      filePath: avatarUrl,
-      name: '头像',
-      header: {
-        uid: wx.getStorageSync('uid')
-      },
-      success: (res) => {
-        const newAvatar = JSON.parse(res.data).data;
-        const str = 'userInfo.avatar'
+    data: {
+        gradeIndex: 0,
+        gradeArray: [{
+                value: 'PRESCHOOL',
+                key: '学前班'
+            }, {
+                value: 'PRIMARY_FIRST_GRADE',
+                key: '一年级'
+            },
+            {
+                value: 'PRIMARY_SECOND_GRADE',
+                key: '二年级'
+            },
+            {
+                value: 'PRIMARY_THREE_GRADE',
+                key: '三年级'
+            },
+            {
+                value: 'PRIMARY_SENIOR_GRADE',
+                key: '四年级'
+            }, {
+                value: 'PRIMARY_FIVE_GRADE',
+                key: '五年级'
+            }, {
+                value: 'PRIMARY_SIX_GRADE',
+                key: '六年级'
+            },
+        ],
+    },
+    onLoad(options) {
+        // 手工绑定 
+        this.storeBindings = createStoreBindings(this, {
+            store,
+            fields: {
+                userInfo: 'userInfo'
+            },
+            actions: {
+                setUser: 'setUser'
+            }
+        })
+        // 立刻更新
+        this.storeBindings.updateStoreBindings()
+        let {
+            grade
+        } = this.data.userInfo
+        let gradeIndex = this.data.gradeArray.findIndex(item => {
+            return item.value == grade
+        })
         this.setData({
-          [str]: newAvatar
+            gradeIndex
         })
-        this.setUserInfo({
-          avatar: newAvatar
+
+    },
+    // 调用清理函数
+    onUnload() {
+        this.storeBindings.destroyStoreBindings()
+    },
+    changeAvatar(e) {
+        const {
+            avatarUrl
+        } = e.detail
+        wx.uploadFile({
+            url: 'https://reader-api.ai160.com/file/upload',
+            filePath: avatarUrl,
+            name: '头像',
+            header: {
+                uid: wx.getStorageSync('uid')
+            },
+            success: (res) => {
+                const newAvatar = JSON.parse(res.data).data;
+                const str = 'userInfo.avatar'
+                this.setData({
+                    [str]: newAvatar
+                })
+                this.setUserInfo({
+                    avatar: newAvatar
+                })
+            }
         })
-      }
-    })
-  },
-  saveNickName(e) {
-    let nickName = e.detail.value;
-    if (nickName == this.data.userInfo.nickName) {
-      return
-    }
-    this.setUserInfo({
-      nickName
-    })
-  },
-  selectProfession() {
-    wx.showActionSheet({
-      itemList: ['学生', '家长', '老师'],
-      success: (res) => {
-        if (['学生', '家长', '老师'][res.tapIndex] == this.data.userInfo.profession) {
-          return
+    },
+    saveNickName(e) {
+        let nickName = e.detail.value;
+        if (nickName == this.data.userInfo.nickName) {
+            return
         }
         this.setUserInfo({
-          profession: ['学生', '家长', '老师'][res.tapIndex]
+            nickName
+        })
+    },
+    selectProfession() {
+        wx.showActionSheet({
+            itemList: ['学生', '家长', '老师'],
+            success: (res) => {
+                if (['学生', '家长', '老师'][res.tapIndex] == this.data.userInfo.profession) {
+                    return
+                }
+                this.setUserInfo({
+                    profession: ['学生', '家长', '老师'][res.tapIndex]
+                })
+            },
+        })
+    },
+    selectGender() {
+        wx.showActionSheet({
+            itemList: ['女', '男'],
+            success: (res) => {
+                if (res.tapIndex == this.data.userInfo.gender) {
+                    return
+                }
+                this.setUserInfo({
+                    gender: res.tapIndex
+                })
+            },
+        })
+    },
+    bindDateChange(e) {
+        this.setUserInfo({
+            birthday: e.detail.value
         })
-      },
-    })
-  },
-  selectGender() {
-    wx.showActionSheet({
-      itemList: ['女', '男'],
-      success: (res) => {
-        if (res.tapIndex == this.data.userInfo.gender) {
-          return
+    },
+    bindGradeChange(e) {
+        let grade = this.data.gradeArray[e.detail.value].value
+        this.setUserInfo({
+            grade
+        })
+    },
+    saveSchool(e) {
+        let schoolName = e.detail.value;
+        if (schoolName == this.data.userInfo.schoolName) {
+            return
         }
         this.setUserInfo({
-          gender: res.tapIndex
+            schoolName
+        })
+    },
+    async setUserInfo(data) {
+        wx.showLoading({
+            title: '提交中',
+        })
+        let res = await setUserInfo(data, 'put').finally(() => {
+            wx.hideLoading()
+        })
+        this.setUser(res)
+    },
+    async getPhoneNumber({
+        detail
+    }) {
+        let mobile = await exchangePhone({
+            code: detail.code
+        })
+        await bindPhone({
+            mobile
+        })
+        let userInfo = await getMyInfo()
+        this.setUser(userInfo.user)
+        wx.showToast({
+            title: '绑定成功!',
+            icon: "none",
+            duration: 4000
         })
-      },
-    })
-  },
-  bindDateChange(e) {
-    this.setUserInfo({
-      birthday: e.detail.value
-    })
-  },
-  bindGradeChange(e) {
-    let grade = this.data.gradeArray[e.detail.value].value
-    this.setUserInfo({
-      grade
-    })
-  },
-  saveSchool(e) {
-    let schoolName = e.detail.value;
-    if (schoolName == this.data.userInfo.schoolName) {
-      return
-    }
-    this.setUserInfo({
-      schoolName
-    })
-  },
-  async setUserInfo(data) {
-    wx.showLoading({
-      title: '提交中',
-    })
-    let res = await setUserInfo(data, 'put').finally(() => {
-      wx.hideLoading()
-    })
-    this.setUser(res)
-  },
-  async getPhoneNumber({
-    detail
-  }) {
-    let mobile = await exchangePhone({
-      code: detail.code
-    })
-    await bindPhone({
-      mobile
-    })
-    let userInfo = await getMyInfo()
-    this.setUser(userInfo.user)
-    wx.showToast({
-      title: '绑定成功!',
-      icon: "none",
-      duration: 4000
-    })
-  },
+    },
 })