Browse Source

解决冲突

Limengbo 5 years ago
parent
commit
bee476e50c
71 changed files with 1394 additions and 443 deletions
  1. 6 2
      App.js
  2. 28 23
      android/app/src/main/assets/index.android.bundle
  3. 3 8
      pages/BasePage.js
  4. 27 39
      pages/CourseDetails.js
  5. 102 0
      pages/buy/order.js
  6. 158 0
      pages/buy/ticket.js
  7. 339 157
      pages/components/CusVideo.js
  8. 155 106
      pages/components/MainPage.js
  9. 63 34
      pages/components/SchedulePage.js
  10. 7 23
      pages/components/ScrollRow.js
  11. 4 1
      pages/components/SeekBar.js
  12. 128 0
      pages/components/ShopBox.js
  13. 15 18
      pages/components/Swiper.js
  14. 0 1
      pages/components/TopicTitle.js
  15. BIN
      pages/images/shopBox/arrow.png
  16. BIN
      pages/images/shopBox/arrow@2x.png
  17. BIN
      pages/images/shopBox/arrow@3x.png
  18. BIN
      pages/images/shopBox/discount.png
  19. BIN
      pages/images/shopBox/left.png
  20. BIN
      pages/images/shopBox/left@2x.png
  21. BIN
      pages/images/shopBox/left@3x.png
  22. BIN
      pages/images/shopBox/right.png
  23. BIN
      pages/images/shopBox/right@2x.png
  24. BIN
      pages/images/shopBox/right@3x.png
  25. BIN
      pages/images/ticket/coupon-bg.png
  26. BIN
      pages/images/ticket/coupon-bg@2x.png
  27. BIN
      pages/images/ticket/coupon-bg@3x.png
  28. BIN
      pages/images/ticket/discount-bg.png
  29. BIN
      pages/images/ticket/discount-bg@2x.png
  30. BIN
      pages/images/ticket/discount-bg@3x.png
  31. BIN
      pages/images/userCenter/customer.png
  32. BIN
      pages/images/userCenter/customer@2x.png
  33. BIN
      pages/images/userCenter/customer@3x.png
  34. BIN
      pages/images/userCenter/discount.png
  35. BIN
      pages/images/userCenter/discount@2x.png
  36. BIN
      pages/images/userCenter/discount@3x.png
  37. BIN
      pages/images/userCenter/gift.png
  38. BIN
      pages/images/userCenter/gift@2x.png
  39. BIN
      pages/images/userCenter/gift@3x.png
  40. BIN
      pages/images/userCenter/left.png
  41. BIN
      pages/images/userCenter/order.png
  42. BIN
      pages/images/userCenter/order@2x.png
  43. BIN
      pages/images/userCenter/order@3x.png
  44. BIN
      pages/images/userCenter/service.png
  45. BIN
      pages/images/userCenter/service@2x.png
  46. BIN
      pages/images/userCenter/service@3x.png
  47. BIN
      pages/images/video/loading1.png
  48. BIN
      pages/images/video/loading10.png
  49. BIN
      pages/images/video/loading11.png
  50. BIN
      pages/images/video/loading12.png
  51. BIN
      pages/images/video/loading13.png
  52. BIN
      pages/images/video/loading14.png
  53. BIN
      pages/images/video/loading15.png
  54. BIN
      pages/images/video/loading16.png
  55. BIN
      pages/images/video/loading17.png
  56. BIN
      pages/images/video/loading18.png
  57. BIN
      pages/images/video/loading19.png
  58. BIN
      pages/images/video/loading2.png
  59. BIN
      pages/images/video/loading20.png
  60. BIN
      pages/images/video/loading3.png
  61. BIN
      pages/images/video/loading4.png
  62. BIN
      pages/images/video/loading5.png
  63. BIN
      pages/images/video/loading6.png
  64. BIN
      pages/images/video/loading7.png
  65. BIN
      pages/images/video/loading8.png
  66. BIN
      pages/images/video/loading9.png
  67. 14 0
      pages/services/api.js
  68. 15 0
      pages/services/library.js
  69. 151 27
      pages/userCenter.js
  70. 4 4
      pages/utils/dimensions.js
  71. 175 0
      pages/utils/efunRequest.js

+ 6 - 2
App.js

@@ -25,6 +25,8 @@ import SchedulePage from "./pages/components/SchedulePage";
 import PersonalInfo from "./pages/components/PersonalInfo";
 import CourseDetails from "./pages/CourseDetails";
 import userCenter from "./pages/userCenter";
