广告屏react-native项目
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.
 
 
 
 
 

736 rindas
20 KiB

  1. import React, { Component } from 'react';
  2. import {
  3. Platform,
  4. StyleSheet,
  5. Text,
  6. View,
  7. Image,
  8. ImageBackground,
  9. PixelRatio,
  10. NativeModules
  11. } from 'react-native';
  12. //引用插件
  13. import Package from './package.json'
  14. import HttpUtils from './HttpUtils.js';
  15. import CodePush from "react-native-code-push";
  16. import DeviceInfo from "react-native-device-info";
  17. import * as Animatable from 'react-native-animatable';
  18. var testMac = 'FF:FF:FF:FF:FF:FF'
  19. var contentItemDefault = {
  20. type:0,
  21. subType:0,
  22. qrcode:[],
  23. target:{
  24. coverImg:'',
  25. title:'',
  26. subTitle:'',
  27. priceStr:'',
  28. salePriceStr:'',
  29. remark:'',
  30. }
  31. }
  32. var baseInfoDefault = {
  33. imgUrlH:'',
  34. imgQrcodeWeapp:'',
  35. imgQrcodeWemp:''
  36. }
  37. var curAdIndex = 0;
  38. var errorMsg = {
  39. ERR_MAC_GET:'设备编号获取错误',
  40. ERR_DATA_GET:'广告数据获取错误'
  41. }
  42. export default class MyPage extends Component {
  43. constructor(props) {
  44. super(props);
  45. this.state = {
  46. baseInfo: baseInfoDefault,
  47. adDataList:[],
  48. contentItem0:null,
  49. contentItem1:null,
  50. contentItem2:null,
  51. contentDisplayStatus:false,
  52. syncMessage: "初始化..." ,
  53. errorMessage: '加载中...',
  54. progress: {
  55. receivedBytes:0,
  56. totalBytes:0
  57. },
  58. macAddress: '',
  59. versionInfo:'未知'
  60. };
  61. }
  62. // 监听更新状态
  63. codePushStatusDidChange(syncStatus) {
  64. switch(syncStatus) {
  65. case CodePush.SyncStatus.CHECKING_FOR_UPDATE:
  66. this.setState({ syncMessage: "检查更新" });
  67. break;
  68. case CodePush.SyncStatus.DOWNLOADING_PACKAGE:
  69. this.setState({ syncMessage: "下载更新" });
  70. break;
  71. case CodePush.SyncStatus.AWAITING_USER_ACTION:
  72. this.setState({ syncMessage: "等待用户操作" });
  73. break;
  74. case CodePush.SyncStatus.INSTALLING_UPDATE:
  75. this.setState({ syncMessage: "安装更新" });
  76. break;
  77. case CodePush.SyncStatus.UP_TO_DATE:
  78. this.setState({ syncMessage: "已更新到最新程序", progress: false });
  79. break;
  80. case CodePush.SyncStatus.UPDATE_IGNORED:
  81. this.setState({ syncMessage: "更新被取消", progress: false });
  82. break;
  83. case CodePush.SyncStatus.UPDATE_INSTALLED:
  84. this.setState({ syncMessage: "更新已安装,重启应用后生效", progress: false });
  85. break;
  86. case CodePush.SyncStatus.UNKNOWN_ERROR:
  87. this.setState({ syncMessage: "未知错误", progress: false });
  88. break;
  89. }
  90. }
  91. codePushDownloadDidProgress(progress) {
  92. this.setState({ progress });
  93. }
  94. // 列表滚动
  95. updateContent() {
  96. if (this.state.adDataList.length <=0)
  97. return false;
  98. if (curAdIndex >= this.state.adDataList.length) {
  99. curAdIndex = 0
  100. }
  101. this.setState({contentItem0:this.state.adDataList[curAdIndex]});
  102. if (curAdIndex + 1 < this.state.adDataList.length)
  103. this.setState({contentItem1:this.state.adDataList[curAdIndex+1]});
  104. else
  105. this.setState({contentItem1:null});
  106. if (curAdIndex + 2 < this.state.adDataList.length)
  107. this.setState({contentItem2:this.state.adDataList[curAdIndex+2]});
  108. else
  109. this.setState({contentItem2:null});
  110. curAdIndex+=3
  111. return true;
  112. }
  113. hbRequest() {
  114. HttpUtils.post(NativeModules.BuildConfig.apiHost + 'api/wxDeviceScreenAd/heartbeat?deviceId='
  115. +encodeURIComponent(this.state.macAddress),
  116. {version:this.state.versionInfo})
  117. .then(result => {
  118. })
  119. .catch(error => {
  120. })
  121. }
  122. getAdDataList() {
  123. HttpUtils.get(NativeModules.BuildConfig.apiHost + 'api/wxDeviceScreenAd/list?deviceId='+encodeURIComponent(this.state.macAddress)+'&pageNum=1&pageSize=1000')
  124. .then((result) => {
  125. if (result.code != 200) {
  126. this.setState({contentDisplayStatus: false})
  127. this.setState({errorMessage : result.message+'\n'+this.state.macAddress});
  128. } else if (result.data.list) {
  129. this.setState({adDataList : result.data.list});
  130. if (this.updateContent()) {
  131. this.setState({contentDisplayStatus: true})
  132. }
  133. } else {
  134. this.setState({contentDisplayStatus: false})
  135. this.setState({errorMessage : errorMsg.ERR_DATA_GET});
  136. }
  137. })
  138. .catch(error => {
  139. this.setState({contentDisplayStatus: false})
  140. this.setState({errorMessage : error.message});
  141. })
  142. }
  143. //
  144. getBaseInfo() {
  145. HttpUtils.get(NativeModules.BuildConfig.apiHost + 'api/wxDeviceScreenAd/info?deviceId='+encodeURIComponent(this.state.macAddress))
  146. .then(result => {
  147. if (result.code != 200) {
  148. this.setState({contentDisplayStatus: false})
  149. this.setState({errorMessage : result.message+'\n'+this.state.macAddress});
  150. } else if (result.data) {
  151. this.setState({baseInfo:result.data});
  152. } else {
  153. this.setState({contentDisplayStatus: false})
  154. this.setState({errorMessage : errorMsg.ERR_DATA_GET});
  155. }
  156. })
  157. .catch(error => {
  158. this.setState({contentDisplayStatus: false})
  159. this.setState({errorMessage : error.message});
  160. })
  161. }
  162. componentDidMount() {
  163. CodePush.allowRestart();
  164. CodePush.sync(
  165. { installMode: CodePush.InstallMode.IMMEDIATE},
  166. this.codePushStatusDidChange.bind(this),
  167. this.codePushDownloadDidProgress.bind(this)
  168. );
  169. CodePush.getUpdateMetadata(CodePush.UpdateState.RUNNING)
  170. .then((metadata: LocalPackage) => {
  171. this.setState({ versionInfo: metadata ? metadata.appVersion + "-" + metadata.label : "Unknown"});
  172. }, (error: any) => {
  173. this.setState({ versionInfo: "Unknown"});
  174. });
  175. DeviceInfo.getMACAddress().then((mac)=>{
  176. if (mac=='') {
  177. if (NativeModules.BuildConfig.buildType == 'debug') {
  178. this.setState({macAddress : this.testMac})
  179. this.startAd()
  180. } else {
  181. this.setState({ contentDisplayStatus: false})
  182. this.setState({ errorMessage : errorMsg.ERR_MAC_GET});
  183. }
  184. } else {
  185. this.setState({macAddress : mac})
  186. this.startAd()
  187. }
  188. this.setState({ contentDisplayStatus: true})
  189. }).catch(e => {
  190. this.setState({ contentDisplayStatus: false})
  191. this.setState({ errorMessage : errorMsg.ERR_MAC_GET});
  192. })
  193. }
  194. startAd() {
  195. this.getBaseInfo()
  196. this.getAdDataList()
  197. setInterval(
  198. ()=>{
  199. if (this.state.contentDisplayStatus) {
  200. this.setState({ contentDisplayStatus: false})
  201. if (this.updateContent()) {
  202. this.setState({ contentDisplayStatus: true})
  203. }
  204. } else {
  205. this.getBaseInfo()
  206. this.getAdDataList()
  207. }
  208. },
  209. 1000*10, //10秒更新一下页面
  210. );
  211. setInterval(
  212. ()=>{
  213. this.getAdDataList()
  214. },
  215. 1000*60*60, //1小时一次
  216. );
  217. setInterval(
  218. ()=>{
  219. this.hbRequest()
  220. },
  221. 1000*60*5, //5分钟一次
  222. );
  223. }
  224. getContentViewItemUplayer(contentItem) {
  225. if (contentItem.type == 0) {
  226. if (contentItem.subType == 2)
  227. return (<Image source={require('./image/groupbuy.png')} resizeMode='center' style={styles.contentItemUpLayer} /> )
  228. if (contentItem.subType == 6)
  229. return (<Image source={require('./image/discount.png')} resizeMode='center' style={styles.contentItemUpLayer} /> )
  230. if (contentItem.subType == 7)
  231. return (<Image source={require('./image/groupbuy.png')} resizeMode='center' style={styles.contentItemUpLayer} /> )
  232. }
  233. }
  234. getContentViewItem(contentItem, annomation) {
  235. if (!contentItem)
  236. return (
  237. <View style={styles.contentItem}>
  238. </View>
  239. )
  240. actionText = '扫码领取';
  241. if (contentItem.target.type == 8)
  242. actionText = '扫码砍价';
  243. else if (contentItem.target.type == 9)
  244. actionText = '扫码拼团';
  245. merchantName = "";
  246. if (contentItem.target.merchantVoList.length > 1)
  247. merchantName = '多商户通用';
  248. else
  249. merchantName = contentItem.target.merchantVoList[0].merchantName;
  250. return (
  251. <Animatable.View animation={annomation} easing="ease-out" duration={1500} delay={500} useNativeDriver ={true} style={styles.contentItem}>
  252. <ImageBackground source={require('./image/item-background.png')} resizeMode='center' style={styles.contentItemDownLayer} >
  253. <View style={styles.contentItemTop}>
  254. <Image source={{uri: contentItem.target.coverImg}} resizeMode='cover' style={styles.contentItemTopCoverImg} />
  255. <View style={styles.contentItemTopDetail}>
  256. <Text style={styles.contentItemTopDetailTitle} numberOfLines={2} ellipsizeMode="tail">{contentItem.target.title}</Text>
  257. {/* <Text style={styles.contentItemTopDetailRemark} numberOfLines={1} ellipsizeMode="tail">{contentItem.target.remark}</Text> */}
  258. <View style={styles.contentItemTopDetailPrice}>
  259. <View style={styles.contentItemTopDetailCurPrice}>
  260. <Text style={styles.contentItemTopDetailCurPriceStrUnit}>¥</Text>
  261. <Text style={styles.contentItemTopDetailCurPriceStr}>{contentItem.target.salePriceStr}</Text>
  262. </View>
  263. <View style={styles.contentItemTopDetailSalePrice}>
  264. <Text style={styles.contentItemTopDetailSalePriceStr} >¥{contentItem.target.priceStr}</Text>
  265. </View>
  266. </View>
  267. </View>
  268. <Image source={{uri:'data:image/png;base64,'+contentItem.qrcode}} resizeMode='contain' style={styles.contentItemTopQrcode} />
  269. </View>
  270. <View style={styles.contentItemBottom}>
  271. <Text style={styles.contentItemBottomMerchantName}>{merchantName}</Text>
  272. <View style={styles.contentItemBottomPlacehold}></View>
  273. <Text style={styles.contentItemBottomAction}>{actionText}</Text>
  274. </View>
  275. </ImageBackground>
  276. {this.getContentViewItemUplayer(contentItem)}
  277. </Animatable.View>
  278. )
  279. }
  280. getContentView() {
  281. if (this.state.contentDisplayStatus) {
  282. return (<View style={styles.content}>
  283. {this.getContentViewItem(this.state.contentItem0,"slideInDown")}
  284. {this.getContentViewItem(this.state.contentItem1,"slideInLeft")}
  285. {this.getContentViewItem(this.state.contentItem2,"slideInRight")}
  286. </View>)
  287. }else{
  288. return (
  289. <View style={styles.content}>
  290. <Text style={styles.updatePage}>{this.state.errorMessage}</Text>
  291. </View>)
  292. }
  293. }
  294. render() {
  295. if (this.state.progress) {
  296. if (this.state.progress.totalBytes > 0)
  297. return (
  298. <Text style={styles.updatePage}>{this.state.syncMessage}{'\n'}
  299. {this.state.progress.receivedBytes} of {this.state.progress.totalBytes} bytes received{'\n'}
  300. </Text>
  301. );
  302. return (
  303. <Text style={styles.updatePage}>{this.state.syncMessage}
  304. </Text>
  305. );
  306. }
  307. return (
  308. <ImageBackground style={styles.background} resizeMode='center' source={require('./image/background.png')}>
  309. <View style={styles.title}>
  310. <View style={styles.titleImagePlace}>
  311. <Image source={require('./image/title.png')} resizeMode='center' style={styles.titleImage} />
  312. </View>
  313. <ImageBackground source={require('./image/title-qrcode.png') } resizeMode='center' style={styles.titleQrcodeBonder} >
  314. <View style={styles.titleQrcodePlacehold}></View>
  315. <Image source={{uri: this.state.baseInfo.imgQrcodeWeapp}} resizeMode='center' style={styles.titleQrcode} />
  316. <View style={styles.titleQrcodePlacehold}></View>
  317. </ImageBackground>
  318. </View>
  319. {this.getContentView()}
  320. <View style={styles.bottom}>
  321. <View style={styles.bottomLogoBackground}>
  322. <Image source={{ uri: this.state.baseInfo.imgUrlH, cache: 'force-cache'}} resizeMode='contain' style={styles.bottomLogo} />
  323. </View>
  324. <View style={styles.bottomQrcode1Background}>
  325. <Image source={{ uri: this.state.baseInfo.imgQrcodeWeapp, cache: 'force-cache'}} resizeMode='center' style={styles.bottomQrcode1} />
  326. <Text style={styles.bottomQrcode1Str}>小程序</Text>
  327. </View>
  328. <View style={styles.bottomQrcode2Background}>
  329. <Image source={{ uri: this.state.baseInfo.imgQrcodeWemp, cache: 'force-cache'}} resizeMode='center' style={styles.bottomQrcode2} />
  330. <Text style={styles.bottomQrcode1Str}>公众号</Text>
  331. </View>
  332. <Text style={styles.bottomPlacehold}>{this.state.versionInfo}</Text>
  333. </View>
  334. </ImageBackground>
  335. );
  336. }
  337. }
  338. const styles = StyleSheet.create({
  339. updatePage:{
  340. flex: 2,
  341. width:'100%',
  342. height:'100%',
  343. backgroundColor:'transparent',
  344. textAlign :'center',
  345. textAlignVertical:'center',
  346. fontSize: 63/PixelRatio.get(),
  347. color: 'darkblue'
  348. },
  349. //layer background
  350. background:{
  351. flex: 1,
  352. width:'100%',
  353. height:'100%'
  354. },
  355. //layer top
  356. title:{
  357. flex: 6,
  358. flexDirection: 'row',
  359. alignItems: 'center',
  360. paddingLeft:42/PixelRatio.get(),
  361. paddingRight:42/PixelRatio.get(),
  362. backgroundColor:'transparent'
  363. },
  364. content:{
  365. flex: 18,
  366. flexDirection: 'column',
  367. alignItems: 'center',
  368. backgroundColor:'transparent'
  369. },
  370. bottom:{
  371. flex: 2,
  372. flexDirection: 'row',
  373. alignItems: 'center',
  374. paddingLeft:42/PixelRatio.get(),
  375. paddingRight:42/PixelRatio.get(),
  376. backgroundColor:'transparent'
  377. },
  378. //layer title
  379. titleImagePlace: {
  380. flex: 2,
  381. paddingTop: '20%',
  382. paddingLeft: '15%',
  383. alignItems: 'center',
  384. backgroundColor:'transparent'
  385. },
  386. titleImage: {
  387. width:'100%',
  388. height:'100%',
  389. flex: 1,
  390. backgroundColor:'transparent'
  391. },
  392. titleQrcodeBonder: {
  393. width:'100%',
  394. height:'100%',
  395. alignItems: 'center',
  396. flexDirection: 'column',
  397. flex: 1,
  398. backgroundColor:'transparent'
  399. },
  400. titleQrcodePlacehold: {
  401. flex: 5,
  402. backgroundColor:'transparent'
  403. },
  404. titleQrcode: {
  405. flex: 6,
  406. width:'100%',
  407. height:'100%',
  408. backgroundColor:'transparent'
  409. },
  410. //layer bottom
  411. bottomLogoBackground: {
  412. flex: 3,
  413. borderRadius:16/PixelRatio.get(),
  414. marginTop: 26/PixelRatio.get(),
  415. marginBottom: 26/PixelRatio.get(),
  416. backgroundColor:'transparent',//'rgba(255,255,255,0.5)',
  417. },
  418. bottomLogo: {
  419. width:'100%',
  420. height:'100%',
  421. backgroundColor:'transparent'
  422. },
  423. bottomQrcode1Background : {
  424. flex: 1,
  425. width:'100%',
  426. height:'100%',
  427. marginLeft: 21/PixelRatio.get(),
  428. paddingTop: 27/PixelRatio.get(),
  429. paddingBottom: 11/PixelRatio.get(),
  430. flexDirection: 'column',
  431. backgroundColor:'transparent'
  432. },
  433. bottomQrcode2Background : {
  434. flex: 1,
  435. width:'100%',
  436. height:'100%',
  437. marginLeft: 21/PixelRatio.get(),
  438. paddingTop: 26/PixelRatio.get(),
  439. paddingBottom: 11/PixelRatio.get(),
  440. flexDirection: 'column',
  441. backgroundColor:'transparent'
  442. },
  443. bottomQrcode1: {
  444. flex: 2,
  445. width:'100%',
  446. height:'100%',
  447. backgroundColor:'transparent'
  448. },
  449. bottomQrcode2: {
  450. flex: 2,
  451. width:'100%',
  452. height:'100%',
  453. backgroundColor:'transparent'
  454. },
  455. bottomQrcode1Str: {
  456. flex: 1,
  457. textAlign :'center',
  458. textAlignVertical:'center',
  459. fontSize: 16/PixelRatio.get(),
  460. color : 'white',
  461. backgroundColor:'transparent'
  462. },
  463. bottomQrcode2Str: {
  464. flex: 1,
  465. textAlign :'center',
  466. textAlignVertical:'center',
  467. fontSize: 16/PixelRatio.get(),
  468. color : 'white',
  469. backgroundColor:'transparent'
  470. },
  471. bottomPlacehold: {
  472. flex: 8,
  473. width:'100%',
  474. height:'100%',
  475. backgroundColor:'transparent',
  476. textAlign :'right',
  477. textAlignVertical:'bottom',
  478. fontSize: 27/PixelRatio.get(),
  479. color : 'gray'
  480. },
  481. //layer content item
  482. contentItem:{
  483. flex: 1,
  484. width:'100%',
  485. height:'100%',
  486. flexDirection: 'column',
  487. backgroundColor:'transparent'
  488. },
  489. contentItemDownLayer:{
  490. position:'absolute',
  491. width:'100%',
  492. height:'100%',
  493. flexDirection: 'column',
  494. alignItems: 'center',
  495. backgroundColor:'transparent'
  496. },
  497. contentItemUpLayer:{
  498. width:210/PixelRatio.get(),
  499. height:153/PixelRatio.get(),
  500. position:'absolute',
  501. backgroundColor:'transparent'
  502. },
  503. contentItemTop:{
  504. flex: 3,
  505. width:'100%',
  506. height:'100%',
  507. paddingLeft: 66/PixelRatio.get(),
  508. paddingRight: 53/PixelRatio.get(),
  509. paddingTop: 40/PixelRatio.get(),
  510. flexDirection: 'row',
  511. alignItems: 'center',
  512. backgroundColor:'transparent'
  513. },
  514. contentItemBottom:{
  515. flex: 1,
  516. width:'100%',
  517. height:'100%',
  518. paddingLeft: 66/PixelRatio.get(),
  519. paddingRight: 53/PixelRatio.get(),
  520. paddingBottom: 40/PixelRatio.get(),
  521. flexDirection: 'row',
  522. alignItems: 'center',
  523. backgroundColor:'transparent'
  524. },
  525. //layer content item top
  526. contentItemTopCoverImg:{
  527. flex: 5,
  528. width:'100%',
  529. height:'100%',
  530. borderRadius:27/PixelRatio.get(),
  531. backgroundColor:'transparent'
  532. },
  533. contentItemTopDetail:{
  534. flex: 6,
  535. width:'100%',
  536. height:'100%',
  537. paddingLeft: 27/PixelRatio.get(),
  538. paddingRight: 79/PixelRatio.get(),
  539. alignItems: 'center',
  540. backgroundColor:'transparent'
  541. },
  542. contentItemTopQrcode:{
  543. flex: 5,
  544. width:'100%',
  545. height:'100%',
  546. backgroundColor:'transparent'
  547. },
  548. //layer content item bottom
  549. contentItemBottomMerchantName:{
  550. flex: 5,
  551. width:'100%',
  552. height:'100%',
  553. alignItems: 'center',
  554. backgroundColor:'transparent',
  555. textAlign :'center',
  556. textAlignVertical:'center',
  557. fontSize: 27/PixelRatio.get(),
  558. fontWeight : 'bold'
  559. },
  560. contentItemBottomPlacehold:{
  561. flex: 6,
  562. paddingLeft: 27/PixelRatio.get(),
  563. paddingRight: 79/PixelRatio.get(),
  564. width:'100%',
  565. height:'100%',
  566. backgroundColor:'transparent',
  567. },
  568. contentItemBottomAction:{
  569. flex: 5,
  570. width:'100%',
  571. height:'100%',
  572. backgroundColor:'transparent',
  573. fontWeight : 'bold',
  574. textAlign :'center',
  575. textAlignVertical:'center',
  576. fontSize: 36/PixelRatio.get(),
  577. color: 'darkgray'
  578. },
  579. //layer content item top detail
  580. contentItemTopDetailTitle:{
  581. flex: 2,
  582. width:'100%',
  583. height:'100%',
  584. backgroundColor:'transparent',
  585. textAlign :'left',
  586. textAlignVertical:'center',
  587. fontSize: 53/PixelRatio.get(),
  588. },
  589. /*
  590. contentItemTopDetailRemark:{
  591. flex: 1,
  592. width:'100%',
  593. height:'100%',
  594. backgroundColor:'transparent',
  595. textAlign :'left',
  596. textAlignVertical:'center',
  597. fontSize: 27/PixelRatio.get(),
  598. color : 'gray'
  599. },
  600. */
  601. contentItemTopDetailPrice:{
  602. flex: 2,
  603. width:'100%',
  604. height:'100%',
  605. backgroundColor:'transparent',
  606. flexDirection: 'row',
  607. },
  608. contentItemTopDetailCurPrice:{
  609. flex: 3,
  610. width:'100%',
  611. height:'100%',
  612. flexDirection: 'row',
  613. backgroundColor:'transparent',
  614. },
  615. contentItemTopDetailCurPriceStr:{
  616. backgroundColor:'transparent',
  617. fontSize:96/PixelRatio.get(),
  618. fontFamily:"PingFangSC-Bold",
  619. fontWeight: "bold",
  620. textAlign :'left',
  621. textAlignVertical:'bottom',
  622. color : 'red'
  623. },
  624. contentItemTopDetailCurPriceStrUnit:{
  625. backgroundColor:'transparent',
  626. textAlign :'left',
  627. textAlignVertical:'bottom',
  628. paddingBottom: 16/PixelRatio.get(),
  629. fontSize: 48/PixelRatio.get(),
  630. color : 'red'
  631. },
  632. contentItemTopDetailSalePrice:{
  633. flex: 1,
  634. width:'100%',
  635. height:'100%',
  636. backgroundColor:'transparent',
  637. },
  638. contentItemTopDetailSalePriceStr:{
  639. width:'100%',
  640. height:'100%',
  641. backgroundColor:'transparent',
  642. textAlign :'left',
  643. textAlignVertical:'bottom',
  644. fontSize: 27/PixelRatio.get(),
  645. textDecorationLine: 'line-through',
  646. color : 'gray'
  647. },
  648. });