import React, { Component } from 'react'; import { Platform, StyleSheet, Text, View, Image, ImageBackground, PixelRatio, NativeModules } from 'react-native'; //引用插件 import Package from './package.json' import HttpUtils from './HttpUtils.js'; import CodePush from "react-native-code-push"; import DeviceInfo from "react-native-device-info"; import RNFetchBlob from 'react-native-fetch-blob'; import * as Animatable from 'react-native-animatable'; import {CachedImage,ImageCache} from "react-native-img-cache"; var testMac = 'FF:FF:FF:FF:FF:FF' var curAdIndex = 0; var errorMsg = { ERR_MAC_GET:'设备编号获取错误', ERR_START_AD:'广告播放系统错误', ERR_DATA_GET:'广告数据获取错误', ERR_HEARTBEAT:'设备心跳数据错误', ERR_NO_DATA:'暂无优惠信息' } var animationThemes = [ // 滑入 { first:"slideInDown", second:"slideInLeft", third:"slideInRight" }, // 放大 { first:"zoomInDown", second:"zoomInLeft", third:"zoomInRight" }, // 翻转 { first:"flipInX", second:"flipInY", third:"flipInX" }, // 弹出 { first:"bounceInDown", second:"bounceInLeft", third:"bounceInRight" } ] var timer = null; var hbRequestCount var getAdDataCount var pageChangeCount var adDataList = [] var heartConfig = { heartbeatInterval:10, dataRefreshInterval:3600, pageChangeInterval:10, } var requestFailedCount = 0; var versionInfo = ''; let codePushOptions = { //设置检查更新的频率 //ON_APP_RESUME APP恢复到前台的时候 //ON_APP_START APP开启的时候 //MANUAL 手动检查 checkFrequency : CodePush.CheckFrequency.ON_APP_START }; export default class MyPage extends Component { constructor(props) { super(props); this.state = { baseInfo: null, contentItem0:null, contentItem1:null, contentItem2:null, animationTheme:{}, contentDisplayStatus:false, syncMessage: "初始化..." , errorMessage: '加载中...', progress: { receivedBytes:0, totalBytes:0 }, updating:true, macAddress: '', versionInfo:'未知' }; } //更新函数 async codePushUpdate() { await CodePush.getUpdateMetadata(CodePush.UpdateState.RUNNING) .then((metadata: LocalPackage) => { this.setState({ versionInfo: metadata ? 'b'+NativeModules.BuildConfig.versionCode+"-" + metadata.label : 'b'+ NativeModules.BuildConfig.versionCode}); versionInfo = this.state.versionInfo; }, (error: any) => { this.setState({ versionInfo: "Unknown"}); versionInfo = this.state.versionInfo; }); await CodePush.disallowRestart(); await CodePush.sync( { mandatoryInstallMode: CodePush.InstallMode.IMMEDIATE, installMode: CodePush.InstallMode.IMMEDIATE}, this.codePushStatusDidChange.bind(this), this.codePushDownloadDidProgress.bind(this) ); await CodePush.allowRestart(); } // 监听更新状态 codePushStatusDidChange(syncStatus) { switch(syncStatus) { case CodePush.SyncStatus.CHECKING_FOR_UPDATE: this.setState({ syncMessage: "检查更新" }); break; case CodePush.SyncStatus.DOWNLOADING_PACKAGE: this.setState({ syncMessage: "下载更新" }); break; case CodePush.SyncStatus.AWAITING_USER_ACTION: this.setState({ syncMessage: "等待用户操作" }); break; case CodePush.SyncStatus.INSTALLING_UPDATE: this.setState({ syncMessage: "安装更新" }); break; case CodePush.SyncStatus.UP_TO_DATE: this.setState({ syncMessage: "已更新到最新程序", updating: false }); break; case CodePush.SyncStatus.UPDATE_IGNORED: this.setState({ syncMessage: "更新被取消", updating: false }); break; case CodePush.SyncStatus.UPDATE_INSTALLED: this.setState({ syncMessage: "更新已安装,重启应用后生效", updating: false }); break; case CodePush.SyncStatus.UNKNOWN_ERROR: this.setState({ syncMessage: "未知错误", updating: false }); break; } } codePushDownloadDidProgress(progress) { this.setState({ progress }); } // 列表滚动 updateContent() { if (adDataList.length <=0) return false; if (curAdIndex >= adDataList.length) { curAdIndex = 0 } this.setState({contentItem0:adDataList[curAdIndex]}); if (curAdIndex + 1 < adDataList.length) this.setState({contentItem1:adDataList[curAdIndex+1]}); else this.setState({contentItem1:null}); if (curAdIndex + 2 < adDataList.length) this.setState({contentItem2:adDataList[curAdIndex+2]}); else this.setState({contentItem2:null}); curAdIndex+=3 return true; } hbRequest() { return HttpUtils.post(NativeModules.BuildConfig.apiHost + 'api/wxDeviceScreenAd/heartbeat?deviceId=' + encodeURIComponent(this.state.macAddress), {version:this.state.versionInfo}) .then(result => { if (result.code == 200) { let config = JSON.parse(result.data.config); heartConfig.heartbeatInterval = config.heartbeatInterval heartConfig.dataRefreshInterval=config.dataRefreshInterval heartConfig.pageChangeInterval=config.pageChangeInterval // 动画划入 if(config.animationTheme == 0){ this.setState({ animationTheme:animationThemes[0] }) }else if(config.animationTheme == 1){ // 放大 this.setState({ animationTheme:animationThemes[1] }) }else if(config.animationTheme == 2){ // 淡入 this.setState({ animationTheme:animationThemes[2] }) }else if(config.animationTheme == 3){ // 弹入 this.setState({ animationTheme:animationThemes[3] }) } } else { //do nothing } }) .catch(error => { requestFailedCount++ this.setState({ versionInfo: versionInfo+`[${requestFailedCount}]`}); }) }  showErrMsg(errMsg) { this.setState({contentDisplayStatus: false}) this.setState({errorMessage : errMsg}); } getAdDataList(first) { HttpUtils.get(NativeModules.BuildConfig.apiHost + 'api/wxDeviceScreenAd/list?deviceId=' + encodeURIComponent(this.state.macAddress) + '&pageNum=1&pageSize=1000') .then(result => { if (result.code != 200) { this.showErrMsg(result.message+'\n'+this.state.macAddress); } else if (result.data.list) { adDataList = result.data.list; if (this.updateContent()) { this.setState({contentDisplayStatus: true}) } else { this.showErrMsg(errorMsg.ERR_NO_DATA); } } else {  this.showErrMsg(errorMsg.ERR_DATA_GET); } }) .catch(error => { if (first) { this.showErrMsg(error.message); } else { requestFailedCount++ this.setState({ versionInfo: versionInfo+`[${requestFailedCount}]`}); } }) } getBaseInfo() { HttpUtils.get(NativeModules.BuildConfig.apiHost + 'api/wxDeviceScreenAd/info?deviceId=' + encodeURIComponent(this.state.macAddress)) .then(result => { if (result.code != 200) { this.showErrMsg(result.message+'\n'+this.state.macAddress); } else if (result.data) { this.setState({baseInfo:result.data}); } else { this.showErrMsg(errorMsg.ERR_DATA_GET); } }) .catch(error => { this.showErrMsg(error.message); }) } componentDidMount() { this.codePushUpdate(); DeviceInfo.getMACAddress().then((mac)=>{ if (mac=='' || mac==null ) { if (NativeModules.BuildConfig.buildType == 'debug') { this.setState({macAddress : this.testMac}) this.startAd() } else { this.showErrMsg(errorMsg.ERR_MAC_GET); } } else { this.setState({macAddress : mac}) this.startAd() } }).catch(e => { this.showErrMsg(errorMsg.ERR_START_AD); }) } componentWillUnmount(){ if (timer) clearTimeout(timer) } async routine() { hbRequestCount -=1; getAdDataCount -=1; pageChangeCount -=1; try { if (getAdDataCount<=0) { this.getAdDataList(false) getAdDataCount = heartConfig.dataRefreshInterval } else if (hbRequestCount<=0) { this.hbRequest() hbRequestCount = heartConfig.heartbeatInterval } if (pageChangeCount <= 0) { //页面切换间隔 if (this.state.contentDisplayStatus && this.state.baseInfo) { this.setState({ contentDisplayStatus: false}) if (this.updateContent()) { this.setState({ contentDisplayStatus: true}) } } else { await this.getBaseInfo() await this.getAdDataList(true) getAdDataCount = heartConfig.dataRefreshInterval hbRequestCount = heartConfig.heartbeatInterval } pageChangeCount = heartConfig.pageChangeInterval } } catch(e){ this.setState({ versionInfo: versionInfo+'[E]'}); } timer = setTimeout(()=>{ this.routine(); },1000); } startAd() { hbRequestCount = 0; getAdDataCount = 0; pageChangeCount = 0; this.routine(); } getContentViewItemUplayer(contentItem) { if (contentItem.type == 0) { if (contentItem.subType == 2) return ( ) if (contentItem.subType == 6) return ( ) if (contentItem.subType == 7) return ( ) return null; } } getContentViewItemActionStr(contentItem) { if (contentItem.type == 0) { if (contentItem.subType == 2) return '扫码秒杀'; else if (contentItem.subType == 6) return '扫码砍价'; else if (contentItem.subType == 7) return '扫码拼团'; else return '扫码领取'; } } getContentViewItemMerchantName(contentItem) { if (contentItem.type == 0) { if (contentItem.target.merchantVoList.length > 1) return '多商户通用'; else return contentItem.target.merchantVoList[0].merchantName; } } getContentViewItem(contentItem, annomation) { if (!contentItem) return ( ) actionText = this.getContentViewItemActionStr(contentItem); merchantName = this.getContentViewItemMerchantName(contentItem); // console.warn(annomation) return ( {/* 列表 */} {/* 券的title */} {contentItem.target.title} {/* 售价 */} {contentItem.target.salePriceStr} {/* 面额 */} ¥{contentItem.target.priceStr} {/* */} {/* 优惠券底部商户名称 */} {merchantName} {contentItem.target.merchantVoList[0].buildingName}{contentItem.target.merchantVoList[0].floorName} {actionText} {this.getContentViewItemUplayer(contentItem)} ) } getContentView() { if (this.state.contentDisplayStatus) { return ( {this.getContentViewItem(this.state.contentItem0,this.state.animationTheme.first)} {this.getContentViewItem(this.state.contentItem1,this.state.animationTheme.second)} {this.getContentViewItem(this.state.contentItem2,this.state.animationTheme.third)} ) }else{ return ( {this.state.errorMessage} ) } } getUpdateView() { if (this.state.progress.totalBytes > 0) return ( {this.state.syncMessage}{'\n'} {this.state.progress.receivedBytes} of {this.state.progress.totalBytes} bytes received{'\n'} ); return ( {this.state.syncMessage} ); } getAdView(){ if (this.state.baseInfo) { return ( {/* 头部title二维码开始 */} {/* 券列表展示列表开始 */} {this.getContentView()} {/* 底部商场信息展示开始 */} 小程序 公众号 {this.state.versionInfo} );} else { return ( {/* 头部title二维码开始 */} {/* 券列表展示列表开始 */} {this.getContentView()} {/* 底部商场信息展示开始 */} {this.state.versionInfo} ); } } render() { if (this.state.updating) { return this.getUpdateView(); } return this.getAdView(); } } const styles = StyleSheet.create({ updatePage:{ flex: 2, width:'100%', height:'100%', backgroundColor:'transparent', textAlign :'center', textAlignVertical:'center', fontSize: 63/PixelRatio.get(), color: 'darkblue' }, //layer background background:{ flex: 1, width:'100%', height:'100%' }, //layer top title:{ flex: 6, flexDirection: 'row', alignItems: 'center', paddingLeft:42/PixelRatio.get(), paddingRight:42/PixelRatio.get(), backgroundColor:'transparent' }, content:{ flex: 18, flexDirection: 'column', alignItems: 'center', backgroundColor:'transparent' }, bottom:{ flex: 2, flexDirection: 'row', alignItems: 'center', paddingLeft:42/PixelRatio.get(), paddingRight:42/PixelRatio.get(), backgroundColor:'transparent' }, //layer title titleImagePlace: { flex: 2, paddingTop: '20%', paddingLeft: '15%', alignItems: 'center', backgroundColor:'transparent' }, titleImage: { width:'100%', height:'100%', flex: 1, backgroundColor:'transparent' }, titleQrcodeBonder: { width:'100%', height:'100%', alignItems: 'center', flexDirection: 'column', flex: 1, backgroundColor:'transparent' }, titleQrcodePlacehold: { flex: 5, backgroundColor:'transparent' }, titleQrcode: { flex: 6, width:'100%', height:'100%', backgroundColor:'transparent' }, //layer bottom bottomLogoBackground: { flex: 3, borderRadius:16/PixelRatio.get(), marginTop: 26/PixelRatio.get(), marginBottom: 26/PixelRatio.get(), backgroundColor:'transparent',//'rgba(255,255,255,0.5)', }, bottomLogo: { width:'100%', height:'100%', backgroundColor:'transparent' }, bottomQrcode1Background : { flex: 1, width:'100%', height:'100%', marginLeft: 21/PixelRatio.get(), paddingTop: 27/PixelRatio.get(), paddingBottom: 11/PixelRatio.get(), flexDirection: 'column', backgroundColor:'transparent' }, bottomQrcode2Background : { flex: 1, width:'100%', height:'100%', marginLeft: 21/PixelRatio.get(), paddingTop: 26/PixelRatio.get(), paddingBottom: 11/PixelRatio.get(), flexDirection: 'column', backgroundColor:'transparent' }, bottomQrcode1: { flex: 2, width:'100%', height:'100%', backgroundColor:'transparent' }, bottomQrcode2: { flex: 2, width:'100%', height:'100%', backgroundColor:'transparent' }, bottomQrcode1Str: { flex: 1, textAlign :'center', textAlignVertical:'center', fontSize: 16/PixelRatio.get(), color : 'white', backgroundColor:'transparent' }, bottomQrcode2Str: { flex: 1, textAlign :'center', textAlignVertical:'center', fontSize: 16/PixelRatio.get(), color : 'white', backgroundColor:'transparent' }, bottomPlacehold: { flex: 8, width:'100%', height:'100%', backgroundColor:'transparent', textAlign :'right', textAlignVertical:'bottom', fontSize: 27/PixelRatio.get(), color : 'gray' }, //layer content item contentItem:{ flex: 1, width:'100%', height:'100%', flexDirection: 'column', backgroundColor:'transparent' }, contentItemDownLayer:{ position:'absolute', width:'100%', height:'100%', flexDirection: 'column', alignItems: 'center', backgroundColor:'transparent' }, contentItemUpLayer:{ width:210/PixelRatio.get(), height:153/PixelRatio.get(), position:'absolute', backgroundColor:'transparent' }, contentItemTop:{ flex: 3, width:'100%', height:'100%', paddingLeft: 66/PixelRatio.get(), paddingRight: 53/PixelRatio.get(), paddingTop: 40/PixelRatio.get(), flexDirection: 'row', alignItems: 'center', backgroundColor:'transparent' }, contentItemBottom:{ flex: 1, width:'100%', height:'100%', paddingLeft: 66/PixelRatio.get(), paddingRight: 53/PixelRatio.get(), paddingBottom: 40/PixelRatio.get(), flexDirection: 'row', alignItems: 'center', backgroundColor:'transparent' }, //layer content item top contentItemTopCoverImg:{ flex: 5, width:'100%', height:'100%', borderRadius:27/PixelRatio.get(), backgroundColor:'transparent' }, contentItemTopDetail:{ flex: 6, width:'100%', height:'100%', paddingLeft: 20/PixelRatio.get(), paddingRight: 20/PixelRatio.get(), alignItems: 'center', backgroundColor:'transparent' }, contentItemTopQrcode:{ flex: 5, width:'100%', height:'100%', // borderStyle:"solid", // borderWidth:1, // borderColor:"red", marginLeft:18/PixelRatio.get(), backgroundColor:'transparent' }, //layer content item bottom contentItemBottomMerchantName:{ flex: 5, width:'100%', height:'100%', alignItems: 'center', color:"black", backgroundColor:'transparent', textAlign :'center', textAlignVertical:'center', fontSize: 27/PixelRatio.get(), fontWeight : 'bold' }, contentItemBottomPlacehold:{ flex: 6, fontSize: 27/PixelRatio.get(), paddingLeft: 27/PixelRatio.get(), paddingRight: 79/PixelRatio.get(), width:'100%', height:'100%', color:"black", textAlignVertical:'center', backgroundColor:'transparent', }, contentItemBottomAction:{ flex: 5, width:'100%', height:'100%', backgroundColor:'transparent', textAlign :'center', textAlignVertical:'center', fontSize: 36/PixelRatio.get(), color: 'black', // borderStyle:"solid", // borderWidth:1, // borderColor:"red" }, // 券的title contentItemTopDetailTitle:{ flex: 2, // height:'100%', width:'100%', marginTop:"2%", // borderStyle:"solid", // borderWidth:1, // borderColor:"red", backgroundColor:'transparent', textAlign :'left', color:"black", textAlignVertical:'center', fontSize: 53/PixelRatio.get(), }, /* contentItemTopDetailRemark:{ flex: 1, width:'100%', height:'100%', backgroundColor:'transparent', textAlign :'left', textAlignVertical:'center', fontSize: 27/PixelRatio.get(), color : 'gray' }, */ contentItemTopDetailPrice:{ flex: 2, width:'100%', height:'100%', backgroundColor:'transparent', flexDirection: 'row', }, // 售价的样式 contentItemTopDetailCurPrice:{ position:"absolute", bottom:10, left:0, width:'100%', height:'100%', flexDirection: 'row', backgroundColor:'transparent', }, contentItemTopDetailCurPriceStr:{ backgroundColor:'transparent', fontSize:96/PixelRatio.get(), fontFamily:"PingFangSC-Bold", fontWeight: "bold", textAlign :'left', textAlignVertical:'bottom', color : 'red' }, contentItemTopDetailCurPriceStrUnit:{ backgroundColor:'transparent', textAlign :'left', textAlignVertical:'bottom', paddingBottom: 16/PixelRatio.get(), fontSize: 48/PixelRatio.get(), color : 'red' }, // 面额的样式 contentItemTopDetailSalePrice:{ position:"absolute", bottom:2, left:0, // flex: 1, paddingTop:50, width:'100%', // height:'100%', backgroundColor:'transparent', }, contentItemTopDetailSalePriceStr:{ width:'100%', height:'100%', backgroundColor:'transparent', textAlign :'left', textAlignVertical:'bottom', fontSize: 27/PixelRatio.get(), textDecorationLine: 'line-through', color : 'gray' }, });