+import Order from './pages/buy/order'
+import Ticket from './pages/buy/ticket'
 
 const RootNavigator = createStackNavigator(
   {
@@ -34,10 +36,12 @@ const RootNavigator = createStackNavigator(
     SchedulePage: { screen: SchedulePage },
     PersonalInfo: { screen: PersonalInfo },
     userCenter: { screen: userCenter },
-    CourseDetails: { screen: CourseDetails}
+    CourseDetails: { screen: CourseDetails },
+    Order: { screen: Order },
+    Ticket: { screen: Ticket },
   },
   {
-    initialRouteName: "SchoolAge",
+    initialRouteName: "MainPage",
     headerMode: "null"
   }
 );

File diff suppressed because it is too large
+ 28 - 23
android/app/src/main/assets/index.android.bundle


+ 3 - 8
pages/BasePage.js

@@ -22,13 +22,6 @@ import {
 import AndroidUtil from "../util/AndroidUtil";
 
 
-const instructions = Platform.select({
-  ios: "Press Cmd+R to reload,\n" + "Cmd+D or shake for dev menu",
-  android:
-    "Double tap R on your keyboard to reload,\n" +
-    "Shake or press menu button for dev menu"
-});
-
 type Props = {};
 var width = Dimensions.get("window").width;
 var height = Dimensions.get("window").height;
@@ -52,9 +45,11 @@ export default class BasePage extends Component<Props> {
     return width;
   }
 
-  toNextPage(params) {
+  toNextPage= (params) => {
     //跳转之前移除当前界面的监听
     this.removeListener();
+    console.log('跳转参数',params)
+    console.log(this.props)
     this.props.navigation.navigate(params);
   }
   Toast(params) {

+ 27 - 39
pages/CourseDetails.js

@@ -16,47 +16,19 @@ import {
   FlatList
 } from "react-native";
 
-import VideoExplain from './components/VideoExplain';
-import CourseListRow from './components/CourseListRow';
-
-// class CourseListRow extends Component {
-//   render() {
-//     return (
-//       <View style={styles.courseList}>
-//         <View style={[styles.padding, styles.title]}>
-//           <Text style={styles.font}>{this.props.title}</Text>
-//           <Text style={styles.color}>共28课</Text>
-//         </View>
-//         <View style={{
-//             flex: 1,
-//             height: 200,
-//           }}>
-//             <ScrollRow itemWidth={106} itemHeight={150} />
-//           </View>
-//       </View>
-//     );
-//   }
-// }
+import VideoExplain from './components/VideoExplain'
 
+class CourseList extends Component {
+  render() {
+    return (
+      <View style={styles.courseList}>
+        <View style={[styles.padding, styles.title]}>
 
-// class CourseListLine extends Component {
-//   render() {
-//     return (
-//       <View style={styles.courseList}>
-//         <View style={[styles.padding, styles.title]}>
-//           <Text style={styles.font}>{this.props.title}</Text>
-//           <Text style={styles.color}>共28课</Text>
-//         </View>
-//         <View style={{
-//             flex: 1,
-//             height: 200,
-//           }}>
-//             <ScrollRow itemWidth={106} itemHeight={150} />
-//           </View>
-//       </View>
-//     );
-//   }
-// }
+        </View>
+      </View>
+    );
+  }
+}
 
 export default class CourseDetails extends Component {
   render() {
@@ -74,5 +46,21 @@ export default class CourseDetails extends Component {
 }
 
 const styles = StyleSheet.create({
+<<<<<<< HEAD
   
+=======
+  courseList: {
+    width: '100%',
+    backgroundColor: '#fff',
+    marginTop: 8,
+  },
+  padding: {
+    paddingLeft: 20,
+    paddingRight: 20,
+    
+  },
+  title: {
+
+  }
+>>>>>>> ea0eb52ce93eb1f6e7dfff98ef67d5808565f154
 });

+ 102 - 0
pages/buy/order.js

@@ -0,0 +1,102 @@
+/* 
+ * 
+*/
+import React, { Component } from "react";
+import {
+    Platform,
+    StyleSheet,
+    Text,
+    View,
+    Image,
+    TouchableOpacity,
+    FlatList,
+    TouchableHighlight,
+    DeviceEventEmitter,
+    ScrollView
+} from "react-native";
+import BasePage from "../BasePage";
+import Dimensions from '../utils/dimensions';
+import TopicTitle from '../components/TopicTitle';
+
+export default class Order extends BasePage {
+    state = {
+        data: {
+            title: '学前课程', list: [
+                { title: '生活好榜样', time: '2019-10-01' },
+                { title: '生活好榜样2', time: '2019-10-01' },
+                { title: '生活好榜样3', time: '2019-10-01' },
+                { title: '生活好榜样第二期', time: '2019-10-01' },
+            ]
+        }
+
+    };
+    renderItem = (item, index) => {
+        return (
+            <View>
+                {
+                    index === 0
+                        ?
+                        <TopicTitle title={this.state.data.title} ifTubeShow={true} />
+                        :
+                        null
+                }
+                <View style={styles.item}>
+                    <View style={styles.left}>
+                        <Text style={styles.title}>{item.title}</Text>
+                        <Text style={styles.time}>有效期:{item.time}</Text>
+                    </View>
+                    <View style={styles.right}>
+                        <Text style={styles.study}>去学习</Text>
+                    </View>
+                </View>
+            </View>
+        )
+    }
+    render() {
+        return (
+            <FlatList
+
+                data={this.state.data.list}
+                horizontal={false}
+                renderItem={({ item, index }) => this.renderItem(item, index)}
+                keyExtractor={(item, index) => index.toString()}
+            />
+        )
+    }
+}
+
+const styles = StyleSheet.create({
+    item: {
+        width: Dimensions.width,
+        height: Dimensions.getHeight(79),
+        flexDirection: 'row',
+        justifyContent: 'space-between',
+        alignItems: 'center',
+        paddingHorizontal: 14,
+        borderTopWidth: 1,
+        borderColor: '#f0f1f5'
+    },
+    left: {
+        flexDirection: 'column'
+    },
+    title: {
+        fontSize: 18,
+        color: '#151515'
+    },
+    time: {
+        fontSize: 14,
+        color: '#555'
+    },
+    right: {
+        width: Dimensions.getWidth(83),
+        height: Dimensions.getHeight(27),
+        borderRadius: 14,
+        backgroundColor: '#ffae59',
+        justifyContent: 'center',
+        alignItems: 'center'
+    },
+    study: {
+        color: '#fff',
+        fontSize: 16
+    }
+})

+ 158 - 0
pages/buy/ticket.js

@@ -0,0 +1,158 @@
+/* 
+ * 
+*/
+import React, { Component } from "react";
+import {
+    Platform,
+    StyleSheet,
+    Text,
+    View,
+    Image,
+    TouchableOpacity,
+    FlatList,
+    TouchableHighlight,
+    DeviceEventEmitter,
+    ScrollView,
+    ImageBackground
+} from "react-native";
+import BasePage from "../BasePage";
+import Dimensions from '../utils/dimensions';
+
+export default class Ticket extends BasePage {
+    state = {
+        data: [
+            {
+                type: 1,
+                price: 12,
+                num: 6,
+                time: '2019-12-12'
+            },
+            {
+                type: 2,
+                price: 50,
+                limit: '199',
+                time: '2019-12-12'
+            }
+        ]
+    };
+    renderItem = (item, index) => {
+
+        return (
+            <View>
+                {
+                    item.type === 1
+                        ? // 抵用券
+                        <ImageBackground
+                            source={require('../images/ticket/discount-bg.png')}
+                            style={styles.type1}
+                        >
+                            <View style={styles.topInfo}>
+                                <View style={styles.left2}>
+                                    <Text style={styles.price}>
+                                        ¥{item.price}
+                                    </Text>
+                                    <Text style={styles.type}>抵用券</Text>
+                                </View>
+
+                                <View style={styles.right2}>
+                                    <Text style={styles.greyText}>购买{item.num}个单课程的奖励</Text>
+                                    <Text style={styles.greyText}>有效期:{item.time}</Text>
+                                </View>
+
+                            </View>
+                            <View style={styles.bottomInfo}>
+                                <Text style={styles.greyText}>注:开通会员时方可使用</Text>
+                                <Text style={styles.blueText}>查看订单</Text>
+                            </View>
+                        </ImageBackground>
+                        : // 优惠券
+                        <ImageBackground
+                            source={require('../images/ticket/coupon-bg.png')}
+                            style={styles.type2}
+                        >
+                            <View style={styles.left2}>
+                                <Text style={styles.price}>
+                                    ¥{item.price}
+                                </Text>
+                                <Text style={styles.type}>优惠券</Text>
+                            </View>
+
+                            <View style={styles.right2}>
+                                <Text style={styles.greyText}>满{item.limit}可用</Text>
+                                <Text style={styles.greyText}>有效期:{item.time}</Text>
+                            </View>
+                        </ImageBackground>
+                }
+            </View>
+
+        )
+    }
+    render() {
+        return (
+            <FlatList
+
+                data={this.state.data}
+                horizontal={false}
+                renderItem={({ item, index }) => this.renderItem(item, index)}
+                keyExtractor={(item, index) => index.toString()}
+            />
+        )
+    }
+}
+
+const styles = StyleSheet.create({
+    type1: {
+        width: 343,
+        height: 144,
+        flexDirection: 'column',
+        justifyContent: 'space-between',
+        alignItems: 'center',
+        paddingTop: 12,
+        paddingBottom: 14
+    },
+    type2: {
+        width: 343,
+        height: 100,
+        flexDirection: 'row',
+        justifyContent: 'flex-start',
+        alignItems: 'center',
+        paddingLeft: 27
+    },
+    left2: {
+        flexDirection: 'column',
+
+    },
+    price: {
+        color: '#ff6d2f',
+        fontSize: 19,
+        fontWeight: '500'
+    },
+    type: {
+        color: '#ff6d2f',
+        fontSize: 18,
+        fontWeight: '500'
+    },
+    right2: {
+        flexDirection: 'column'
+
+    },
+    topInfo: {
+        flexDirection: 'row',
+        alignItems: 'center'
+    },
+    bottomInfo: {
+        width: '100%',
+        paddingHorizontal: 12,
+        flexDirection: 'row',
+        alignItems: 'center',
+        justifyContent: 'space-between'
+    },
+    greyText: {
+        fontSize: 14,
+        color: '#888'
+    },
+    blueText: {
+        color: '#4a90e2',
+        fontSize: 14
+    }
+})

+ 339 - 157
pages/components/CusVideo.js

@@ -7,6 +7,7 @@ import {
   Button,
   Image,
   TouchableOpacity,
+  PanResponder,
   StyleSheet
 } from "react-native";
 import { createStackNavigator, createAppContainer } from "react-navigation";
@@ -21,7 +22,20 @@ const instructions = Platform.select({
 
 type Props = {};
 export default class CusVideo extends React.Component {
+  constructor(props) {
+    super(props);
+    this.pressStatus = false;
+    this.progress = 0;
+  }
+  config = {
+    changeX: 0,
+    changeY: 0,
+    xDiff: 0,
+    yDiff: 0
+  };
+
   state = {
+    player_status_icon: require("../images/video/start.png"),
     rate: 1,
     volume: 1,
     muted: false,
@@ -30,15 +44,20 @@ export default class CusVideo extends React.Component {
     currentTime: 0.0,
     paused: false,
     wheel: false,
-    player_status_icon: require("../images/video/start.png"),
     isFull: false,
-    needback: this.props.needback
+    needback: this.props.needback,
+    show_controller: true,
+    show_loading: true
   };
 
   render() {
+    if (!this.props.show) {
+      return null;
+    }
     return (
-      <View style={this.props.style}>
+      <View style={[this.props.style, { overflow: "hidden" }]}>
         <Video
+          {...this.videotouch.panHandlers}
           style={{ flex: 1 }}
           source={{
             uri: this.props.uri
@@ -47,9 +66,9 @@ export default class CusVideo extends React.Component {
             this.player = ref;
           }}
           // poster={this.props.poster}
-          resizeMode={this.state.resizeMode}
+          resizeMode={[this.state.resizeMode]}
           // posterResizeMode={this.state.resizeMode}
-          onBuffer={this.onBuffer}
+          onBuffer={this.onBuffer.bind(this)}
           rate={this.state.rate} //播放速率
           paused={this.state.paused} //暂停
           volume={this.state.volume} //调节音量
@@ -68,132 +87,108 @@ export default class CusVideo extends React.Component {
         />
         <View
           style={{
-            flexDirection: "row",
             position: "absolute",
             width: "100%",
-            height: 50,
+            height: "100%",
             alignItems: "center",
             justifyContent: "center"
           }}
         >
-          <View
-            style={{
-              flex: 1,
-              alignItems: "center"
-            }}
-          >
-            <VideoBack
-              needback={this.state.needback}
-              videoback={this.videoBackClick.bind(this)}
-            />
-          </View>
-          <View style={{ flex: 2 }} />
-          <View
-            style={{
-              flex: 9,
-              overflow: "hidden"
-            }}
-          />
-          <View style={{ flex: 2 }} />
-          <View
-            style={{
-              flex: 1,
-              alignItems: "center"
-            }}
-          />
-        </View>
-        <View style={[styles.player_controller]}>
-          <View
-            style={{
-              flex: 1,
-              alignItems: "center"
-            }}
-          >
-            {/* 暂停播放按钮 */}
-            <TouchableOpacity
-              //点击事件放在这个组件里才管用
-              style={{
-                justifyContent: "center",
-                width: "100%",
-                height: "100%"
-              }}
-              onPress={() => this.play()}
-            >
-              <Image
-                style={[styles.player_pause_icon]}
-                source={this.state.player_status_icon}
-              />
-            </TouchableOpacity>
-          </View>
-          <View style={{ flex: 2 }}>
-            {/* //左侧当前播放时长 */}
-            <Text style={[styles.player_time]}>
-              {formatTime(this.state.currentTime)}
-            </Text>
-          </View>
-          <View
-            style={{
-              flex: 9,
-              overflow: "hidden"
-            }}
-          >
-            {/* //中间进度条 */}
-            <SeekBar
-              style={{ flex: 1 }}
-              ref={view => (this.seekbar = view)}
-              //必须带此方法,作为滑动之后抬起的回调
-              touchUpCallBack={this.touch_up_callback.bind(this)}
-            />
-          </View>
-          <View style={{ flex: 2 }}>
-            {/* //右侧总时长 */}
-            <Text style={[styles.player_time]}>
-              {formatTime(this.state.duration)}
-            </Text>
-          </View>
-          <View
-            style={{
-              flex: 1,
-              alignItems: "center"
-            }}
-          >
-            <TouchableOpacity
-              style={{
-                justifyContent: "center",
-                width: "100%",
-                height: "100%"
-              }}
-              onPress={() => this.presentFullscreenPlayer()}
-            >
-              {/* //放大按钮 */}
-              <Image
-                style={[styles.fullscreen_icon]}
-                source={require("../images/video/fullscreen.png")}
-              />
-            </TouchableOpacity>
-          </View>
+          <Loading show={this.state.show_loading} />
         </View>
+        <TopController
+          ref={view => (this.topcontroller = view)}
+          needback={this.state.needback}
+          videoback={this.videoBackClick.bind(this)}
+        />
+        <BottomController
+          ref={view => (this.bottomcontroller = view)}
+          show={this.state.show_controller}
+          touch_up_callback={this.touch_up_callback.bind(this)}
+          full_click={this.presentFullscreenPlayer.bind(this)}
+          play_click={this.play.bind(this)}
+          duration={this.state.duration}
+          currentTime={this.state.currentTime}
+          player_status_icon={this.state.player_status_icon}
+        />
       </View>
     );
   }
 
+  componentWillMount() {
+    this.videotouch = PanResponder.create({
+      onStartShouldSetPanResponder: (evt, gestureState) => true,
+      onStartShouldSetPanResponderCapture: (evt, gestureState) => true,
+      onMoveShouldSetPanResponder: (evt, gestureState) => true,
+      onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,
+
+      onPanResponderGrant: (evt, gestureState) => {
+        this.pressStatus = true;
+        this.config.changeY = evt.nativeEvent.pageY;
+        this.config.changeX = evt.nativeEvent.pageX;
+        if (this.state.show_controller) {
+          this.hideController();
+        } else {
+          this.showController();
+        }
+        console.log("onPanResponderGrant");
+      },
+      onPanResponderStart: (evt, gestureState) => {
+        this.pressStatus = true;
+        console.log("onPanResponderStart");
+      },
+      onPanResponderMove: (evt, gestureState) => {
+        this.config.yDiff = evt.nativeEvent.pageY - this.config.changeY;
+        this.config.xDiff = evt.nativeEvent.pageX - this.config.changeX;
+        this.config.changeY = evt.nativeEvent.pageY;
+        this.config.changeX = evt.nativeEvent.pageX;
+      },
+      onPanResponderEnd: (evt, gestureState) => {
+        this.pressStatus = true;
+        console.log("onPanResponderEnd");
+      },
+      onPanResponderTerminationRequest: (evt, gestureState) => true,
+      onPanResponderRelease: (evt, gestureState) => {
+        if (this.pressStatus) {
+          this.props.onPress && this.props.onPress();
+        }
+      },
+      onPanResponderTerminate: (evt, gestureState) => {
+        // 另一个组件已经成为了新的响应者,所以当前手势将被取消。
+      },
+      onShouldBlockNativeResponder: (evt, gestureState) => {
+        // 返回一个布尔值,决定当前组件是否应该阻止原生组件成为JS响应者
+        // 默认返回true。目前暂时只支持android。
+        //基于业务交互场景,如果这里使用js事件处理,会导致容器不能左右滑动。所以设置成false.
+        return false;
+      }
+    });
+  }
+
   loadStart() {
     // alert("loadStart");
   }
+
   onBuffer({ isBuffering }: { isBuffering: boolean }) {
     //true为正在加载,false为没有加载,此处给loading提示
+    this.setState({
+      show_loading: isBuffering
+    });
     console.log("isBuffering:" + isBuffering);
   }
   onLoad = data => {
     //获取的是秒数
     this.setState({ duration: data.duration });
-    this.seekbar.setMax(data.duration);
+    this.bottomcontroller.setMax(data.duration);
   };
   onProgress = data => {
     this.setState({
       currentTime: data.currentTime
     });
-    this.seekbar.setProgress(this.state.currentTime);
+    if (this.state.show_controller) {
+      this.bottomcontroller.setProgress(this.state.currentTime);
+      this.bottomcontroller.setMax(this.state.duration);
+    }
   };
 
   onError() {
@@ -203,6 +198,7 @@ export default class CusVideo extends React.Component {
     alert("播放结束");
   }
   play() {
+    //controller的play点击无法换图...
     if (this.state.paused) {
       this.start();
     } else {
@@ -223,10 +219,7 @@ export default class CusVideo extends React.Component {
     });
     this.player_icon_index = 0;
   }
-  showToast(params) {
-    // ToastExample.message(params);
-    ToastExample.show(params, ToastExample.SHORT);
-  }
+
   seekTo(progress) {
     this.player.seek(progress);
   }
@@ -244,7 +237,7 @@ export default class CusVideo extends React.Component {
     }
 
     this.props.videofullScreenPlayer();
-    this.seekbar.setProgress(this.state.currentTime);
+    this.bottomcontroller.setProgress(this.state.currentTime);
   }
   touch_up_callback(progress) {
     //抬起之后,获取算出来的progress
@@ -271,8 +264,243 @@ export default class CusVideo extends React.Component {
       this.props.videoback();
     }
   }
+  showController() {
+    this.setState({
+      show_controller: true
+      // needback: this.props.needback
+    });
+    this.bottomcontroller.setBottom(0);
+    this.topcontroller.setTop(0);
+  }
+  hideController() {
+    this.setState({
+      show_controller: false
+      // needback: false
+    });
+    this.bottomcontroller.setBottom(-50);
+    this.topcontroller.setTop(-50);
+  }
+}
+
+/**
+ * 将秒转换为 分:秒
+ * s int 秒数
+ */
+function formatTime(s) {
+  //计算分钟
+  //算法:将秒数除以60,然后下舍入,既得到分钟数
+  var h;
+  h = Math.floor(s / 60);
+  //计算秒
+  //算法:取得秒%60的余数,既得到秒数
+  s = Math.round(s % 60);
+  //将变量转换为字符串
+  h += "";
+  s += "";
+  //如果只有一位数,前面增加一个0
+  h = h.length == 1 ? "0" + h : h;
+  s = s.length == 1 ? "0" + s : s;
+  return h + ":" + s;
+}
+class TopController extends Component {
+  state = {
+    controller_top: 0
+  };
+  render() {
+    if (this.props.needback == false) {
+      return null;
+    }
+    return (
+      <View
+        style={[styles.player_controller, { top: this.state.controller_top }]}
+      >
+        <View
+          style={{
+            flex: 1,
+            alignItems: "center"
+          }}
+        >
+          <TouchableOpacity
+            //点击事件放在这个组件里才管用
+            style={{
+              justifyContent: "center",
+              width: "100%",
+              height: "100%"
+            }}
+            onPress={() => this.props.videoback()}
+          >
+            <Image
+              style={[styles.player_pause_icon]}
+              source={require("../images/video/back.png")}
+            />
+          </TouchableOpacity>
+        </View>
+        <View style={{ flex: 2 }} />
+        <View
+          style={{
+            flex: 9,
+            overflow: "hidden"
+          }}
+        />
+        <View style={{ flex: 2 }} />
+        <View
+          style={{
+            flex: 1,
+            alignItems: "center"
+          }}
+        />
+      </View>
+    );
+  }
+
+  setTop(top) {
+    this.setState({
+      controller_top: top
+    });
+  }
+}
+
+class Loading extends Component {
+  state = {
+    image_arr: [
+      require("../images/video/loading1.png"),
+      require("../images/video/loading2.png"),
+      require("../images/video/loading3.png"),
+      require("../images/video/loading3.png"),
+      require("../images/video/loading4.png"),
+      require("../images/video/loading5.png"),
+      require("../images/video/loading6.png"),
+      require("../images/video/loading7.png"),
+      require("../images/video/loading8.png"),
+      require("../images/video/loading9.png"),
+      require("../images/video/loading10.png"),
+      require("../images/video/loading11.png"),
+      require("../images/video/loading12.png"),
+      require("../images/video/loading13.png"),
+      require("../images/video/loading14.png"),
+      require("../images/video/loading15.png"),
+      require("../images/video/loading16.png"),
+      require("../images/video/loading17.png"),
+      require("../images/video/loading18.png"),
+      require("../images/video/loading19.png"),
+      require("../images/video/loading20.png")
+    ],
+    loading_index: 0
+  };
+  render() {
+    if (this.props.show) {
+      return (
+        <Image
+          source={this.state.image_arr[this.state.loading_index]}
+          style={{ width: "20%", height: "10%", backgroundColor: "blue" }}
+        />
+      );
+    } else {
+      return null;
+    }
+  }
 }
 
+class BottomController extends Component {
+  state = {
+    controller_bottom: 0
+  };
+
+  render() {
+    return (
+      <View
+        style={[
+          styles.player_controller,
+          { bottom: this.state.controller_bottom }
+        ]}
+      >
+        <View
+          style={{
+            flex: 1,
+            alignItems: "center"
+          }}
+        >
+          {/* 暂停播放按钮 */}
+          <TouchableOpacity
+            //点击事件放在这个组件里才管用
+            style={{
+              justifyContent: "center",
+              width: "100%",
+              height: "100%"
+            }}
+            onPress={() => this.props.play_click()}
+          >
+            <Image
+              style={[styles.player_pause_icon]}
+              source={this.props.player_status_icon}
+            />
+          </TouchableOpacity>
+        </View>
+        <View style={{ flex: 2 }}>
+          {/* //左侧当前播放时长 */}
+          <Text style={[styles.player_time]}>
+            {formatTime(this.props.currentTime)}
+          </Text>
+        </View>
+        <View
+          style={{
+            flex: 9,
+            overflow: "hidden"
+          }}
+        >
+          {/* //中间进度条 */}
+          <SeekBar
+            style={{ flex: 1 }}
+            ref={view => (this.seekbar = view)}
+            //必须带此方法,作为滑动之后抬起的回调
+            touchUpCallBack={this.props.touch_up_callback}
+          />
+        </View>
+        <View style={{ flex: 2 }}>
+          {/* //右侧总时长 */}
+          <Text style={[styles.player_time]}>
+            {formatTime(this.props.duration)}
+          </Text>
+        </View>
+        <View
+          style={{
+            flex: 1,
+            alignItems: "center"
+          }}
+        >
+          <TouchableOpacity
+            style={{
+              justifyContent: "center",
+              width: "100%",
+              height: "100%"
+            }}
+            onPress={() => this.props.full_click()}
+          >
+            {/* //放大按钮 */}
+            <Image
+              style={[styles.fullscreen_icon]}
+              source={require("../images/video/fullscreen.png")}
+            />
+          </TouchableOpacity>
+        </View>
+      </View>
+    );
+  }
+  setMax(duration) {
+    this.seekbar.setMax(duration);
+  }
+  getMax() {
+    return this.seekbar.getMax();
+  }
+  setBottom(bottom) {
+    this.setState({
+      controller_bottom: bottom
+    });
+  }
+  setProgress(currentTime) {
+    this.seekbar.setProgress(currentTime);
+  }
+}
 const styles = StyleSheet.create({
   player_controller: {
     flexDirection: "row",
@@ -280,8 +508,7 @@ const styles = StyleSheet.create({
     width: "100%",
     height: 50,
     alignItems: "center",
-    justifyContent: "center",
-    bottom: 0
+    justifyContent: "center"
   },
   player_pause_icon: {
     width: "80%",
@@ -309,51 +536,6 @@ const styles = StyleSheet.create({
 });
 
 /**
- * 将秒转换为 分:秒
- * s int 秒数
- */
-function formatTime(s) {
-  //计算分钟
-  //算法:将秒数除以60,然后下舍入,既得到分钟数
-  var h;
-  h = Math.floor(s / 60);
-  //计算秒
-  //算法:取得秒%60的余数,既得到秒数
-  s = Math.round(s % 60);
-  //将变量转换为字符串
-  h += "";
-  s += "";
-  //如果只有一位数,前面增加一个0
-  h = h.length == 1 ? "0" + h : h;
-  s = s.length == 1 ? "0" + s : s;
-  return h + ":" + s;
-}
-class VideoBack extends Component {
-  render() {
-    if (this.props.needback) {
-      return (
-        <TouchableOpacity
-          //点击事件放在这个组件里才管用
-          style={{
-            justifyContent: "center",
-            width: "100%",
-            height: "100%"
-          }}
-          onPress={() => this.props.videoback()}
-        >
-          <Image
-            style={[styles.player_pause_icon]}
-            source={require("../images/video/back.png")}
-          />
-        </TouchableOpacity>
-      );
-    } else {
-      return null;
-    }
-  }
-}
-
-/**
   使用方法
   <CusVideo
       uri={this.state.video_uri}

+ 155 - 106
pages/components/MainPage.js

@@ -32,57 +32,101 @@ import MySwiper from "./Swiper";
 import Dimensions from '../utils/dimensions';
 import TopicTitle from './TopicTitle';
 import ScrollRow from "./ScrollRow";
-// import console from 'console';
+import LibraryUrl from '../services/library'
+import { ScrollView } from "react-native-gesture-handler";
 
 export default class MainPage extends BasePage {
   constructor(props) {
     super(props);
   }
 
+  componentDidMount() {
+    LibraryUrl.getIndex('PRESCHOOL').success(res => {
+      console.log(res)
+      const monthTopicTitle = res.data.monthTopic.zone.title;
+      const monthTopicScroll = res.data.monthTopic.zoneCourseVOList;
+      const schedule = res.data.schedule;
+      const hotCourse = res.data.hotCourse;
+      const recommend = res.data.recommend; //全部课程
+      const banner = res.data.banner; //轮播图
+      // const listData = [];
+      // for(let item in res.data){
+      //   console.log(item)
+      //   listData.push(1)
+      // }
+      // console.log(typeof listData)
+      // console.log(listData)
+      // console.log(listData.length)
+      this.setState({
+        // listData: listData.length? listData : [],
+        hotCourse,
+        monthTopicTitle,
+        monthTopicScroll,
+        schedule,
+        recommend,
+        banner
+      })
+      console.log(this.state.banner)
+    })
+  }
+
   state = {
     grade: '大学',
     text: '小伙子',
     ifGradeMenuShow: false,
     fadeAnim: new Animated.Value(0),
+    schedule: [],
+    recommend: [],
+    listData: [],
+    banner:[]
   }
 
   render() {
+    // const abc =Object.keys(this.state.data).map((k)=>this.state.data[k])
     return (
-        <View style={{ flex: 1 }} onPress={this.hideGradeMenu}>
-          {/* 尝试切换为sectionList 分组显示 */}
-          <SectionList
-            sections={sectionData}
-            renderItem={({ item }) => {
-              return this.loadFlatItem(item);
-            }}
-            keyExtractor={(item, index) => item.key.toString()}
-            ListHeaderComponent={() => this.headerorfooterComponent()}
-            renderSectionHeader={this.sectionTitle}
-            onScroll={this.hideGradeMenu}
-          />
-          {
-            this.state.ifGradeMenuShow ? (
-              <Animated.View
-                style={{
-                  ...styles.callUpGrade,
-                  opacity: this.state.fadeAnim
-                }}>
-                <View style={styles.gradeItem}>
-                  <Text style={styles.gradeText}>小学</Text>
-                </View>
-                <View style={styles.gradeItemMid}>
-                  <Text style={styles.gradeText}>学前</Text>
-                </View>
-                <View style={styles.gradeItem}>
-                  <Text style={styles.gradeText}>中学</Text>
-                </View>
-              </Animated.View>
-            ) : (
-                null
-              )
+      <View style={{ flex: 1 }} onPress={this.hideGradeMenu}>
+        {/* <SectionList     sectionList组件 性能好 但是针对当前布局是否有要用的必要,以后可能迭代
+          sections={this.state.listData}
+          renderItem={({ item }) => {
+            return this.loadFlatItem(item);
+          }}
+          keyExtractor={(item, index) => item.key.toString()}
+          ListHeaderComponent={() => this.headerorfooterComponent()}
+          renderSectionHeader={this.sectionTitle}
+          onScroll={this.hideGradeMenu}
+        /> */}
+        <ScrollView style={{ height: Dimensions.height }} >
+          {this.headerorfooterComponent()}
+          {this.getSwiperElement()}
+          {this.getScheduleElement()}
+          {this.getMonthTopic()}
+          {this.getHotCourse()}
+          {this.getAllCourses()}
+        </ScrollView>
 
-          }
-        </View>
+        {
+          this.state.ifGradeMenuShow ? (
+            <Animated.View
+              style={{
+                ...styles.callUpGrade,
+                opacity: this.state.fadeAnim
+              }}>
+              <View style={styles.gradeItem}>
+                <Text style={styles.gradeText}>小学</Text>
+              </View>
+              <View style={styles.gradeItemMid}>
+                <Text style={styles.gradeText}>学前</Text>
+              </View>
+              <View style={styles.gradeItem}>
+                <Text style={styles.gradeText}>中学</Text>
+              </View>
+            </Animated.View>
+          ) : (
+              null
+            )
+
+        }
+      </View>
     );
   }
 
@@ -128,7 +172,6 @@ export default class MainPage extends BasePage {
   }
   // 渲染轮播图
   getSwiperElement() {
-    console.log('进入swiper')
     return (
       <View
         style={{
@@ -137,12 +180,10 @@ export default class MainPage extends BasePage {
           justifyContent: "center",
           alignItems: "center",
           flexDirection: "row",
-          // backgroundColor: 'red'
         }}
       >
         <View
           style={{
-            // width: Dimensions.width,
             width: Dimensions.getWidth(358),
             height: Dimensions.getDp(153),
             justifyContent: "center",
@@ -153,28 +194,25 @@ export default class MainPage extends BasePage {
             autoplay={true}
             loop={true}
             ifShowMiddle={true}
+            data={this.state.banner}
           />
         </View>
       </View>
     );
   }
   // 渲染课程表
-  getScheduleElement(data) {
-    let arr = [];
-    let index = 0;
-    for (let item of data.item.icon_item) {
-      arr.push(
+  getScheduleElement() {
+    let renderScheduleItem = (item, index) => {
+      return (
         <TouchableOpacity
           style={{ width: 172, height: 86, marginRight: 12 }}
-          onPress={() => {
-            alert(Dimensions.width.toString());
-          }}
+          onPress={()=>this.toNextPage('SchedulePage')}
           key={index}
           activeOpacity={1}
         >
           <Image
             source={{
-              uri: item.icon
+              uri: item.boothContent
             }}
             key={index}
             style={{
@@ -186,18 +224,7 @@ export default class MainPage extends BasePage {
             }}
           />
         </TouchableOpacity>
-      );
-      if (index < data.item.icon_item.length - 1) {
-        arr.push(
-          <View
-            key={item.name}
-            style={{
-              flex: 0.1
-            }}
-          />
-        );
-      }
-      index++;
+      )
     }
     return (
       <View
@@ -205,7 +232,6 @@ export default class MainPage extends BasePage {
           flex: 1,
           flexDirection: "column",
           height: 160,
-          // backgroundColor: 'blue'
         }}
       >
         <TopicTitle title={'课程表:第一周'} ifTubeShow={true} />
@@ -213,78 +239,101 @@ export default class MainPage extends BasePage {
           style={{
             flex: 2,
             flexDirection: "row",
-            // backgroundColor: 'green',
             alignItems: 'center',
             paddingLeft: 10
           }}
         >
-          {arr}
+          {this.state.schedule.map((item, index) => renderScheduleItem(item, index))}
         </View>
       </View>
     );
   }
-  // 渲染每一个块儿
+  // 渲染月主题
+  getMonthTopic() {
+    return (
+      <View style={{
+        flex: 1,
+        height: 225,
+      }}>
+        <TopicTitle title={this.state.monthTopicTitle} summary={'每天30分钟'} ifTubeShow={true} />
+        <ScrollRow itemWidth={352} itemHeight={153} nav={this.props.navigation.navigate} data={this.state.monthTopicScroll} />
+      </View>
+
+    );
+  }
+  // 渲染热门课程
+  getHotCourse() {
+    return (
+      <View style={{
+        flex: 1,
+        height: 220,
+      }}>
+        <TopicTitle title={'热门课程'} ifTubeShow={true} />
+        <ScrollRow itemWidth={106} itemHeight={150} nav={this.props.navigation.navigate} data={this.state.hotCourse} />
+      </View>
+    )
+  }
+  // 渲染全部课程
+  getAllCourses() {
+    return (
+      <View>
+        {this.state.recommend.map((item, index) => {
+          return (
+            <View
+              style={{
+                flex: 1,
+                height: 240,
+              }}
+              key={index}
+            >
+              {index === 0
+                ?
+                null
+                :
+                <View style={{ width: Dimensions.width, height: 4, backgroundColor: '#f0f1f5' }}></View>
+              }
+              <TopicTitle title={item.zone.title} />
+              <ScrollRow itemWidth={106} itemHeight={150} nav={this.props.navigation.navigate} data={item.zoneCourseVOList} />
+            </View>
+          )
+        })}
+      </View>
+
+
+    )
+  }
+  // 渲染每一个块儿  sectionList组件的data,没有用到,以后可能会用
   loadFlatItem(data) {
-    console.log(data)
-    console.log(data.typea)
-    switch (data.typea) {
+
+
+    switch (data.title) {
       // 轮播图
-      case 1:
-        console.log(1)
+      case 'banner':
         return this.getSwiperElement();
         break;
       // 课程表
-      case 2:
-        console.log(2)
-        return this.getScheduleElement(data);
+      case 'schedule':
+        return this.getScheduleElement();
         break;
       // 大图主题
-      case 3:
-        console.log(3)
-        return (
-          <View style={{
-            flex: 1,
-            height: 225,
-          }}>
-            <TopicTitle title={'五月主题:五月主题,去看看不同的世界'} summary={'每天30分钟'} ifTubeShow={true} />
-            <ScrollRow itemWidth={352} itemHeight={153} />
-          </View>
-
-        );
+      case 'monthTopic':
+        return this.getMonthTopic();
         break;
       // 热门课程
-      case 4:
-        return (
-          <View style={{
-            flex: 1,
-            height: 220,
-          }}>
-            <TopicTitle title={'热门广场'} ifTubeShow={true} />
-            <ScrollRow itemWidth={106} itemHeight={150} />
-          </View>
-        )
+      case 'hotCourse':
+        return this.getHotCourse();
         break;
-      case 5:
-        return (
-          <View style={{
-            flex: 1,
-            height: 240,
-          }}>
-            <TopicTitle title={'生活好榜样'} summary={'死数据不是动态渲染'} />
-            <ScrollRow itemWidth={106} itemHeight={150} />
-          </View>
-        )
+      case 'recommend':
+        return this.getAllCourses();
         break;
       default:
         break;
     }
   }
-  // 渲染每一个section的title
+  // 渲染每一个section的title  sectionList组件的data,没有用到,以后可能会用
   sectionTitle = (info) => {
-    console.log(info)
     switch (info.section.title) {
       case 'operation':
-        console.log('进入运营区头部', info.section.title)
         return (
           <View
             style={{

+ 63 - 34
pages/components/SchedulePage.js

@@ -16,6 +16,8 @@ import {
   TouchableOpacity,
   ImageBackground,
   FlatList,
+  findNodeHandle,
+  UIManager,
   StatusBar,
   Button,
   DeviceEventEmitter
@@ -39,12 +41,14 @@ export default class SchedulePage extends BasePage {
     super(props);
     this.state = {
       statusbar_hidden: false,
+      video_show: false,
+      x: 0.0,
+      y: 0.0,
       videoImg_flex: 1,
-      videoImg_width: "100%",
-      videoImg_height: "100%",
-      video_flex: 0,
-      video_width: "0%",
-      video_height: "0%",
+      videoImage_width: 0,
+      videoImage_height: 0,
+      videoImage_x: 0.0,
+      videoImage_y: 0.0,
       video_uri:
         "http://efunvideo.ai160.com/vs2m/056/05602002/05602002001/05602002001.m3u8",
       title_height: "6%",
@@ -107,20 +111,11 @@ export default class SchedulePage extends BasePage {
                   "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1556277324856&di=dc1548a0c5ba10481af922e174912937&imgtype=0&src=http%3A%2F%2Fwww.51pptmoban.com%2Fd%2Ffile%2F2012%2F05%2F12%2F82c4568a90055adcf8fbb896f0841c69.jpg"
               }}
               style={{
-                flex: this.state.videoImg_flex,
-                width: this.state.videoImg_width,
-                height: this.state.videoImg_height
+                width: "100%",
+                height: "100%"
               }}
-            />
-            <CusVideo
-              uri={this.state.video_uri}
-              ref={view => (this.video = view)}
-              needback={false}
-              videofullScreenPlayer={this.fullScreenPlayer.bind(this)}
-              style={{
-                flex: this.state.video_flex,
-                width: this.state.video_width,
-                height: this.state.video_height
+              ref={c => {
+                this.video_image = c;
               }}
             />
           </View>
@@ -230,6 +225,22 @@ export default class SchedulePage extends BasePage {
             />
           </View>
         </View>
+        <CusVideo
+          show={this.state.video_show}
+          uri={this.state.video_uri}
+          ref={view => (this.video = view)}
+          needback={false}
+          videoback={() => alert("videoback")}
+          videofullScreenPlayer={this.fullScreenPlayer.bind(this)}
+          style={{
+            left: this.state.x,
+            top: this.state.y,
+            width: this.state.video_width,
+            height: this.state.video_height,
+            overflow: "hidden",
+            position: "absolute"
+          }}
+        />
       </View>
     );
   }
@@ -247,20 +258,28 @@ export default class SchedulePage extends BasePage {
     if (!this.state.isFull) {
       Orientation.lockToLandscape();
       this.setState({
-        title_height: "0%",
+        // title_height: "0%",
         video_frame_height: "100%",
-        seat_height: "0%",
-        flatlist_height: "0%",
+        // seat_height: "0%",
+        // flatlist_height: "0%",
         statusbar_hidden: true,
-        isFull: true
+        isFull: true,
+        x: 0,
+        y: 0,
+        video_width: "100%",
+        video_height: "100%"
       });
     } else {
       Orientation.lockToPortrait();
       this.setState({
-        title_height: "6%",
+        // title_height: "6%",
         video_frame_height: "32%",
-        seat_height: "2%",
-        flatlist_height: "60%",
+        // seat_height: "2%",
+        // flatlist_height: "60%",
+        x: this.state.videoImage_x,
+        y: this.state.videoImage_y,
+        video_width: this.state.videoImage_width,
+        video_height: this.state.videoImage_height,
         statusbar_hidden: false,
         isFull: false
       });
@@ -269,15 +288,25 @@ export default class SchedulePage extends BasePage {
   changeUrl(url) {
     //切换视频并且播放
     // alert(url);
-    this.setState({
-      videoImg_flex: 0,
-      videoImg_width: "0%",
-      videoImg_height: "0%",
-      video_flex: 1,
-      video_width: "100%",
-      video_height: "100%",
-      video_uri: url
-    });
+    const handle = findNodeHandle(this.video_image);
+    setTimeout(() => {
+      UIManager.measure(handle, (x, y, width, height, pageX, pageY) => {
+        console.warn(x, y, width, height, pageX, pageY);
+        this.setState({
+          x: pageX,
+          y: pageY,
+          video_width: width,
+          video_height: height,
+          videoImage_width: width,
+          videoImage_height: height,
+          videoImage_x: pageX,
+          videoImage_y: pageY,
+          video_show: true,
+          video_uri: url
+        });
+      });
+    }, 0);
+
     this.video.refreshVideo();
     this.video.start();
   }

+ 7 - 23
pages/components/ScrollRow.js

@@ -3,6 +3,7 @@
  *      itemWidth: 每一个图片宽度
  *      itemHeight: 每一个图片高度
  *      data:  数据 Arrary
+ *      nav: 路由方法
  */
 
 import React, { Component } from "react";
@@ -14,6 +15,7 @@ import {
     TouchableOpacity,
     Image
 } from "react-native";
+import BasePage from '../BasePage'
 import Dimensions from '../utils/dimensions'
 
 export default class ScrollRow extends Component {
@@ -23,25 +25,7 @@ export default class ScrollRow extends Component {
         return (
             <FlatList
 
-                data={[{
-                    summary: 'Title Text', key: 'item1', icon:
-                        "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1556277324856&di=dc1548a0c5ba10481af922e174912937&imgtype=0&src=http%3A%2F%2Fwww.51pptmoban.com%2Fd%2Ffile%2F2012%2F05%2F12%2F82c4568a90055adcf8fbb896f0841c69.jpg",
-                }, {
-                    summary: 'Title Text', key: 'item2', icon:
-                        "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1556277324856&di=dc1548a0c5ba10481af922e174912937&imgtype=0&src=http%3A%2F%2Fwww.51pptmoban.com%2Fd%2Ffile%2F2012%2F05%2F12%2F82c4568a90055adcf8fbb896f0841c69.jpg",
-                }, {
-                    summary: 'Title Text', key: 'item3', icon:
-                        "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1556277324856&di=dc1548a0c5ba10481af922e174912937&imgtype=0&src=http%3A%2F%2Fwww.51pptmoban.com%2Fd%2Ffile%2F2012%2F05%2F12%2F82c4568a90055adcf8fbb896f0841c69.jpg",
-                }, {
-                    summary: 'Title Text', key: 'item4', icon:
-                        "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1556277324856&di=dc1548a0c5ba10481af922e174912937&imgtype=0&src=http%3A%2F%2Fwww.51pptmoban.com%2Fd%2Ffile%2F2012%2F05%2F12%2F82c4568a90055adcf8fbb896f0841c69.jpg",
-                }, {
-                    title: 'Title Text', key: 'item5', icon:
-                        "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1556277324856&di=dc1548a0c5ba10481af922e174912937&imgtype=0&src=http%3A%2F%2Fwww.51pptmoban.com%2Fd%2Ffile%2F2012%2F05%2F12%2F82c4568a90055adcf8fbb896f0841c69.jpg",
-                }, {
-                    summary: 'Title Text', key: 'item6', icon:
-                        "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1556277324856&di=dc1548a0c5ba10481af922e174912937&imgtype=0&src=http%3A%2F%2Fwww.51pptmoban.com%2Fd%2Ffile%2F2012%2F05%2F12%2F82c4568a90055adcf8fbb896f0841c69.jpg",
-                }]}
+                data={this.props.data}
                 horizontal={true}
                 renderItem={({ item, separators }) => this.renderItem(item, separators)}
             />
@@ -49,6 +33,7 @@ export default class ScrollRow extends Component {
     }
 
     renderItem(item, separators) {
+        console.log(this.toNextPage)
         return (
             <TouchableOpacity
                 style={{
@@ -59,9 +44,7 @@ export default class ScrollRow extends Component {
                     alignItems: 'center',
                     marginLeft: 9,
                 }}
-                onPress={() => {
-                    alert(item.title);
-                }}
+                onPress={() => this.props.nav('CourseDetails')}
                 activeOpacity={1}
             >
                 <View style={{
@@ -73,7 +56,8 @@ export default class ScrollRow extends Component {
                 }}>
                     <Image
                         source={{
-                            uri: item.icon
+                            uri: item.zoneCourse ? item.zoneCourse.iconImg : item.boothContent
+                            // uri: item.icon
                         }}
                         style={{
                             borderRadius: 10,

+ 4 - 1
pages/components/SeekBar.js

@@ -7,8 +7,8 @@ import {
   Image,
   Button,
   PanResponder,
-  findNodeHandle,
   ImageBackground,
+  findNodeHandle,
   UIManager,
   DeviceEventEmitter
 } from "react-native";
@@ -196,6 +196,9 @@ export default class SeekBar extends BasePage {
       max: setmax
     });
   }
+  getMax() {
+    return this.state.max;
+  }
   setProgress(progress) {
     if (this.state.view_width > 0) {
       this.progress = progress;

+ 128 - 0
pages/components/ShopBox.js

@@ -0,0 +1,128 @@
+/** 
+ * @param: 
+ *      data: 商品列表
+ *      discount: 优惠信息
+ */
+
+import React, { Component } from "react";
+import {
+    StyleSheet,
+    Text,
+    View,
+    Image,
+    TouchableOpacity,
+    ImageBackground,
+} from "react-native";
+import Dimensions from '../utils/dimensions'
+
+const styles = StyleSheet.create({
+    bigWrapper: {
+        flexDirection: 'column',
+    },
+    wrapper: {
+        // width: Dimensions.width,
+        // height: 45,
+        justifyContent: "center",
+        flexDirection: 'row',
+        justifyContent: 'space-around',
+        paddingHorizontal: 7
+    },
+    item: {
+        width: Dimensions.width * 168 / 375,
+        height: Dimensions.width * 168 / 375 * 120 / 168,
+        paddingLeft: 10
+    },
+    title: {
+        fontSize: 20,
+        color: '#fff',
+        marginTop: 15,
+    },
+    line2: {
+        flexDirection: 'row',
+        alignItems: 'center',
+        // marginTop: 3
+    },
+    price: {
+        fontSize: 24,
+        color: '#fff',
+        fontWeight: 'bold',
+        marginRight: 5
+    },
+    originPrice: {
+        fontSize: 11,
+        color: '#fff',
+        textDecorationLine: 'line-through'
+    },
+    line3: {
+        alignItems: 'center',
+        flexDirection: 'row',
+        marginTop: 8
+    },
+    buy: {
+        fontSize: 18,
+        color: '#fff'
+    },
+    discount: {
+        width: Dimensions.width,
+        alignItems: 'center',
+        justifyContent: 'center',
+        height: 100
+    },
+    discountIcon: {
+        width: Dimensions.width * 343 / 375,
+        height: Dimensions.width * 343 / 375 * 80 / 343
+    }
+
+})
+
+export default class ShopBox extends Component {
+
+    renderGoods = (item, index) => {
+        return (
+            <ImageBackground
+                source={item.background}
+                style={styles.item}
+                key={index}
+            >
+                <Text
+                    style={styles.title}
+                >{item.title}</Text>
+                <View
+                    style={styles.line2}
+                >
+                    <Text style={styles.price}>¥{item.price}</Text>
+                    <Text style={styles.originPrice}>原价: {item.originPrice}</Text>
+                </View>
+                <View
+                    style={styles.line3}
+                >
+                    <Text style={styles.buy}>立即购买</Text>
+                    <Image
+                        source={require('../images/shopBox/arrow.png')}
+                        style={styles.arrow}
+                    />
+
+                </View>
+            </ImageBackground>
+        )
+    }
+
+    render() {
+
+        return (
+            <View style={styles.bigWrapper}>
+                <View style={styles.wrapper}>
+                    {this.props.data.map((item, index) => this.renderGoods(item, index))}
+                </View>
+                <View style={styles.discount}>
+                    <Image
+                        source={this.props.discount.icon}
+                        stytle={styles.discountIcon}
+                    />
+                </View>
+
+            </View>
+
+        );
+    }
+}

+ 15 - 18
pages/components/Swiper.js

@@ -21,6 +21,7 @@ const dotActive = <View style={{ backgroundColor: '#fff', width: 8, height: 8, b
 export default class Swipers extends Component {
 
   render() {
+    console.log(this.props)
     return (
       <Swiper
         style={styles.wrapper}
@@ -34,24 +35,20 @@ export default class Swipers extends Component {
         dot={dotRegular}
         activeDot={dotActive}
       >
-        <View style={styles.slide}>
-          <Image
-            source={{
-              uri:
-                "https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=1295208965,3056573814&fm=26&gp=0.jpg"
-            }}
-            style={styles.img}
-          />
-        </View>
-        <View style={styles.slide}>
-          <Image
-            source={{
-              uri:
-                "https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=1295208965,3056573814&fm=26&gp=0.jpg"
-            }}
-            style={styles.img}
-          />
-        </View>
+        {
+          this.props.data.map((item, index) => {
+            return (
+              <View style={styles.slide} key={index}>
+                <Image
+                  source={{
+                    uri: item.boothContent
+                  }}
+                  style={styles.img}
+                />
+              </View>
+            )
+          })
+        }
       </Swiper>
     );
   }

+ 0 - 1
pages/components/TopicTitle.js

@@ -65,7 +65,6 @@ export default class TopicTitle extends Component {
             tube = 1
         }
         const tubeColor = this.props.tubeColor ? this.props.tubeColor : '#ffd101';
-        console.log('背景色', this.props)
         return (
             <View
                 style={{

BIN
pages/images/shopBox/arrow.png


BIN
pages/images/shopBox/arrow@2x.png


BIN
pages/images/shopBox/arrow@3x.png


BIN
pages/images/shopBox/discount.png


BIN
pages/images/shopBox/left.png


BIN
pages/images/shopBox/left@2x.png


BIN
pages/images/shopBox/left@3x.png


BIN
pages/images/shopBox/right.png


BIN
pages/images/shopBox/right@2x.png


BIN
pages/images/shopBox/right@3x.png


BIN
pages/images/ticket/coupon-bg.png


BIN
pages/images/ticket/coupon-bg@2x.png


BIN
pages/images/ticket/coupon-bg@3x.png


BIN
pages/images/ticket/discount-bg.png


BIN
pages/images/ticket/discount-bg@2x.png


BIN
pages/images/ticket/discount-bg@3x.png


BIN
pages/images/userCenter/customer.png


BIN
pages/images/userCenter/customer@2x.png


BIN
pages/images/userCenter/customer@3x.png


BIN
pages/images/userCenter/discount.png


BIN
pages/images/userCenter/discount@2x.png


BIN
pages/images/userCenter/discount@3x.png


BIN
pages/images/userCenter/gift.png


BIN
pages/images/userCenter/gift@2x.png


BIN
pages/images/userCenter/gift@3x.png


BIN
pages/images/userCenter/left.png


BIN
pages/images/userCenter/order.png


BIN
pages/images/userCenter/order@2x.png


BIN
pages/images/userCenter/order@3x.png


BIN
pages/images/userCenter/service.png


BIN
pages/images/userCenter/service@2x.png


BIN
pages/images/userCenter/service@3x.png


BIN
pages/images/video/loading1.png


BIN
pages/images/video/loading10.png


BIN
pages/images/video/loading11.png


BIN
pages/images/video/loading12.png


BIN
pages/images/video/loading13.png


BIN
pages/images/video/loading14.png


BIN
pages/images/video/loading15.png


BIN
pages/images/video/loading16.png


BIN
pages/images/video/loading17.png


BIN
pages/images/video/loading18.png


BIN
pages/images/video/loading19.png


BIN
pages/images/video/loading2.png


BIN
pages/images/video/loading20.png


BIN
pages/images/video/loading3.png


BIN
pages/images/video/loading4.png


BIN
pages/images/video/loading5.png


BIN
pages/images/video/loading6.png


BIN
pages/images/video/loading7.png


BIN
pages/images/video/loading8.png


BIN
pages/images/video/loading9.png


+ 14 - 0
pages/services/api.js

@@ -0,0 +1,14 @@
+const url = {
+    library_url: 'http://ott80testlibrary.yifangjiaoyu.cn/mobile/page'
+}
+
+
+export default class APIConfig {
+    constructor(props){
+        this.library_url = 'http://ott80testlibrary.yifangjiaoyu.cn/mobile/page'
+    }
+    static getLibraryUrl(path){
+        console.log(url.library_url + path)
+        return url.library_url + path
+    }
+} 

+ 15 - 0
pages/services/library.js

@@ -0,0 +1,15 @@
+import APIConfig from './api.js';
+import efunRequest from '../utils/efunRequest'
+
+export default class LibraryUrl {
+    
+    static aabbcc(){
+        alert(123)
+    }
+    static getIndex(ageGroup) {
+        console.log(ageGroup)
+        return efunRequest.getHttpRequest().url(APIConfig.getLibraryUrl(`/category`)).params({
+            ageGroup
+        }).get();
+    }
+}

+ 151 - 27
pages/userCenter.js

@@ -18,28 +18,58 @@ import {
     ScrollView
 } from "react-native";
 import BasePage from "./BasePage";
-import Dimensions from './utils/dimensions'
+import Dimensions from './utils/dimensions';
+import ShopBox from "./components/ShopBox";
+import TopicTitle from './components/TopicTitle';
+import ScrollRow from './components/ScrollRow';
 
 export default class userCenter extends BasePage {
     state = {
         nickName: "初始昵称",
-        schoolName: "未设置",
+        user: {
+            nickName: '啊啊啊',
+            avatar: 'https://gss2.bdstatic.com/-fo3dSag_xI4khGkpoWK1HF6hhy/baike/w%3D268%3Bg%3D0/sign=043fea1806f431adbcd2443f730dcb92/f636afc379310a550591d17ebd4543a983261086.jpg'
+        },
         ifDiscount: true,
         isVIP: false,
         btnArr: [
-            { title: '订单', icon: 'https://facebook.github.io/react-native/docs/assets/favicon.png' },
-            { title: '优惠券', icon: 'https://facebook.github.io/react-native/docs/assets/favicon.png' },
-            { title: '活动', icon: 'https://facebook.github.io/react-native/docs/assets/favicon.png' },
-            { title: '客服', icon: 'https://facebook.github.io/react-native/docs/assets/favicon.png' },
-        ]
+            { title: '订单', icon: require('./images/userCenter/order.png'), goTo: 'Order' },
+            { title: '抵用券', icon: require('./images/userCenter/discount.png'), goTo: 'Ticket' },
+            { title: '客服', icon: require('./images/userCenter/service.png'), goTo: 'Order' },
+        ],
+        shopData: [
+            { title: '1个月', originPrice: '199', price: '49', background: require('./images/shopBox/left.png') },
+            { title: '12个月', originPrice: '499', price: '199', background: require('./images/shopBox/right.png') }
+        ],
+        discount: { title: '限时秒杀', icon: require('./images/shopBox/discount.png') },
+        courseSroll: [{
+            summary: 'Title Text', key: 'item1', icon:
+                "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1556277324856&di=dc1548a0c5ba10481af922e174912937&imgtype=0&src=http%3A%2F%2Fwww.51pptmoban.com%2Fd%2Ffile%2F2012%2F05%2F12%2F82c4568a90055adcf8fbb896f0841c69.jpg",
+        }, {
+            summary: 'Title Text', key: 'item2', icon:
+                "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1556277324856&di=dc1548a0c5ba10481af922e174912937&imgtype=0&src=http%3A%2F%2Fwww.51pptmoban.com%2Fd%2Ffile%2F2012%2F05%2F12%2F82c4568a90055adcf8fbb896f0841c69.jpg",
+        }, {
+            summary: 'Title Text', key: 'item3', icon:
+                "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1556277324856&di=dc1548a0c5ba10481af922e174912937&imgtype=0&src=http%3A%2F%2Fwww.51pptmoban.com%2Fd%2Ffile%2F2012%2F05%2F12%2F82c4568a90055adcf8fbb896f0841c69.jpg",
+        }, {
+            summary: 'Title Text', key: 'item4', icon:
+                "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1556277324856&di=dc1548a0c5ba10481af922e174912937&imgtype=0&src=http%3A%2F%2Fwww.51pptmoban.com%2Fd%2Ffile%2F2012%2F05%2F12%2F82c4568a90055adcf8fbb896f0841c69.jpg",
+        }, {
+            title: 'Title Text', key: 'item5', icon:
+                "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1556277324856&di=dc1548a0c5ba10481af922e174912937&imgtype=0&src=http%3A%2F%2Fwww.51pptmoban.com%2Fd%2Ffile%2F2012%2F05%2F12%2F82c4568a90055adcf8fbb896f0841c69.jpg",
+        }, {
+            summary: 'Title Text', key: 'item6', icon:
+                "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1556277324856&di=dc1548a0c5ba10481af922e174912937&imgtype=0&src=http%3A%2F%2Fwww.51pptmoban.com%2Fd%2Ffile%2F2012%2F05%2F12%2F82c4568a90055adcf8fbb896f0841c69.jpg",
+        }]
+
+
     };
-    render() {
-        let btnRender = null;
-        this.state.btnArr.forEach((item) => {
-            btnRender + (
+    renderBtn = (item, index) => {
+        return (
+            <TouchableOpacity key={index} onPress={() => this.goTo(`${item.goTo}`)}>
                 <View style={styles.btnItem}>
                     <Image
-                        source={{ uri: item.icon }}
+                        source={item.icon}
                         style={styles.btnIcon}
                     />
                     <Text
@@ -48,32 +78,61 @@ export default class userCenter extends BasePage {
                         {item.title}
                     </Text>
                 </View>
-            )
-        })
+            </TouchableOpacity>
+        )
+    }
+    render() {
         return (
-            <ScrollView style={{ height: 1000, overflow: 'scroll' }}>
+
+            <ScrollView style={{ height: 1100, overflow: 'scroll', backgroundColor: '#fff' }}>
                 <View style={styles.topSection}>
                     <ImageBackground
                         source={
                             require('./images/userCenter/top-bg.png')
                         }
-                        style={{width: '100%',height: 203}}
+                        style={{ width: '100%', height: 203 }}
                     >
                         <View style={styles.userInfo}>
-                            
+                            <TouchableOpacity onPress={() => this.goTo(`PersonalInfo`)}>
+                                <Image style={styles.userAvatar} source={{ uri: this.state.user.avatar }} />
+                            </TouchableOpacity>
+
+                            <View style={styles.userRight}>
+                                <View style={styles.userName}>
+                                    <Text style={styles.userNameText}>{this.state.user.nickName}</Text>
+                                    <Image style={styles.vipTag} source={require('./images/common/vip.png')}></Image>
+                                </View>
+                                <View style={styles.userName}>
+                                    <Text style={styles.vipSologan}>开通vip</Text>
+                                </View>
+                            </View>
                         </View>
-                        <View style={styles.btnBox}>
-                            {btnRender}
+                        <View style={styles.btnBoxWrapper}>
+                            <View style={styles.btnBox}>
+                                {this.state.btnArr.map((item, index) => this.renderBtn(item, index))}
+                            </View>
                         </View>
+
                     </ImageBackground>
 
                 </View>
-                <View style={styles.discountSection}></View>
-                <View style={styles.recordSection}></View>
-                <View style={styles.collectSection}></View>
+                <View style={styles.discountSection}>
+                    <ShopBox data={this.state.shopData} discount={this.state.discount} />
+                </View>
+                <View style={styles.recordSection}>
+                    <TopicTitle title={'观看记录'} ifTubeShow={true} />
+                    <ScrollRow itemWidth={106} itemHeight={153} data={this.state.courseSroll} />
+                </View>
+                <View style={styles.collectSection}>
+                    <TopicTitle title={'我的课程'} ifTubeShow={true} />
+                    <ScrollRow itemWidth={106} itemHeight={153} data={this.state.courseSroll} />
+                </View>
             </ScrollView>
         )
     }
+    goTo(index) {
+        this.toNextPage(index)
+    }
 }
 
 const styles = StyleSheet.create({
@@ -82,19 +141,84 @@ const styles = StyleSheet.create({
         width: Dimensions.width,
         // backgroundColor: 'red'
     },
+    userInfo: {
+        width: Dimensions.width,
+        height: 70,
+        flexDirection: 'row',
+        justifyContent: 'flex-start',
+        alignItems: 'center',
+    },
+    userAvatar: {
+        width: 67,
+        height: 67,
+        borderRadius: 55,
+        marginHorizontal: 12
+    },
+    userRight: {
+        flexDirection: 'column',
+    },
+    userName: {
+        flexDirection: 'row',
+        alignItems: 'center',
+    },
+    userNameText: {
+        fontSize: 18,
+        color: '#fff',
+        fontWeight: '500',
+        marginRight: 9
+    },
+    vipSologan: {
+        fontSize: 14,
+        color: '#fff',
+    },
+    btnBoxWrapper: {
+        width: Dimensions.width,
+        alignItems: 'center',
+        marginTop: 16
+    },
+    btnBox: {
+        width: Dimensions.width * 343 / 375,
+        height: 100,
+        borderRadius: 10,
+        shadowColor: '#000',
+        // shadowOffset: 1,
+        shadowOpacity: 2,
+        shadowRadius: 5,
+        elevation: 4,
+        backgroundColor: '#fff',
+        justifyContent: 'space-around',
+        flexDirection: 'row',
+    },
+    btnItem: {
+        width: 48,
+        height: '100%',
+        flexDirection: 'column',
+        justifyContent: 'center',
+        alignItems: 'center'
+    },
+    btnIcon: {
+        width: 36,
+        height: 24,
+        marginBottom: 7
+    },
+    btnTitle: {
+        color: '#3f3f3f',
+        fontSize: 16,
+    },
     discountSection: {
         width: Dimensions.width,
-        height: 242,
-        backgroundColor: 'green'
+        // height: 242,
+        // backgroundColor: 'green'
     },
     recordSection: {
         width: Dimensions.width,
         height: 235,
-        backgroundColor: 'blue'
+        // backgroundColor: 'blue'
     },
     collectSection: {
         width: Dimensions.width,
         height: 235,
-        backgroundColor: 'yellow'
-    }
+        // backgroundColor: 'yellow'
+    },
+
 })

+ 4 - 4
pages/utils/dimensions.js

@@ -24,11 +24,11 @@ export default Dimensions  = {
 	getFontSize:function(size){
 		return size*fontScale;
 	},
-	getWidth:function(width){
-		return width*widthScale;
+	getWidth:function(px){
+		return  width * px /375;
 	},
-	getHeight:function(height){
-		return height*fontScale;
+	getHeight:function(px){
+		return width / 375 * px ;
 	},
 	/* px转dp */
 	getDp: px => PixelRatio.roundToNearestPixel(px),

+ 175 - 0
pages/utils/efunRequest.js

@@ -0,0 +1,175 @@
+//http 网络请求封装类(和业务相关的代码请不要写进这个类中)
+// import UserDataStorage from './UserDataStorage';
+
+class efunRequest {
+
+    constructor() {
+        this._url = '';
+        this._params = {};
+        this._data = {};
+        this._header = {};
+        this.xmlHTTPRequest = null;
+        this._onSuccess = null;
+        this._onFailed = null;
+        this._deserialize = null;
+    }
+
+    request(method) {
+
+        const paramStr = () => {
+            if (!this._params) {
+                return ''
+            }
+            var pstr = '';
+            for (let key in this._params) {
+                pstr += `${key}=${this._params[key]}&`;
+            }
+            return pstr.slice(0, -1);
+        }
+
+        this.xmlHTTPRequest = new XMLHttpRequest();
+        this.xmlHTTPRequest.open(method, this._url + '?' + paramStr(), true);
+        this.xmlHTTPRequest.setRequestHeader('Content-Type', 'application/' + (method == 'POST' || method == 'PUT' ? 'x-www-form-urlencoded' : 'text'));
+
+        for (let key in this._header) {
+            this.xmlHTTPRequest.setRequestHeader(key, this._header[key]);
+        }
+
+        this.xmlHTTPRequest.onreadystatechange = () => {
+            this.whenResponse();
+        }
+
+        var sendBody = null;
+        if (this._data && (method == 'POST' || method == 'PUT')) {
+            var arr = new Array();
+            var i = 0;
+            for (var attr in this._data) {
+                arr[i] = encodeURIComponent(attr) + '=' + encodeURIComponent(this._data[attr]);
+                i++;
+            }
+            sendBody = '&' + arr.join('&');
+        }
+        this.xmlHTTPRequest.send(sendBody);
+        return this;
+    }
+
+    get() {
+        this.request('GET');
+        return this;
+    }
+
+    post() {
+        this.request('POST');
+        return this;
+    }
+
+    put() {
+        this.request('PUT');
+        return this;
+    }
+
+    delete() {
+        this.request('DELETE');
+        return this;
+    }
+
+    whenResponse() {
+        if (this.xmlHTTPRequest.readyState != 4) {
+            return;
+        }
+
+        if (this._deserialize) {
+            this._deserialize(this.xmlHTTPRequest.responseText, this);
+            return;
+        }
+
+        let cb = this.xmlHTTPRequest.status == 200 ? this._onSuccess : this._onFailed;
+        if (!cb) {
+            return;
+        }
+        cb(this.xmlHTTPRequest.status, this.xmlHTTPRequest.responseText);
+    }
+
+    success(callback) {
+        this._onSuccess = callback;
+        return this;
+    }
+
+    fail(callback) {
+        this._onFailed = callback;
+        return this;
+    }
+
+    header(obj, rewrite) {
+        if (rewrite) {
+            this._header = obj;
+        } else {
+            for (let key in obj) {
+                this._header[key] = obj[key];
+            }
+        }
+        return this;
+    }
+
+    params(obj) {
+        this._params = obj;
+        return this;
+    }
+
+    data(obj) {
+        this._data = obj;
+        return this;
+    }
+
+    url(str) {
+        this._url = str;
+        return this;
+    }
+
+    responseDeserialize(func) {
+        this._deserialize = func;
+        return this;
+    }
+
+    static getHttpRequest() {
+        let request = new efunRequest();
+        // if (UserDataStorage.getToken()) {
+        //     request.header({
+        //         'Authentication': UserDataStorage.getToken()
+        //     });
+        // }
+        request.responseDeserialize(function (res, req) {
+            function callFailed(data) {
+                if (req._onFailed) {
+                    req._onFailed(data);
+                }
+            }
+
+            function callSuccess(data) {
+                if (req._onSuccess) {
+                    req._onSuccess(data);
+                }
+            }
+
+            let rObj = null;
+            try {
+                rObj = JSON.parse(res);
+            } catch (e) {
+                callFailed(e);
+                return;
+            }
+            if (req.xmlHTTPRequest.status != 200) {
+                callFailed(rObj);
+                return;
+            }
+            if (!rObj.success) {
+                callFailed(rObj);
+                return;
+            }
+            callSuccess(rObj);
+        });
+        return request;
+    }
+}
+
+export default efunRequest;