广告屏react-native项目
Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 
 
 

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