main_tab_navigation.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. import React, {Component} from 'react';
  2. import {
  3. StyleSheet,
  4. View,
  5. Text,
  6. TouchableOpacity,
  7. Alert,
  8. Platform,
  9. Linking,
  10. Image,
  11. } from 'react-native';
  12. import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
  13. import FontAwesome from 'react-native-vector-icons/FontAwesome';
  14. import Ionicons from 'react-native-vector-icons/Ionicons';
  15. import {Carousel, Modal, Progress, Provider} from '@ant-design/react-native';
  16. import {NavigationContainer} from '@react-navigation/native';
  17. import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
  18. import {
  19. conf,
  20. confClick,
  21. homeClick,
  22. home,
  23. personal,
  24. personalClick,
  25. search,
  26. searchClick,
  27. } from '../../source/icon/icon';
  28. import {SvgXml} from 'react-native-svg';
  29. import * as WeChat from 'react-native-wechat-lib';
  30. import home_navigation from './home_navigation';
  31. import tax_navigation from './tax_navigation';
  32. import personal_navigation from './personal_navigation';
  33. import configure_navigation from './configure_navigation';
  34. import {RetrieveData} from '../../data/storage';
  35. import {
  36. isFirstTime,
  37. isRolledBack,
  38. packageVersion,
  39. currentVersion,
  40. checkUpdate,
  41. downloadUpdate,
  42. switchVersion,
  43. switchVersionLater,
  44. markSuccess,
  45. downloadAndInstallApk,
  46. } from 'react-native-update';
  47. function MyTabBar({state, descriptors, navigation}) {
  48. return (
  49. <View style={{flexDirection: 'row'}}>
  50. {state.routes.map((route, index) => {
  51. const {options} = descriptors[route.key];
  52. const label =
  53. options.tabBarLabel !== undefined
  54. ? options.tabBarLabel
  55. : options.title !== undefined
  56. ? options.title
  57. : route.name;
  58. const isFocused = state.index === index;
  59. const onPress = () => {
  60. const event = navigation.emit({
  61. type: 'tabPress',
  62. target: route.key,
  63. });
  64. if (!isFocused && !event.defaultPrevented) {
  65. navigation.navigate(route.name);
  66. }
  67. };
  68. const onLongPress = () => {
  69. navigation.emit({
  70. type: 'tabLongPress',
  71. target: route.key,
  72. });
  73. };
  74. return (
  75. <TouchableOpacity
  76. key={route.key}
  77. accessibilityRole="button"
  78. accessibilityStates={isFocused ? ['selected'] : []}
  79. accessibilityLabel={options.tabBarAccessibilityLabel}
  80. testID={options.tabBarTestID}
  81. onPress={onPress}
  82. onLongPress={onLongPress}
  83. style={{
  84. flex: 1,
  85. height: 50,
  86. flexDirection: 'row',
  87. justifyContent: 'center',
  88. alignItems: 'center',
  89. }}>
  90. <Text style={{color: isFocused ? '#673ab7' : '#222'}}>{label}</Text>
  91. </TouchableOpacity>
  92. );
  93. })}
  94. </View>
  95. );
  96. }
  97. const Tab = createBottomTabNavigator();
  98. import _updateConfig from '../../update.json';
  99. const {appKey} = _updateConfig[Platform.OS];
  100. export default class Main_tab_navigation extends Component {
  101. constructor(props) {
  102. super(props);
  103. this.state = {
  104. received: 0,
  105. total: 0,
  106. proportion: 0,
  107. isDownload: false,
  108. authority: '',
  109. };
  110. }
  111. render() {
  112. return (
  113. <Provider>
  114. <NavigationContainer>
  115. <Tab.Navigator
  116. screenOptions={({route}) => ({
  117. tabBarIcon: ({focused, color, size}) => {
  118. let iconName;
  119. if (route.name === 'home_navigation') {
  120. iconName = focused ? (
  121. <SvgXml height={25} xml={homeClick()} />
  122. ) : (
  123. <SvgXml height={25} xml={home()} />
  124. );
  125. } else if (route.name === 'tax_navigation') {
  126. iconName = focused ? (
  127. <SvgXml height={25} xml={searchClick()} />
  128. ) : (
  129. <SvgXml height={25} xml={search()} />
  130. );
  131. } else if (route.name === 'configure_navigation') {
  132. iconName = focused ? (
  133. <SvgXml height={25} xml={confClick()} />
  134. ) : (
  135. <SvgXml height={25} xml={conf()} />
  136. );
  137. } else if (route.name === 'personal_navigation') {
  138. iconName = focused ? (
  139. <SvgXml height={25} xml={personalClick()} />
  140. ) : (
  141. <SvgXml height={25} xml={personal()} />
  142. );
  143. }
  144. return iconName;
  145. // return <Ionicons name={iconName} size={size} color={color} />;
  146. // return (<Image
  147. // source={require('../../source/img/search.png')}
  148. // style={{height: 16, width: 16}}
  149. // />
  150. // );
  151. },
  152. })}
  153. tabBarOptions={{
  154. activeTintColor: '#2A67FE',
  155. inactiveTintColor: 'gray',
  156. }}>
  157. <Tab.Screen
  158. name="home_navigation"
  159. component={home_navigation}
  160. options={{title: '首页'}}
  161. />
  162. <Tab.Screen
  163. name="tax_navigation"
  164. component={tax_navigation}
  165. options={{title: '查询'}}
  166. />
  167. <Tab.Screen
  168. name="configure_navigation"
  169. component={configure_navigation}
  170. options={{title: '配置'}}
  171. />
  172. <Tab.Screen
  173. name="personal_navigation"
  174. component={personal_navigation}
  175. options={{title: '我的'}}
  176. />
  177. </Tab.Navigator>
  178. </NavigationContainer>
  179. <Modal
  180. title="更新进度"
  181. transparent
  182. maskClosable
  183. visible={this.state.isDownload}
  184. closable={false}>
  185. <View style={{paddingVertical: 20}}>
  186. <View
  187. style={{
  188. flexDirection: 'row',
  189. justifyContent: 'space-between',
  190. alignItems: 'center',
  191. }}>
  192. <View style={{marginRight: 10, height: 4, flex: 1}}>
  193. <Progress percent={this.state.proportion} />
  194. </View>
  195. <Text>{this.state.proportion}%</Text>
  196. </View>
  197. </View>
  198. </Modal>
  199. </Provider>
  200. );
  201. }
  202. async componentDidMount(): void {
  203. if (isFirstTime) {
  204. // 必须调用此更新成功标记方法
  205. // 否则默认更新失败,下一次启动会自动回滚
  206. markSuccess();
  207. console.log('更新完成');
  208. } else if (isRolledBack) {
  209. console.log('刚刚更新失败了,版本被回滚.');
  210. }
  211. await this.getAuthority();
  212. await this.checkUpdate();
  213. WeChat.registerApp('wxc4f72f029a280bc4', 'universalLink').then((value) => {
  214. console.log(value);
  215. });
  216. }
  217. getAuthority = async () => {
  218. let authority = await RetrieveData('authority');
  219. if (authority) {
  220. this.setState({
  221. authority: authority,
  222. });
  223. }
  224. };
  225. doUpdate = async (info) => {
  226. try {
  227. this.setState({
  228. isDownload: true,
  229. });
  230. const hash = await downloadUpdate(info, {
  231. onDownloadProgress: ({received, total}) => {
  232. if (received !== '' && received !== null) {
  233. if (total !== '' && total !== null) {
  234. let proportion = (parseInt(received) / parseInt(total)) * 100;
  235. this.setState({
  236. proportion: proportion,
  237. });
  238. }
  239. }
  240. this.setState({
  241. received,
  242. total,
  243. });
  244. },
  245. });
  246. this.setState({
  247. isDownload: false,
  248. });
  249. Alert.alert('提示', '下载完毕,是否重启应用?', [
  250. {
  251. text: '是',
  252. onPress: () => {
  253. switchVersion(hash);
  254. },
  255. },
  256. {text: '否'},
  257. {
  258. text: '下次启动时',
  259. onPress: () => {
  260. switchVersionLater(hash);
  261. },
  262. },
  263. ]);
  264. } catch (err) {
  265. Alert.alert('更新失败', err.message);
  266. }
  267. };
  268. checkUpdate = async () => {
  269. if (__DEV__) {
  270. // 开发模式不支持热更新,跳过检查
  271. return;
  272. }
  273. let info;
  274. try {
  275. info = await checkUpdate(appKey);
  276. } catch (err) {
  277. Alert.alert('更新检查失败', err.message);
  278. return;
  279. }
  280. if (info.expired) {
  281. Alert.alert('提示', '您的应用版本已更新,点击确定下载安装新版本', [
  282. {
  283. text: '确定',
  284. onPress: () => {
  285. if (info.downloadUrl) {
  286. // apk可直接下载安装
  287. if (
  288. Platform.OS === 'android' &&
  289. info.downloadUrl.endsWith('.apk')
  290. ) {
  291. this.setState({
  292. isDownload: true,
  293. });
  294. downloadAndInstallApk({
  295. url: info.downloadUrl,
  296. onDownloadProgress: ({received, total}) => {
  297. if (received !== '' && received !== null) {
  298. if (total !== '' && total !== null) {
  299. let proportion =
  300. (parseInt(received) / parseInt(total)) * 100;
  301. this.setState({
  302. proportion: parseInt(proportion),
  303. });
  304. if (parseInt(proportion) >= 100) {
  305. this.setState({
  306. isDownload: false,
  307. });
  308. }
  309. }
  310. }
  311. this.setState({
  312. received,
  313. total,
  314. });
  315. },
  316. });
  317. } else {
  318. Linking.openURL(info.downloadUrl);
  319. }
  320. }
  321. },
  322. },
  323. ]);
  324. } else if (info.upToDate) {
  325. // Alert.alert('提示', '您的应用版本已是最新.');
  326. } else {
  327. Alert.alert(
  328. '提示',
  329. '检查到新的版本' + info.name + ',是否下载?\n' + info.description,
  330. [
  331. {
  332. text: '是',
  333. onPress: () => {
  334. this.doUpdate(info);
  335. },
  336. },
  337. {text: '否'},
  338. ],
  339. );
  340. }
  341. };
  342. }