mirror of
https://github.com/timepill/timepill-app.git
synced 2025-04-30 09:59:31 +08:00
1. 用户详情页用户信息
2. 用户详情页今天日记列表
This commit is contained in:
parent
bb0a75e15f
commit
84ce205ee6
13 changed files with 204 additions and 50 deletions
|
@ -12,31 +12,53 @@ import DiaryActionIcon from './diaryActionIcon';
|
||||||
|
|
||||||
export default class DiaryBrief extends Component {
|
export default class DiaryBrief extends Component {
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.diary = props.diary;
|
||||||
|
this.editable = props.editable || false;
|
||||||
|
|
||||||
|
this.showField = ['icon', 'userName', 'subject', 'createdTime'];
|
||||||
|
if(props.showField && props.showField.length > 0) {
|
||||||
|
this.showField = props.showField
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
show(field) {
|
||||||
|
return this.showField.indexOf(field) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let diary = this.props.diary;
|
let diary = this.diary;
|
||||||
|
if(!diary) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
let user = diary.user;
|
let user = diary.user;
|
||||||
let editable = this.props.editable;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={[localStyle.box, this.props.style]}>
|
<View style={[localStyle.box, this.props.style]}>
|
||||||
{(user && user.iconUrl)
|
{(user && user.iconUrl && this.show('icon'))
|
||||||
? <UserIcon iconUrl={user.iconUrl}></UserIcon> : null}
|
? <UserIcon iconUrl={user.iconUrl}></UserIcon> : null}
|
||||||
|
|
||||||
<View style={localStyle.body}>
|
<View style={localStyle.body}>
|
||||||
<View style={localStyle.title}>
|
<View style={localStyle.title}>
|
||||||
{(user && user.name)
|
{(user && user.name && this.show('userName'))
|
||||||
? ( <Text style={localStyle.titleName} numberOfLines={1}>
|
? ( <Text style={localStyle.titleName} numberOfLines={1}>
|
||||||
{user.name}
|
{user.name}
|
||||||
</Text>
|
</Text>
|
||||||
) : null}
|
) : null}
|
||||||
{(user && user.name)
|
{(diary.notebook_subject && this.show('subject'))
|
||||||
? ( <Text style={[localStyle.titleText, {flex: 1}]} numberOfLines={1}>
|
? ( <Text style={[localStyle.titleText, {flex: 1}]} numberOfLines={1}>
|
||||||
《{diary.notebook_subject}》
|
《{diary.notebook_subject}》
|
||||||
</Text>
|
</Text>
|
||||||
) : null}
|
) : null}
|
||||||
<Text style={localStyle.titleText}>
|
{(diary.created && this.show('createdTime'))
|
||||||
{moment(diary.created).format('H:mm')}
|
? ( <Text style={localStyle.titleText}>
|
||||||
</Text>
|
{moment(diary.created).format('H:mm')}
|
||||||
|
</Text>
|
||||||
|
) : null}
|
||||||
|
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<Text style={localStyle.content} numberOfLines={5}>
|
<Text style={localStyle.content} numberOfLines={5}>
|
||||||
|
@ -53,7 +75,7 @@ export default class DiaryBrief extends Component {
|
||||||
}
|
}
|
||||||
<View style={{flex: 1}} />
|
<View style={{flex: 1}} />
|
||||||
{
|
{
|
||||||
editable
|
this.editable
|
||||||
? <DiaryActionIcon></DiaryActionIcon>
|
? <DiaryActionIcon></DiaryActionIcon>
|
||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,6 +66,7 @@ export default class DiaryList extends Component {
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
diaries: result.list ? result.list : [],
|
diaries: result.list ? result.list : [],
|
||||||
|
hasMore: result.more,
|
||||||
refreshFailed: false
|
refreshFailed: false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -130,7 +131,9 @@ export default class DiaryList extends Component {
|
||||||
renderItem={({item}) => {
|
renderItem={({item}) => {
|
||||||
return (
|
return (
|
||||||
<Touchable onPress={() => this.props.onDiaryPress(item)}>
|
<Touchable onPress={() => this.props.onDiaryPress(item)}>
|
||||||
<DiaryBrief diary={item}></DiaryBrief>
|
<DiaryBrief diary={item}
|
||||||
|
showField={this.props.showField}>
|
||||||
|
</DiaryBrief>
|
||||||
</Touchable>
|
</Touchable>
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -53,6 +53,7 @@ export default class FollowUserList extends Component {
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
users: result.list ? result.list : [],
|
users: result.list ? result.list : [],
|
||||||
|
hasMore: result.more,
|
||||||
refreshFailed: false
|
refreshFailed: false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ export default class Loading extends Component {
|
||||||
);
|
);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return <View />
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,6 +97,7 @@ export default class NotebookDiaryList extends Component {
|
||||||
let diaries = this.formatDiaries(result.list);
|
let diaries = this.formatDiaries(result.list);
|
||||||
this.setState({
|
this.setState({
|
||||||
diaries,
|
diaries,
|
||||||
|
hasMore: result.more,
|
||||||
refreshFailed: false
|
refreshFailed: false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -159,7 +160,9 @@ export default class NotebookDiaryList extends Component {
|
||||||
|
|
||||||
renderItem={(rowData) => {
|
renderItem={(rowData) => {
|
||||||
return (<Touchable onPress={() => {}}>
|
return (<Touchable onPress={() => {}}>
|
||||||
<DiaryBrief diary={rowData.item}></DiaryBrief>
|
<DiaryBrief diary={rowData.item}
|
||||||
|
showField={['createdTime']}>
|
||||||
|
</DiaryBrief>
|
||||||
</Touchable>);
|
</Touchable>);
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
|
|
@ -60,8 +60,6 @@ export default class NotebookList extends Component {
|
||||||
this.setState({refreshing: true});
|
this.setState({refreshing: true});
|
||||||
Api.getSelfNotebooks()
|
Api.getSelfNotebooks()
|
||||||
.then(notebooks => {
|
.then(notebooks => {
|
||||||
console.log('get notebooks:', notebooks);
|
|
||||||
|
|
||||||
let groups = this.createGroup(notebooks, this.itemsPerRow);
|
let groups = this.createGroup(notebooks, this.itemsPerRow);
|
||||||
this.setState({
|
this.setState({
|
||||||
notebooks: groups
|
notebooks: groups
|
||||||
|
|
|
@ -11,8 +11,10 @@ export default class UserIcon extends Component {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Avatar small rounded
|
<Avatar rounded
|
||||||
containerStyle={localStyle.container}
|
containerStyle={localStyle.container}
|
||||||
|
width={this.props.width || 40}
|
||||||
|
height={this.props.height || 40}
|
||||||
source={{uri: this.props.iconUrl}}
|
source={{uri: this.props.iconUrl}}
|
||||||
onPress={this.props.onPress ? this.props.onPress : this._defaultOnPress.bind(this)}
|
onPress={this.props.onPress ? this.props.onPress : this._defaultOnPress.bind(this)}
|
||||||
activeOpacity={0.7}
|
activeOpacity={0.7}
|
||||||
|
|
105
src/component/userIntro.js
Normal file
105
src/component/userIntro.js
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
import React, {Component} from 'react';
|
||||||
|
import {StyleSheet, Text, View, ScrollView, InteractionManager} from 'react-native';
|
||||||
|
import {Avatar} from "react-native-elements";
|
||||||
|
import moment from 'moment';
|
||||||
|
|
||||||
|
import Color from '../style/color';
|
||||||
|
import Api from '../util/api';
|
||||||
|
import Msg from '../util/msg';
|
||||||
|
|
||||||
|
import UserIcon from './userIcon'
|
||||||
|
import Loading from './loading'
|
||||||
|
|
||||||
|
|
||||||
|
export default class UserIntro extends Component {
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
user: props.user,
|
||||||
|
isLoading: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
InteractionManager.runAfterInteractions(() => {
|
||||||
|
this.loadUser();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
loadUser() {
|
||||||
|
Api.getSelfInfoByStore()
|
||||||
|
.then(user => {
|
||||||
|
this.setState({
|
||||||
|
user: user
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
Msg.showMsg('用户信息加载失败');
|
||||||
|
})
|
||||||
|
.done(() => {
|
||||||
|
this.setState({
|
||||||
|
isLoading: false
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const user = this.state.user;
|
||||||
|
|
||||||
|
return this.state.isLoading
|
||||||
|
? <Loading visible={this.state.isLoading}></Loading>
|
||||||
|
: (
|
||||||
|
<ScrollView style={localStyle.container} automaticallyAdjustContentInsets={false}>
|
||||||
|
<View style={localStyle.userIcon}>
|
||||||
|
<UserIcon width={90} height={90} iconUrl={user.coverUrl} />
|
||||||
|
<Text style={localStyle.userTitle}>{user.name}</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{
|
||||||
|
user.intro && user.intro.length > 0
|
||||||
|
? (<Text style={localStyle.introText}>{user.intro}</Text>) : null
|
||||||
|
}
|
||||||
|
|
||||||
|
<Text style={localStyle.joinTime}>
|
||||||
|
{moment(user.created).format('YYYY年M月D日')}加入胶囊
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
</ScrollView>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const localStyle = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: 'white'
|
||||||
|
},
|
||||||
|
userIcon: {
|
||||||
|
height: 230,
|
||||||
|
backgroundColor: 'white',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center'
|
||||||
|
},
|
||||||
|
userTitle: {
|
||||||
|
fontSize: 22,
|
||||||
|
marginTop: 30,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
color: '#000'
|
||||||
|
},
|
||||||
|
introText: {
|
||||||
|
padding: 15,
|
||||||
|
color: Color.text,
|
||||||
|
lineHeight: 24,
|
||||||
|
textAlign: 'center'
|
||||||
|
},
|
||||||
|
joinTime: {
|
||||||
|
marginTop: 30,
|
||||||
|
marginBottom:60,
|
||||||
|
padding: 15,
|
||||||
|
color: Color.inactiveText,
|
||||||
|
lineHeight: 20,
|
||||||
|
textAlign: 'center'
|
||||||
|
}
|
||||||
|
});
|
24
src/dataLoader/userDiaryData.js
Normal file
24
src/dataLoader/userDiaryData.js
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
import Api from '../util/api'
|
||||||
|
|
||||||
|
|
||||||
|
const PAGE_SIZE = 21;
|
||||||
|
|
||||||
|
export default class UserDiaryData {
|
||||||
|
|
||||||
|
constructor(userId = 0) {
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
async refresh() {
|
||||||
|
if(this.userId === 0) {
|
||||||
|
let user = await Api.getSelfInfoByStore();
|
||||||
|
this.userId = user.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
let list = await Api.getUserTodayDiaries(this.userId);
|
||||||
|
return {
|
||||||
|
list,
|
||||||
|
more: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,7 +6,7 @@ import Api from '../util/api'
|
||||||
import {Icon} from '../style/icon'
|
import {Icon} from '../style/icon'
|
||||||
|
|
||||||
import DiaryList from '../component/diary/diaryList'
|
import DiaryList from '../component/diary/diaryList'
|
||||||
import FollowListData from '../dataLoader/followDiaryData';
|
import FollowDiaryData from '../dataLoader/followDiaryData';
|
||||||
|
|
||||||
|
|
||||||
export default class FollowPage extends Component {
|
export default class FollowPage extends Component {
|
||||||
|
@ -15,7 +15,7 @@ export default class FollowPage extends Component {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
Navigation.events().bindComponent(this);
|
Navigation.events().bindComponent(this);
|
||||||
this.dataSource = new FollowListData();
|
this.dataSource = new FollowDiaryData();
|
||||||
}
|
}
|
||||||
|
|
||||||
static options(passProps) {
|
static options(passProps) {
|
||||||
|
|
|
@ -5,14 +5,14 @@ import {Navigation} from 'react-native-navigation';
|
||||||
import Api from '../util/api';
|
import Api from '../util/api';
|
||||||
|
|
||||||
import DiaryList from '../component/diary/diaryList'
|
import DiaryList from '../component/diary/diaryList'
|
||||||
import HomeListData from '../dataLoader/homeDiaryData';
|
import HomeDiaryData from '../dataLoader/homeDiaryData';
|
||||||
|
|
||||||
|
|
||||||
export default class HomePage extends Component {
|
export default class HomePage extends Component {
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.dataSource = new HomeListData();
|
this.dataSource = new HomeDiaryData();
|
||||||
}
|
}
|
||||||
|
|
||||||
_onDiaryPress(diary) {
|
_onDiaryPress(diary) {
|
||||||
|
@ -28,20 +28,11 @@ export default class HomePage extends Component {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
renderHeader() {
|
|
||||||
return (
|
|
||||||
<View style={localStyle.header}>
|
|
||||||
<Text style={localStyle.title}>胶囊日记</Text>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<View style={localStyle.wrap}>
|
<View style={localStyle.wrap}>
|
||||||
<DiaryList ref={(r) => this.list = r}
|
<DiaryList ref={(r) => this.list = r}
|
||||||
dataSource={this.dataSource}
|
dataSource={this.dataSource}
|
||||||
header={this.renderHeader.bind(this)}
|
|
||||||
onDiaryPress={this._onDiaryPress.bind(this)}
|
onDiaryPress={this._onDiaryPress.bind(this)}
|
||||||
|
|
||||||
navigator={this.props.navigator}
|
navigator={this.props.navigator}
|
||||||
|
@ -56,15 +47,5 @@ const localStyle = StyleSheet.create({
|
||||||
wrap: {
|
wrap: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
backgroundColor: '#fff'
|
backgroundColor: '#fff'
|
||||||
},
|
|
||||||
header: {
|
|
||||||
paddingLeft: 20,
|
|
||||||
paddingTop: 20,
|
|
||||||
flexDirection: "row"
|
|
||||||
},
|
|
||||||
title: {
|
|
||||||
flex: 1,
|
|
||||||
fontSize: 30,
|
|
||||||
color: '#000'
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -11,17 +11,23 @@ import {Navigation} from 'react-native-navigation';
|
||||||
import Api from '../util/api';
|
import Api from '../util/api';
|
||||||
import Color from '../style/color';
|
import Color from '../style/color';
|
||||||
|
|
||||||
import NotebookList from '../component/notebook/notebookList'
|
import UserIntro from '../component/userIntro';
|
||||||
|
import UserDiaryData from '../dataLoader/userDiaryData';
|
||||||
|
import DiaryList from '../component/diary/diaryList';
|
||||||
|
import NotebookList from '../component/notebook/notebookList';
|
||||||
|
|
||||||
|
|
||||||
export default class UserPage extends Component {
|
export default class UserPage extends Component {
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
|
this.dataSource = new UserDiaryData();
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
index: 0,
|
index: 0,
|
||||||
routes: [
|
routes: [
|
||||||
{ key: 'userInfo', title: '简介' },
|
{ key: 'userIntro', title: '简介' },
|
||||||
{ key: 'diary', title: '日记' },
|
{ key: 'diary', title: '日记' },
|
||||||
{ key: 'notebook', title: '日记本' }
|
{ key: 'notebook', title: '日记本' }
|
||||||
]
|
]
|
||||||
|
@ -68,8 +74,14 @@ export default class UserPage extends Component {
|
||||||
};
|
};
|
||||||
|
|
||||||
_renderScene = SceneMap({
|
_renderScene = SceneMap({
|
||||||
userInfo: () => <View style={localStyle.container}><Text style={localStyle.welcome}>user info !</Text></View>,
|
userIntro: () => <UserIntro
|
||||||
diary: () => <View style={localStyle.container}><Text style={localStyle.welcome}>diary !</Text></View>,
|
/>,
|
||||||
|
diary: () => <DiaryList
|
||||||
|
dataSource={this.dataSource}
|
||||||
|
onDiaryPress={() => {}}
|
||||||
|
|
||||||
|
navigator={this.props.navigator}
|
||||||
|
/>,
|
||||||
notebook: () => <NotebookList
|
notebook: () => <NotebookList
|
||||||
onNotebookPress={this._onNotebookPress.bind(this)}
|
onNotebookPress={this._onNotebookPress.bind(this)}
|
||||||
navigator={this.props.navigator}
|
navigator={this.props.navigator}
|
||||||
|
@ -100,14 +112,6 @@ export default class UserPage extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
const localStyle = StyleSheet.create({
|
const localStyle = StyleSheet.create({
|
||||||
|
|
||||||
welcome: {
|
|
||||||
fontSize: 20,
|
|
||||||
textAlign: 'center',
|
|
||||||
marginTop: 40
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
container: {
|
container: {
|
||||||
flex: 1
|
flex: 1
|
||||||
},
|
},
|
||||||
|
|
|
@ -25,6 +25,7 @@ async function login(username, password) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const userInfo = await getSelfInfo();
|
const userInfo = await getSelfInfo();
|
||||||
|
|
||||||
await TokenManager.setUserInfo(userInfo);
|
await TokenManager.setUserInfo(userInfo);
|
||||||
await TokenManager.setLoginPassword('');
|
await TokenManager.setLoginPassword('');
|
||||||
|
|
||||||
|
@ -90,6 +91,14 @@ async function getNotebookDiaries(id, page, page_size) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getSelfInfoByStore() {
|
||||||
|
return await TokenManager.getUserInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getUserTodayDiaries(userId) {
|
||||||
|
return call('GET', '/users/' + userId + '/diaries/')
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async function call(method, api, body, _timeout = 10000) {
|
async function call(method, api, body, _timeout = 10000) {
|
||||||
let token = await TokenManager.getUserToken();
|
let token = await TokenManager.getUserToken();
|
||||||
|
@ -177,10 +186,12 @@ export default {
|
||||||
IS_IPHONEX,
|
IS_IPHONEX,
|
||||||
|
|
||||||
login,
|
login,
|
||||||
|
getSelfInfoByStore,
|
||||||
|
|
||||||
getTodayDiaries,
|
getTodayDiaries,
|
||||||
getFollowDiaries,
|
getFollowDiaries,
|
||||||
getNotebookDiaries,
|
getNotebookDiaries,
|
||||||
|
getUserTodayDiaries,
|
||||||
|
|
||||||
getDiaryComments,
|
getDiaryComments,
|
||||||
getSelfNotebooks,
|
getSelfNotebooks,
|
||||||
|
|
Loading…
Reference in a new issue