index.tsx 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. import Taro, { useLoad, useReady } from '@tarojs/taro'
  2. import { PropsWithChildren, useState } from 'react'
  3. import { View, Video, Image } from '@tarojs/components'
  4. import useGetCustomClient from '@/hooks/useGetCustomClient'
  5. import { wrapProps, generateUUID } from '@/plugin/share'
  6. import './index.less'
  7. import http from '@/http/index'
  8. import { adSelfPredict } from '@/http/api/index'
  9. import { adActionLog } from '@/logCenter/index'
  10. import { reportBusinessType } from '@/plugin/share/const'
  11. import { queryURLParams } from '@/plugin/share'
  12. // 在一些场景下 loadedMetaFiredInOnce 被触发了很多次
  13. let loadedMetaFiredInOnce = 0
  14. let pqtId
  15. function PqCustom(props: PropsWithChildren<CustomPropsType>) {
  16. let {
  17. adpId,
  18. openEmbeddedMiniProgram,
  19. onError,
  20. onLoad,
  21. onClose
  22. } = wrapProps(props)
  23. const [show, setShow] = useState(true)
  24. const [adData, setAdData] = useState<any>({})
  25. useReady(() => {
  26. init()
  27. pqtId = generateUUID()
  28. getAdConfig()
  29. })
  30. function init() {
  31. if (
  32. typeof adpId !== 'string' ||
  33. typeof openEmbeddedMiniProgram !== 'function'
  34. ) {
  35. catchError('参数错误', 1031)
  36. return
  37. }
  38. }
  39. function getAdConfig() {
  40. http.post(`${adSelfPredict}?adpId=uh2321awe1`, {
  41. baseInfo: {},
  42. positionId: 1,
  43. phoneModel : '',
  44. careModelStatus : 1,
  45. videoId: 0
  46. }, {
  47. header: { 'content-type': 'application/json;' }
  48. }).then((res: RequestType) => {
  49. const { code, data } = res
  50. if(code === 10001) {
  51. catchError('广告资源加载失败', 1022)
  52. return
  53. }
  54. if(code === 10002) {
  55. catchError('adpId 无效', 1021)
  56. return
  57. }
  58. if(code === 10003) {
  59. catchError('初始化失败', 1011)
  60. return
  61. }
  62. const { ownPlatformAlliance } = data || {}
  63. const { adType, platformCreativeInfo } = ownPlatformAlliance || {}
  64. const { landingPageAddress } = platformCreativeInfo
  65. if (!landingPageAddress) {
  66. catchError('数据异常', 1013)
  67. return
  68. }
  69. setAdData({
  70. adType,
  71. ...platformCreativeInfo
  72. })
  73. }).catch(() => {
  74. catchError('初始化失败', 1011)
  75. })
  76. }
  77. function videoPlay() {
  78. adActionReport(reportBusinessType.adPlay, 'adPlay')
  79. }
  80. function videoClick() {
  81. adActionReport(reportBusinessType.adClick, 'adClick')
  82. videoOpenMiniProgram()
  83. closeCustom()
  84. }
  85. function videoOpenMiniProgram() {
  86. const { landingPageAddress } = adData
  87. const query = queryURLParams(createAdActionReportData())
  88. adActionReport(reportBusinessType.adPlay, 'adOpen')
  89. openEmbeddedMiniProgram(
  90. 'wx5ef216d1caf4a0ea',
  91. `/pages/ad-launch-page/index?path=${encodeURIComponent(landingPageAddress)}&${query}`
  92. )
  93. console.log(`/pages/ad-launch-page/index?path=${encodeURIComponent(landingPageAddress)}&${query}`)
  94. }
  95. function videoLoad() {
  96. adActionReport(reportBusinessType.adLoad, 'adLoad')
  97. onLoad()
  98. }
  99. function videoError() {
  100. catchError('广告加载失败', 1012)
  101. }
  102. function videoView() {
  103. adActionReport(reportBusinessType.adView, 'adView')
  104. }
  105. function videoTimeUpdate() {}
  106. function closeCustom() {
  107. adActionReport(reportBusinessType.adClose, 'adClose')
  108. onClose()
  109. setShow(false)
  110. }
  111. function clickMask() {
  112. closeCustom()
  113. }
  114. function adActionReport(eventId, businessType, extParams = {}) {
  115. const data = createAdActionReportData
  116. adActionLog([{
  117. businessType,
  118. eventId,
  119. ...data,
  120. ...extParams
  121. }])
  122. }
  123. function createAdActionReportData() {
  124. const {
  125. trafficCode, // 流量主code
  126. // 广告主
  127. advertiserCode,
  128. advertiserId,
  129. // 广告计划
  130. campaignCode,
  131. campaignId,
  132. // 广告
  133. adCode,
  134. adId,
  135. // 创意
  136. creativeCode,
  137. id,
  138. // 广告位
  139. positionId,
  140. // 竞价
  141. bidType = '',
  142. unitPrice = '', // 单价
  143. bidCreativeParam = {}, // {}
  144. } = adData
  145. return {
  146. adpCode: trafficCode,
  147. advertiserCode,
  148. advertiserId,
  149. campaignCode,
  150. campaignId,
  151. adCode,
  152. adId,
  153. creativeCode,
  154. id,
  155. positionId,
  156. bidType,
  157. unitPrice, // 单价
  158. bidCreativeParam: JSON.stringify(bidCreativeParam || {}), // {}
  159. adpId,
  160. pqtId
  161. }
  162. }
  163. function catchError(message, code) {
  164. onError({ message, code })
  165. setShow(false)
  166. adActionReport(reportBusinessType.adError, 'adError', {
  167. errorCode: code
  168. })
  169. }
  170. return (
  171. <>
  172. {show && <View className='pq-custom' onClick={clickMask}>
  173. <View className='custom-container'>
  174. <View className='icon'>
  175. 广告
  176. </View>
  177. <View className='close-icon' onClick={closeCustom}>
  178. </View>
  179. <Custom
  180. adData={adData}
  181. onPlay={videoPlay}
  182. onClick={videoClick}
  183. onLoad={videoLoad}
  184. onView={videoView}
  185. onError={videoError}
  186. onTimeUpdate={videoTimeUpdate}
  187. />
  188. </View>
  189. </View>}
  190. </>
  191. )
  192. }
  193. function Custom({
  194. adData, onPlay, // 播放事件
  195. onClick, onLoad, onView, onError, onTimeUpdate
  196. }) {
  197. const [style, setStyle] = useState({ width: '0px', height: '0px' })
  198. useReady(() => {
  199. loadedMetaFiredInOnce = 0
  200. })
  201. useGetCustomClient((customClient) => {
  202. let clientWidth = customClient.width
  203. let clientHeight = customClient.height
  204. setStyle({
  205. width: `${clientWidth}px`,
  206. height: `${clientHeight}px`
  207. })
  208. })
  209. function onLoadedMetaData() {
  210. if (loadedMetaFiredInOnce++ < 1) {
  211. // 上报load
  212. onLoad()
  213. }
  214. }
  215. return (
  216. <View className='custom' style={style}>
  217. <Video
  218. id='pq-custom'
  219. className='custom-video'
  220. objectFit='fill'
  221. controls={false}
  222. autoplay
  223. loop
  224. src={adData.materialAddress}
  225. poster={adData.materialCoverPic}
  226. onPlay={onPlay}
  227. onTimeUpdate={onTimeUpdate}
  228. onError={onError}
  229. onClick={onClick}
  230. onLoadedMetaData={onLoadedMetaData}
  231. />
  232. <View className='custom-bottom'>
  233. <Image src={adData.creativeLogoAddress} className='logo' />
  234. <View className='title'>{adData.creativeTitle}</View>
  235. <View className='button'>{adData.clickButtonText}</View>
  236. </View>
  237. </View>
  238. )
  239. }
  240. export default PqCustom