index.tsx 6.6 KB

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