广告屏react-native项目
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 

735 行
19 KiB

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