Authored by 于良

跳转规则和bug fix review by 阿瑟

@@ -28,7 +28,7 @@ export default class SlicedImage extends React.Component { @@ -28,7 +28,7 @@ export default class SlicedImage extends React.Component {
28 width = PixelRatio.getPixelSizeForLayoutSize(width); 28 width = PixelRatio.getPixelSizeForLayoutSize(width);
29 height = PixelRatio.getPixelSizeForLayoutSize(height); 29 height = PixelRatio.getPixelSizeForLayoutSize(height);
30 let newSrc = src; 30 let newSrc = src;
31 - if (src.indexOf('imageView2') === -1) { 31 + if (src.indexOf('imageView') === -1) {
32 newSrc = src + '?imageView2/' + this.mode + '/w/' + width + '/h/' + height; 32 newSrc = src + '?imageView2/' + this.mode + '/w/' + width + '/h/' + height;
33 } else { 33 } else {
34 newSrc = src.replace('{mode}', this.mode) 34 newSrc = src.replace('{mode}', this.mode)
@@ -317,8 +317,7 @@ export default function community(platform) { @@ -317,8 +317,7 @@ export default function community(platform) {
317 }, 317 },
318 318
319 homeOnRight(state) { 319 homeOnRight(state) {
320 - Actions.SubjectPost();  
321 - // state.dispatch(startEditPost(state.getPostingState())); 320 + state.dispatch(startEditPost(state.getPostingState()));
322 }, 321 },
323 /* 322 /*
324 * 自定义导航push动画 323 * 自定义导航push动画
@@ -307,7 +307,7 @@ export default class Home extends React.Component { @@ -307,7 +307,7 @@ export default class Home extends React.Component {
307 isVisible={isSyncFetching} 307 isVisible={isSyncFetching}
308 /> 308 />
309 <SuperMan 309 <SuperMan
310 - fly={styles.fly} 310 + uid={user.uid}
311 avatar={user.avatar} 311 avatar={user.avatar}
312 msgCount={user.msgCount} 312 msgCount={user.msgCount}
313 onSaveingTheWorld={this.props.onSaveingTheWorld} 313 onSaveingTheWorld={this.props.onSaveingTheWorld}
@@ -355,9 +355,4 @@ let styles = StyleSheet.create({ @@ -355,9 +355,4 @@ let styles = StyleSheet.create({
355 height: 0.5, 355 height: 0.5,
356 backgroundColor: '#e0e0e0', 356 backgroundColor: '#e0e0e0',
357 }, 357 },
358 - fly: {  
359 - position: 'absolute',  
360 - right: 20,  
361 - bottom: 20,  
362 - },  
363 }); 358 });
@@ -51,6 +51,7 @@ let styles = StyleSheet.create({ @@ -51,6 +51,7 @@ let styles = StyleSheet.create({
51 height: 18, 51 height: 18,
52 }, 52 },
53 number: { 53 number: {
  54 + color: '#b0b0b0',
54 fontSize: 14, 55 fontSize: 14,
55 marginLeft: 5, 56 marginLeft: 5,
56 }, 57 },
@@ -17,6 +17,7 @@ const { @@ -17,6 +17,7 @@ const {
17 export default class SuperMan extends React.Component { 17 export default class SuperMan extends React.Component {
18 18
19 static propTypes = { 19 static propTypes = {
  20 + uid: React.PropTypes.number,
20 avatar: React.PropTypes.string, 21 avatar: React.PropTypes.string,
21 msgCount: React.PropTypes.string, 22 msgCount: React.PropTypes.string,
22 onSaveingTheWorld: React.PropTypes.func, 23 onSaveingTheWorld: React.PropTypes.func,
@@ -28,8 +29,18 @@ export default class SuperMan extends React.Component { @@ -28,8 +29,18 @@ export default class SuperMan extends React.Component {
28 29
29 } 30 }
30 31
  32 + renderText() {
  33 + if (this.props.uid == 0 ) {
  34 + return (
  35 + <Text style={styles.loginText}>请登录</Text>
  36 + );
  37 + } else {
  38 + return null;
  39 + }
  40 + }
  41 +
31 renderMsgCount() { 42 renderMsgCount() {
32 - if (parseInt(this.props.msgCount) !== 0) { 43 + if (this.props.uid > 0 && parseInt(this.props.msgCount) !== 0) {
33 return ( 44 return (
34 <View style={styles.textContainer}> 45 <View style={styles.textContainer}>
35 <Text style={styles.text}>{this.props.msgCount}</Text> 46 <Text style={styles.text}>{this.props.msgCount}</Text>
@@ -41,15 +52,17 @@ export default class SuperMan extends React.Component { @@ -41,15 +52,17 @@ export default class SuperMan extends React.Component {
41 } 52 }
42 53
43 render() { 54 render() {
44 - let avtatStyle = this.props.avatar ? styles.avatarContainer : null; 55 + let avatarContainerStyle = this.props.uid > 0 ? styles.avatarContainer : null;
  56 + let avatarStyle = this.props.uid > 0 ? styles.avatarBorder : null;
45 return ( 57 return (
46 <View style={[styles.container, this.props.fly]}> 58 <View style={[styles.container, this.props.fly]}>
47 <TouchableOpacity activeOpacity={0.8} onPress={() => { 59 <TouchableOpacity activeOpacity={0.8} onPress={() => {
48 this.props.onSaveingTheWorld && this.props.onSaveingTheWorld(); 60 this.props.onSaveingTheWorld && this.props.onSaveingTheWorld();
49 }}> 61 }}>
50 - <View style={avtatStyle}>  
51 - <SlicedImage style={styles.avatar} source={{uri: this.props.avatar}} resizeMode={'cover'} defaultSource={require('../../images/home/superman.png')}/> 62 + <View style={avatarContainerStyle}>
  63 + <SlicedImage style={[styles.avatar, avatarStyle]} source={{uri: this.props.avatar}} resizeMode={'cover'} defaultSource={require('../../images/home/superman.png')}/>
52 </View> 64 </View>
  65 + {this.renderText()}
53 {this.renderMsgCount()} 66 {this.renderMsgCount()}
54 </TouchableOpacity> 67 </TouchableOpacity>
55 </View> 68 </View>
@@ -59,7 +72,10 @@ export default class SuperMan extends React.Component { @@ -59,7 +72,10 @@ export default class SuperMan extends React.Component {
59 72
60 let styles = StyleSheet.create({ 73 let styles = StyleSheet.create({
61 container: { 74 container: {
62 - flexDirection: 'row', 75 + position: 'absolute',
  76 + right: 20,
  77 + bottom: 20,
  78 + flexDirection: 'column',
63 alignItems: 'center', 79 alignItems: 'center',
64 backgroundColor: 'transparent', 80 backgroundColor: 'transparent',
65 width: 45, 81 width: 45,
@@ -79,12 +95,15 @@ let styles = StyleSheet.create({ @@ -79,12 +95,15 @@ let styles = StyleSheet.create({
79 width: 44, 95 width: 44,
80 height: 44, 96 height: 44,
81 borderRadius: 22, 97 borderRadius: 22,
  98 + },
  99 + avatarBorder: {
82 borderColor: 'white', 100 borderColor: 'white',
83 borderWidth: 1, 101 borderWidth: 1,
84 - // shadowColor: 'red',  
85 - // shadowOpacity: 1,  
86 - // // shadowRadius: 20,  
87 - // shadowOffset: {width: 0, height: 0}, 102 + },
  103 + loginText: {
  104 + marginTop: 2,
  105 + fontSize: 10,
  106 + textAlign: 'center',
88 }, 107 },
89 textContainer: { 108 textContainer: {
90 position: 'absolute', 109 position: 'absolute',
@@ -290,7 +290,7 @@ export default class Section extends React.Component { @@ -290,7 +290,7 @@ export default class Section extends React.Component {
290 }} 290 }}
291 /> 291 />
292 <SuperMan 292 <SuperMan
293 - fly={styles.fly} 293 + uid={user.uid}
294 avatar={user.avatar} 294 avatar={user.avatar}
295 msgCount={user.msgCount} 295 msgCount={user.msgCount}
296 onSaveingTheWorld={this.props.onSaveingTheWorld} 296 onSaveingTheWorld={this.props.onSaveingTheWorld}
@@ -22,7 +22,8 @@ export default class SectionHeader extends React.Component { @@ -22,7 +22,8 @@ export default class SectionHeader extends React.Component {
22 static propTypes = { 22 static propTypes = {
23 data: ImmutablePropTypes.contains({ 23 data: ImmutablePropTypes.contains({
24 uri: React.PropTypes.string.isRequired, 24 uri: React.PropTypes.string.isRequired,
25 - title: React.PropTypes.string.isRequired, 25 + title: React.PropTypes.string,
  26 + desc: React.PropTypes.string.isRequired,
26 post: React.PropTypes.string.isRequired, 27 post: React.PropTypes.string.isRequired,
27 comment: React.PropTypes.string.isRequired, 28 comment: React.PropTypes.string.isRequired,
28 like: React.PropTypes.string.isRequired, 29 like: React.PropTypes.string.isRequired,
@@ -35,11 +36,11 @@ export default class SectionHeader extends React.Component { @@ -35,11 +36,11 @@ export default class SectionHeader extends React.Component {
35 } 36 }
36 37
37 render() { 38 render() {
38 - let {uri, title, post, comment, like} = this.props.data.toJS(); 39 + let {uri, desc, post, comment, like} = this.props.data.toJS();
39 return ( 40 return (
40 <Image style={[styles.container, this.props.style]} source={{uri}} resizeMode={'cover'}> 41 <Image style={[styles.container, this.props.style]} source={{uri}} resizeMode={'cover'}>
41 - <Text style={styles.title}>{title}</Text>  
42 - <View style={styles.desc}> 42 + <Text style={styles.desc}>{desc}</Text>
  43 + <View style={styles.stats}>
43 <Text style={[styles.content, {flex: 0.3}]} numberOfLines={1}>{post}</Text> 44 <Text style={[styles.content, {flex: 0.3}]} numberOfLines={1}>{post}</Text>
44 <Text style={styles.content}>|</Text> 45 <Text style={styles.content}>|</Text>
45 <Text style={[styles.content, {flex: 0.3}]} numberOfLines={1}>{comment}</Text> 46 <Text style={[styles.content, {flex: 0.3}]} numberOfLines={1}>{comment}</Text>
@@ -58,7 +59,7 @@ let styles = StyleSheet.create({ @@ -58,7 +59,7 @@ let styles = StyleSheet.create({
58 // alignItems: 'center', 59 // alignItems: 'center',
59 backgroundColor: '#b0b0b0', 60 backgroundColor: '#b0b0b0',
60 }, 61 },
61 - title: { 62 + desc: {
62 color: 'white', 63 color: 'white',
63 // fontFamily: 'SourceHanSansCN Normal', 64 // fontFamily: 'SourceHanSansCN Normal',
64 fontSize: 24, 65 fontSize: 24,
@@ -66,7 +67,7 @@ let styles = StyleSheet.create({ @@ -66,7 +67,7 @@ let styles = StyleSheet.create({
66 textAlign: 'center', 67 textAlign: 'center',
67 backgroundColor: 'transparent', 68 backgroundColor: 'transparent',
68 }, 69 },
69 - desc: { 70 + stats: {
70 flex: 1, 71 flex: 1,
71 flexDirection: 'row', 72 flexDirection: 'row',
72 justifyContent: 'space-between', 73 justifyContent: 'space-between',
@@ -5,6 +5,7 @@ export default keyMirror({ @@ -5,6 +5,7 @@ export default keyMirror({
5 SET_PLATFORM: null, 5 SET_PLATFORM: null,
6 SET_CONTAINER: null, 6 SET_CONTAINER: null,
7 SET_CHANNEL: null, 7 SET_CHANNEL: null,
  8 + GO_ACTION: null,
8 9
9 SET_UID: null, 10 SET_UID: null,
10 SYNC_USER_REQUEST: null, 11 SYNC_USER_REQUEST: null,
@@ -51,7 +52,7 @@ export default keyMirror({ @@ -51,7 +52,7 @@ export default keyMirror({
51 52
52 /*用户中心*/ 53 /*用户中心*/
53 USER_BACKGROUND_TAP: null, 54 USER_BACKGROUND_TAP: null,
54 - USER_AVATAR_TAP:null, 55 + USER_AVATAR_TAP: null,
55 56
56 USER_POSTS_REQUEST: null, //我的帖子 57 USER_POSTS_REQUEST: null, //我的帖子
57 USER_POSTS_SUCCESS: null, 58 USER_POSTS_SUCCESS: null,
@@ -117,11 +117,12 @@ class HomeContainer extends React.Component { @@ -117,11 +117,12 @@ class HomeContainer extends React.Component {
117 } 117 }
118 118
119 _onPressBanner(url) { 119 _onPressBanner(url) {
120 - ReactNative.NativeModules.YH_CommunityHelper.jumpWithUrl(url, {}); 120 + this.props.actions.goAction(url);
121 } 121 }
122 122
123 _onPressNotice(url) { 123 _onPressNotice(url) {
124 - ReactNative.NativeModules.YH_CommunityHelper.jumpWithUrl(url, {}); 124 + // url = `http://feature.yoho.cn/0714/0714ITEMBOY/index.html?title=男生分会场&share_id=814&openby:yohobuy={"action":"go.comm.h5","params":{"product_skn":51285070,"forumid":10003,"param":{"share_id":"814","title":"男生分会场"},"share":"/operations/api/v5/webshare/getShare","shareparam":{"share_id":"814"},"title":"男生分会场","url":"http://feature.yoho.cn/0714/0714ITEMBOY/index.html"}}`;
  125 + this.props.actions.goAction(url);
125 } 126 }
126 127
127 _onPressSection(section) { 128 _onPressSection(section) {
@@ -13,6 +13,7 @@ import Section from '../components/section/Section'; @@ -13,6 +13,7 @@ import Section from '../components/section/Section';
13 import * as sectionActions from '../reducers/section/sectionActions'; 13 import * as sectionActions from '../reducers/section/sectionActions';
14 import * as postingActions from '../reducers/posting/postingActions'; 14 import * as postingActions from '../reducers/posting/postingActions';
15 import * as homeActions from '../reducers/home/homeActions'; 15 import * as homeActions from '../reducers/home/homeActions';
  16 +import * as appActions from '../reducers/app/appActions';
16 import {Actions} from 'react-native-router-flux'; 17 import {Actions} from 'react-native-router-flux';
17 import {shouldShowTabBar, shouldHideTabBar} from '../utils/tabBar'; 18 import {shouldShowTabBar, shouldHideTabBar} from '../utils/tabBar';
18 19
@@ -32,7 +33,8 @@ const { @@ -32,7 +33,8 @@ const {
32 const actions = [ 33 const actions = [
33 sectionActions, 34 sectionActions,
34 postingActions, 35 postingActions,
35 - homeActions 36 + homeActions,
  37 + appActions
36 ]; 38 ];
37 39
38 /** 40 /**
@@ -98,12 +100,11 @@ class SectionContainer extends React.Component { @@ -98,12 +100,11 @@ class SectionContainer extends React.Component {
98 } 100 }
99 101
100 _onPressBanner(url) { 102 _onPressBanner(url) {
101 - console.log('banner');  
102 - 103 + this.props.actions.goAction(url);
103 } 104 }
104 105
105 _onPressNotice(url) { 106 _onPressNotice(url) {
106 - console.log('notice'); 107 + this.props.actions.goAction(url);
107 } 108 }
108 109
109 _onPressPost(id) { 110 _onPressPost(id) {
@@ -6,13 +6,17 @@ @@ -6,13 +6,17 @@
6 */ 6 */
7 'use strict'; 7 'use strict';
8 8
  9 +import ReactNative from 'react-native';
9 import {Actions} from 'react-native-router-flux'; 10 import {Actions} from 'react-native-router-flux';
10 import AppService from '../../services/AppService'; 11 import AppService from '../../services/AppService';
  12 +import RouterService from '../../services/RouterService';
  13 +import {goToSection, goToPost} from '../home/homeActions';
11 14
12 const { 15 const {
13 SET_PLATFORM, 16 SET_PLATFORM,
14 SET_CONTAINER, 17 SET_CONTAINER,
15 SET_CHANNEL, 18 SET_CHANNEL,
  19 + GO_ACTION,
16 } = require('../../constants/actionTypes').default; 20 } = require('../../constants/actionTypes').default;
17 21
18 export function setPlatform(platform) { 22 export function setPlatform(platform) {
@@ -35,3 +39,46 @@ export function setChannel(channel) { @@ -35,3 +39,46 @@ export function setChannel(channel) {
35 payload: channel 39 payload: channel
36 }; 40 };
37 } 41 }
  42 +
  43 +export function goAction(inputUrl) {
  44 + return (dispatch, getState) => {
  45 + return new RouterService().parseUrl(inputUrl)
  46 + .then((json) => {
  47 + let {action, params} = json;
  48 + let {param, share, shareparam, title, url} = params;
  49 +
  50 + if (action == 'go.comm.forum') {
  51 + let id = params && params.forumid ? params.forumid : 0;
  52 + let name = '';
  53 + if (id != 0) {
  54 + dispatch(goToSection({id, name}));
  55 + }
  56 +
  57 + } else if (action == 'go.comm.postdetail') {
  58 + let id = params && params.postid ? params.postid : 0;
  59 + if (id != 0) {
  60 + dispatch(goToPost(id));
  61 + }
  62 +
  63 + } else if (action == 'go.comm.h5') {
  64 + let title = params.title ? params.title : '';
  65 + let url = params.url ? params.url : '';
  66 + if (!url || url.length == 0) {
  67 + return;
  68 + }
  69 + ReactNative.NativeModules.YH_CommunityHelper.displayH5({url, title});
  70 + } else if (action == 'go.comm.productDetail') {
  71 + let productSkn = params.product_skn ? params.product_skn : '';
  72 + productSkn = productSkn + '';
  73 + let tag = params.tag ? params.tag : '';
  74 + if (!productSkn || productSkn.length == 0) {
  75 + return;
  76 + }
  77 + ReactNative.NativeModules.YH_CommunityHelper.displayProductDetail({productSkn, tag});
  78 + }
  79 + })
  80 + .catch(error => {
  81 + __DEV__ && console.log(error);
  82 + });
  83 + };
  84 +}
@@ -60,7 +60,7 @@ export function goToUserOrMe(uid) { @@ -60,7 +60,7 @@ export function goToUserOrMe(uid) {
60 } 60 }
61 61
62 export function goToPost(id) { 62 export function goToPost(id) {
63 - // Actions.Post(); 63 + Actions.SubjectPost();
64 return { 64 return {
65 type: GO_TO_POST, 65 type: GO_TO_POST,
66 payload: id, 66 payload: id,
@@ -284,6 +284,7 @@ function parseBNS(json) { @@ -284,6 +284,7 @@ function parseBNS(json) {
284 id: item.forumCode ? item.forumCode : 0, 284 id: item.forumCode ? item.forumCode : 0,
285 logo: item.forumPic ? item.forumPic : '', 285 logo: item.forumPic ? item.forumPic : '',
286 title: item.forumName ? item.forumName : '', 286 title: item.forumName ? item.forumName : '',
  287 + desc: item.forumDesc ? item.forumDesc : '',
287 post: number10KFormater(item.postsNum), 288 post: number10KFormater(item.postsNum),
288 comment: number10KFormater(item.commentsNum), 289 comment: number10KFormater(item.commentsNum),
289 like: number10KFormater(item.praiseNum), 290 like: number10KFormater(item.praiseNum),
@@ -232,6 +232,7 @@ function parseHeader(json) { @@ -232,6 +232,7 @@ function parseHeader(json) {
232 232
233 let uri = json.forumPic ? json.forumPic : ''; 233 let uri = json.forumPic ? json.forumPic : '';
234 let title = json.forumName ? json.forumName : ''; 234 let title = json.forumName ? json.forumName : '';
  235 + let desc = json.forumDesc ? json.forumDesc : '';
235 let post = number10KFormater(json.postsNum); 236 let post = number10KFormater(json.postsNum);
236 let comment = number10KFormater(json.commentsNum); 237 let comment = number10KFormater(json.commentsNum);
237 let like = number10KFormater(json.praiseNum); 238 let like = number10KFormater(json.praiseNum);
@@ -239,6 +240,7 @@ function parseHeader(json) { @@ -239,6 +240,7 @@ function parseHeader(json) {
239 let header = { 240 let header = {
240 uri, 241 uri,
241 title, 242 title,
  243 + desc,
242 post, 244 post,
243 comment, 245 comment,
244 like, 246 like,
@@ -29,6 +29,7 @@ let item = new (Record({ @@ -29,6 +29,7 @@ let item = new (Record({
29 header: new (Record({ 29 header: new (Record({
30 uri: '', 30 uri: '',
31 title: '', 31 title: '',
  32 + desc: '',
32 post: '', 33 post: '',
33 comment: '', 34 comment: '',
34 like: '', 35 like: '',
@@ -76,6 +76,7 @@ export default function sectionReducer(state = initialState, action) { @@ -76,6 +76,7 @@ export default function sectionReducer(state = initialState, action) {
76 .set('ptr', false) 76 .set('ptr', false)
77 .setIn(['header', 'uri'], header.uri) 77 .setIn(['header', 'uri'], header.uri)
78 .setIn(['header', 'title'], header.title) 78 .setIn(['header', 'title'], header.title)
  79 + .setIn(['header', 'desc'], header.desc)
79 .setIn(['header', 'post'], header.post) 80 .setIn(['header', 'post'], header.post)
80 .setIn(['header', 'comment'], header.comment) 81 .setIn(['header', 'comment'], header.comment)
81 .setIn(['header', 'like'], header.like) 82 .setIn(['header', 'like'], header.like)
@@ -13,6 +13,8 @@ import InitialState from './subjectPostInitialState'; @@ -13,6 +13,8 @@ import InitialState from './subjectPostInitialState';
13 import Immutable, {List, Record} from 'immutable'; 13 import Immutable, {List, Record} from 'immutable';
14 14
15 const { 15 const {
  16 + GO_TO_POST,
  17 +
16 SUBJECT_CONTENT_REQUEST, 18 SUBJECT_CONTENT_REQUEST,
17 SUBJECT_CONTENT_SUCCESS, 19 SUBJECT_CONTENT_SUCCESS,
18 SUBJECT_CONTENT_FAILURE, 20 SUBJECT_CONTENT_FAILURE,
@@ -34,6 +36,10 @@ export default function postingReducer(state = initialState, action) { @@ -34,6 +36,10 @@ export default function postingReducer(state = initialState, action) {
34 if (!(state instanceof InitialState)) return initialState.merge(state); 36 if (!(state instanceof InitialState)) return initialState.merge(state);
35 37
36 switch (action.type) { 38 switch (action.type) {
  39 + case GO_TO_POST: {
  40 + return state.set('id', action.payload);
  41 + }
  42 +
37 case SUBJECT_CONTENT_REQUEST: { 43 case SUBJECT_CONTENT_REQUEST: {
38 let nextState = state.set('isContentFetching', true).set('contentError', null); 44 let nextState = state.set('isContentFetching', true).set('contentError', null);
39 return nextState; 45 return nextState;
@@ -8,5 +8,35 @@ export default class RouterService { @@ -8,5 +8,35 @@ export default class RouterService {
8 this.api = new Request(); 8 this.api = new Request();
9 } 9 }
10 10
11 - 11 + parseUrl(url) {
  12 + return new Promise((resolve, reject) => {
  13 + if (!url) {
  14 + reject('Illegal url: ' + url);
  15 + }
  16 +
  17 + // url解码
  18 + url = decodeURI(url);
  19 + // 处理半角等号和全角等号
  20 + let mark = 'yohobuy=';
  21 + let markIndex = url.indexOf(mark);
  22 + if (markIndex == -1) {
  23 + mark = 'yohobuy=';
  24 + markIndex = url.indexOf(mark);
  25 + }
  26 +
  27 + if (markIndex == -1) {
  28 + reject('Can not find url rule: ' + url);
  29 + }
  30 +
  31 + let rule = url.substring(markIndex + mark.length);
  32 +
  33 + let json;
  34 + try {
  35 + json = JSON.parse(rule);
  36 + resolve(json);
  37 + } catch (e) {
  38 + reject('Parse json string fail: ' + e);
  39 + }
  40 + });
  41 + }
12 } 42 }