unlock-content.vue 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. <template>
  2. <view class="unlock-content">
  3. <!-- #ifdef H5 -->
  4. <!-- 等广告支持H5后优化-->
  5. <button class="text" @click="callAd">请观看广告后解锁全文</button>
  6. <!-- #endif -->
  7. <!-- #ifndef H5 -->
  8. <ad-rewarded-video ref="rewardedVideo" :adpid="adpId" :preload="false" :disabled="true" :loadnext="true"
  9. :url-callback="urlCallback" @load="onAdLoad" @close="onAdClose" @error="onAdError"
  10. v-slot:default="{ loading, error }">
  11. <text v-if="error" class="text">广告加载失败</text>
  12. </ad-rewarded-video>
  13. <button v-if="!isLoadError" class="text" @click="callAd" :loading="adLoading">请观看广告后解锁全文</button>
  14. <!-- #endif -->
  15. </view>
  16. </template>
  17. <script>
  18. // 实例化数据库
  19. const db = uniCloud.database()
  20. // 定义解锁记录表名
  21. const unlockContentDBName = 'uni-cms-unlock-record'
  22. export default {
  23. name: "ad",
  24. props: {
  25. adpId: String,
  26. watchAdUniqueType: {
  27. type: String,
  28. default: 'device'
  29. },
  30. },
  31. data() {
  32. return {
  33. currentArticleId: '',
  34. currentPageRoute: '',
  35. adLoading: false,
  36. isLoadError: false
  37. }
  38. },
  39. computed: {
  40. // 回调URL
  41. urlCallback() {
  42. return {
  43. extra: JSON.stringify({
  44. article_id: this.currentArticleId,
  45. unique_id: this.uniqueId,
  46. unique_type: this.watchAdUniqueType
  47. })
  48. }
  49. },
  50. // 是否通过设备观看
  51. watchByDevice() {
  52. return this.watchAdUniqueType === 'device'
  53. },
  54. // 是否通过用户观看
  55. watchByUser() {
  56. return this.watchAdUniqueType === 'user'
  57. },
  58. // 获取唯一ID
  59. uniqueId() {
  60. return this.watchByDevice ? uni.getSystemInfoSync().deviceId : uniCloud.getCurrentUserInfo().uid
  61. }
  62. },
  63. // #ifndef H5
  64. mounted() {
  65. // 获取当前页面信息
  66. const pages = getCurrentPages()
  67. const currentPage = pages[pages.length - 1]
  68. this.currentArticleId = currentPage.options.id
  69. this.currentPageRoute = currentPage.route
  70. // 如果广告位ID未设置,则提示广告无法正常加载
  71. if (!this.adpId) {
  72. uni.showModal({
  73. content: '广告位ID未设置,广告无法正常加载',
  74. showCancel: false
  75. })
  76. } else {
  77. // 加载广告
  78. this.$refs.rewardedVideo.load()
  79. }
  80. },
  81. // #endif
  82. methods: {
  83. // 调用广告
  84. callAd() {
  85. // #ifdef H5
  86. // 如果在浏览器中,则提示需在App或小程序中操作
  87. return uni.showModal({
  88. content: '需观看广告解锁内容, 但浏览器不支持广告播放, 请在App或小程序中操作',
  89. showCancel: false
  90. })
  91. // #endif
  92. if (this.watchByUser) {
  93. // 登录跳转URL 请根据实际情况修改
  94. const redirectUrl = '/uni_modules/uni-id-pages/pages/login/login-withoutpwd' + (this.currentPageRoute ? '?uniIdRedirectUrl=' + this.currentPageRoute + '?id=' + this.currentArticleId : '')
  95. //::TODO 支持设备与用户
  96. // 如果用户未登录,则提示需要登录
  97. if (uniCloud.getCurrentUserInfo().tokenExpired < Date.now()) {
  98. uni.showModal({
  99. content: '请登录后操作',
  100. success: ({ confirm }) => {
  101. confirm && uni.redirectTo({
  102. url: redirectUrl
  103. });
  104. }
  105. })
  106. }
  107. }
  108. // 显示广告
  109. this.adLoading = true
  110. this.$refs.rewardedVideo.show()
  111. },
  112. // 广告加载成功
  113. onAdLoad() {
  114. this.adLoading && this.$refs.rewardedVideo.show()
  115. console.log('广告数据加载成功');
  116. },
  117. // 广告关闭
  118. onAdClose(e) {
  119. console.log('close', e)
  120. const detail = e.detail
  121. // 轮询3次,每次1秒,如果3秒内没有查询到解锁记录,就提示解锁失败
  122. let i = 3
  123. uni.hideLoading()
  124. this.adLoading = false
  125. // detail.isEnded 为true 说明用户观看了完整视频
  126. if (detail && detail.isEnded) {
  127. uni.showLoading({
  128. title: '正在解锁全文',
  129. timeout: 7000
  130. })
  131. let queryResult = setInterval(async () => {
  132. i--;
  133. // 查询解锁记录
  134. const res = await db.collection(unlockContentDBName).where({
  135. unique_id: this.uniqueId,
  136. article_id: this.currentArticleId,
  137. }).get()
  138. // 1. result.data.length 为0 说明没有解锁记录
  139. // 2. i <= 0 说明已经轮询了3次,还是没有解锁记录,说明解锁失败
  140. // 3. result.data.length && i > 0 说明已经解锁成功
  141. if (i <= 0) {
  142. console.log('解锁失败', i)
  143. clearInterval(queryResult)
  144. uni.hideLoading()
  145. uni.showToast({
  146. title: '解锁失败!',
  147. icon: 'error',
  148. duration: 2000
  149. });
  150. } else if (res.result && res.result.data.length) {
  151. console.log('解锁成功', i)
  152. clearInterval(queryResult)
  153. uni.hideLoading()
  154. uni.showToast({
  155. title: '解锁成功!',
  156. icon: 'success',
  157. duration: 2000
  158. });
  159. uni.$emit('onUnlockContent')
  160. }
  161. }, 1500);
  162. } else {
  163. uni.showModal({
  164. content: "请观看完整视频后解锁全文",
  165. showCancel: false
  166. })
  167. }
  168. },
  169. onAdError(e) {
  170. // uni.hideLoading()
  171. // this.isLoadError = true
  172. console.error('onaderror: ', e)
  173. }
  174. }
  175. }
  176. </script>
  177. <style scoped lang="scss">
  178. .unlock-content {
  179. text-align: center;
  180. padding: 160rpx 0 60rpx;
  181. position: relative;
  182. margin-top: -140rpx;
  183. &:before {
  184. content: '';
  185. position: absolute;
  186. top: 0;
  187. left: 0;
  188. right: 0;
  189. height: 160rpx;
  190. background: linear-gradient(to bottom, transparent, #fff);
  191. }
  192. .text {
  193. border: #f0f0f0 solid 1px;
  194. display: inline-block;
  195. background: #f6f6f6;
  196. border-radius: 10rpx;
  197. font-size: 34rpx;
  198. color: #222;
  199. }
  200. }
  201. </style>