广告屏react-native项目
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 
 
 

717 Zeilen
19 KiB

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