提交 83e90ba3 authored 作者: 吴强's avatar 吴强

在当事人界面添加了照片查看的功能

上级 697755fc
......@@ -7497,6 +7497,34 @@
"react-timer-mixin": "0.13.3"
}
},
"react-native-photo-browser": {
"version": "0.4.0",
"resolved": "http://registry.npm.taobao.org/react-native-photo-browser/download/react-native-photo-browser-0.4.0.tgz",
"integrity": "sha1-SMOJoNyOt7WEpmMBiSdsTG2IPMY=",
"requires": {
"prop-types": "15.5.10",
"react-native-progress": "3.4.0"
},
"dependencies": {
"prop-types": {
"version": "15.5.10",
"resolved": "http://registry.npm.taobao.org/prop-types/download/prop-types-15.5.10.tgz",
"integrity": "sha1-J5ffwxJhguOpXj37suiT3ddFYVQ=",
"requires": {
"fbjs": "0.8.16",
"loose-envify": "1.3.1"
}
}
}
},
"react-native-progress": {
"version": "3.4.0",
"resolved": "http://registry.npm.taobao.org/react-native-progress/download/react-native-progress-3.4.0.tgz",
"integrity": "sha1-wALm77LwuC3WiJUQ5mnEktonGKw=",
"requires": {
"prop-types": "15.6.0"
}
},
"react-native-splash-screen": {
"version": "3.0.6",
"resolved": "http://registry.npm.taobao.org/react-native-splash-screen/download/react-native-splash-screen-3.0.6.tgz",
......
......@@ -43,11 +43,12 @@
"rc-form": "^1.4.8",
"react": "^16.1.1",
"react-native": "^0.49.3",
"react-native-camera": "^0.12.0",
"react-native-background-upload": "^4.1.0",
"react-native-camera": "^0.12.0",
"react-native-code-push": "^5.1.3-beta",
"react-native-device-info": "^0.12.1",
"react-native-fetch-polyfill": "^1.1.2",
"react-native-photo-browser": "^0.4.0",
"react-native-splash-screen": "^3.0.6",
"react-native-tag-input": "0.0.18",
"react-native-vector-icons": "^4.4.2",
......
......@@ -8,13 +8,6 @@ import {
} from 'react-native';
import Icon from 'react-native-vector-icons/MaterialIcons';
import Camera from 'react-native-camera';
import { getToken } from '../utils/auth';
import { errors } from '../utils/error';
import { encrypt } from '../utils/helper';
import config from '../utils/config';
import { futch } from '../utils/polyfill';
import { userApi } from '../services/interfaces';
import { uploadResource } from '../services/resource';
const styles = StyleSheet.create({
container: {
......@@ -138,71 +131,65 @@ class CameraComponent extends React.Component {
.then((data) => { console.log(data); this.setState({ imageURI: data.path }); })
.catch(err => console.error(err));
}
uploadImage() {
let token;
getToken().then((Apptoken) => {
if (!Apptoken) {
return Promise.reject(errors.tokenMissing());
}
token = encrypt(Apptoken);
const uri = `${config.apiContextPath}/resource/${token}`;
const formData = new global.FormData();
const file = { uri: this.state.imageURI, type: 'image/jpg', name: 'tupian.jpg' };
formData.append('file', file);
console.info(formData);
futch(uri, {
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data',
},
body: formData,
}, (progressEvent) => {
const progress = progressEvent.loaded / progressEvent.total;
})
.then(request => request.responseText)// response.text())
.then((responseData) => {
const response = JSON.parse(responseData);
if (response.errorCode === 0) {
const name = 'addTags';// 添加标签
const PicUri = `${config.apiContextPath}/api/interface/user/${name}/invoke`;
console.info(PicUri);
const postjson = { uri: response.data[0], tags: ['当事人信息', '当事人信息'] };
console.info(JSON.stringify(postjson));
userApi.invokeInterface(name, postjson)
// futch(PicUri, {
// method: 'POST',
// headers: {
// 'Content-Type': 'application/json',
// },
// body: JSON.stringify(postjson),
// }, (progressEvent) => {
// console.info(progressEvent);
// })
.then(request => console.info(request));// response.text())
// 这里需要调用接口,对图片数据进行绑定,等待完善
// 页面跳转,跳转到前面的详情的页面
console.info('跳转');
this.props.navigation.navigate('DSRInfoDetail', this.props.navigation.state.params.pID);
}
})
.catch((error) => {
console.info(error);
});
});
}
// uploadImage() {
// let token;
// getToken().then((Apptoken) => {
// if (!Apptoken) {
// return Promise.reject(errors.tokenMissing());
// }
// token = encrypt(Apptoken);
// const uri = `${config.apiContextPath}/resource/${token}`;
// const formData = new global.FormData();
// const file = { uri: this.state.imageURI, type: 'image/jpg', name: 'tupian.jpg' };
//
// formData.append('file', file);
// console.info(formData);
// futch(uri, {
// method: 'POST',
// headers: {
// 'Content-Type': 'multipart/form-data',
// },
// body: formData,
// }, (progressEvent) => {
// const progress = progressEvent.loaded / progressEvent.total;
// })
// .then(request => request.responseText)// response.text())
// .then((responseData) => {
// const response = JSON.parse(responseData);
// if (response.errorCode === 0) {
// const name = 'addTags';// 添加标签
// const PicUri = `${config.apiContextPath}/api/interface/user/${name}/invoke`;
// console.info(PicUri);
// const postjson = { uri: response.data[0], tags: ['当事人信息', '当事人信息'] };
// console.info(JSON.stringify(postjson));
// userApi.invokeInterface(name, postjson)
// // futch(PicUri, {
// // method: 'POST',
// // headers: {
// // 'Content-Type': 'application/json',
// // },
// // body: JSON.stringify(postjson),
// // }, (progressEvent) => {
// // console.info(progressEvent);
// // })
// .then(request => console.info(request));// response.text())
// // 这里需要调用接口,对图片数据进行绑定,等待完善
// // 页面跳转,跳转到前面的详情的页面
// console.info('跳转');
// this.props.navigation.navigate('DSRInfoDetail', this.props.navigation.state.params.pID);
// }
// })
// .catch((error) => {
// console.info(error);
// });
// });
// }
clear() {
this.setState({ imageURI: '' });
}
uploadImage2 = () => {
console.info('输出上传');
console.info(this.state);
uploadResource(this.state.imageURI, (uploadId, arg) => console.info(arg), (uploadId, arg) => console.info(`陈宫${arg}`), (uploadId, arg) => console.info(arg))
.then(uploadId => console.log(`start task ${uploadId}`))
.catch(err => console.log(err));
}
goToUpload() {
this.props.navigation.navigate('DSRInfoTuPian', { imageURI: this.state.imageURI });
this.props.navigation.navigate('DSRInfoTuPian', { imageURI: this.state.imageURI, pID: this.props.navigation.state.params.pID, TableName: this.props.navigation.state.params.TableName });
}
render() {
......@@ -239,7 +226,7 @@ class CameraComponent extends React.Component {
/>
<View style={[styles.overlay, styles.bottomOverlay]}>
<Icon.Button name="clear" size={48} backgroundColor="transparent" onPress={this.clear} />
<Icon.Button name="done" size={48} backgroundColor="transparent" onPress={this.uploadImage2} />
<Icon.Button name="done" size={48} backgroundColor="transparent" onPress={this.goToUpload} />
</View>
</View>
);
......
import React, { Component } from 'react';
import PhotoBrowser from 'react-native-photo-browser';
export default class HomeScreen extends Component {
static navigationOptions = {
header: null,
};
// onSelectionChanged = (media, index, selected) => {
// console.info(`${media.photo} selection status: ${selected}`);
// };
// onActionButton = (media, index) => {
// if (Platform.OS === 'ios') {
// ActionSheetIOS.showShareActionSheetWithOptions(
// {
// url: media.photo,
// message: media.caption,
// },
// () => {},
// () => {},
// );
// } else {
// console.info(`handle sharing on android for ${media.photo}, index: ${index}`);
// }
// };
render() {
const {
media,
initialIndex,
displayNavArrows,
displayActionButton,
displaySelectionButtons,
startOnGrid,
enableGrid,
alwaysDisplayStatusBar,
} = this.props.navigation.state.params.example;
return (
<PhotoBrowser
onBack={this.props.navigation.pop}
mediaList={media}
initialIndex={initialIndex}
displayNavArrows={displayNavArrows}
displaySelectionButtons={displaySelectionButtons}
displayActionButton={displayActionButton}
startOnGrid={startOnGrid}
enableGrid={enableGrid}
useCircleProgress
onSelectionChanged={this.onSelectionChanged}
onActionButton={this.onActionButton}
alwaysDisplayStatusBar={alwaysDisplayStatusBar}
customTitle={(index, rowCount) => `${index} sur ${rowCount}`}
/>
);
}
}
import React, { Component } from 'react';
import {
CameraRoll,
ScrollView,
TouchableOpacity,
Text,
View,
StyleSheet,
} from 'react-native';
import { queryResourceByUsage } from '../../services/resource';
import config from '../../utils/config';
import { getToken } from '../../utils/auth';
import { errors } from '../../utils/error';
import { encrypt } from '../../utils/helper';
const EXAMPLES = [
{
title: '全部',
description: '所有分类,所有tag',
startOnGrid: true,
displayNavArrows: true,
displayActionButton: true,
},
];
// fill 'Library photos' example with local media
CameraRoll.getPhotos({
first: 30,
assetType: 'Photos',
})
.then((data) => {
const media = [];
data.edges.forEach(d =>
media.push({
photo: d.node.image.uri,
}));
EXAMPLES[0].media = media;
})
.catch(error => console.info(error));
export default class HomeScreen extends Component {
constructor(props) {
super(props);
// 获取所有tag 类型下面的照片放到Examples里面
queryResourceByUsage(this.props.navigation.state.params.usage)
.then((data) => {
const media = [];
// 请求Token
let strtoken = '';
getToken()
.then((token) => {
if (!token) {
return Promise.reject(errors.tokenMissing());
}
strtoken = encrypt(token);
data.forEach((d) => {
media.push({
photo: `${config.apiContextPath}/resource/${encodeURIComponent(strtoken)}/${encodeURIComponent(d)}`,
});
console.info(`${config.apiContextPath}/resource/${encodeURIComponent(strtoken)}/${encodeURIComponent(d)}`);
});
EXAMPLES[0].media = media;
})
.catch(error => console.info(error));
})
.catch(err => console.info(err));
}
renderExampleRow = (example) => {
const { navigate } = this.props.navigation;
const { title, description } = example;
return (
<TouchableOpacity
key={`example_${title}`}
onPress={() => {
navigate('PhotoViewDetail', {
example,
});
}}
>
<View style={styles.row}>
<Text style={styles.rowTitle}>
{title}
</Text>
<Text style={styles.rowDescription}>
{description}
</Text>
</View>
</TouchableOpacity>
);
};
render() {
return (
<ScrollView style={styles.container}>
{EXAMPLES.map(this.renderExampleRow)}
</ScrollView>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
list: {
flex: 1,
paddingTop: 54,
paddingLeft: 16,
},
row: {
flex: 1,
padding: 8,
borderBottomColor: 'rgba(0, 0, 0, 0.1)',
borderBottomWidth: 1,
},
rowTitle: {
fontSize: 14,
},
rowDescription: {
fontSize: 12,
},
});
......@@ -4,19 +4,13 @@ import {
StyleSheet,
Text,
TouchableOpacity,
Dimensions,
Image,
Platform,
ScrollView,
} from 'react-native';
import TagInput from 'react-native-tag-input';
import { InputItem } from 'antd-mobile';
import { futch } from '../utils/polyfill';
import { getToken } from '../utils/auth';
import { encrypt } from '../utils/helper';
import config from '../utils/config';
import { userApi } from '../services/interfaces';
import { errors } from '../utils/error';
import { createOperations, editResource, uploadResource } from '../services/resource';
const styles = StyleSheet.create({
container: {
......@@ -27,16 +21,13 @@ const styles = StyleSheet.create({
backgroundColor: 'white',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-around',
},
text_right_title: {
color: '#000',
position: 'absolute',
right: 16,
},
text_left_title: {
color: '#000',
position: 'absolute',
left: 16,
},
text_title: {
color: '#000',
......@@ -58,14 +49,12 @@ const inputProps = {
};
class UploadPageComponent extends PureComponent {
constructor(props) {
console.info('未过滤之前');
console.info(props);
super(props);
console.info('过滤之后');
console.info(props);
const { imageURI } = this.props.navigation.state.params;
const { imageURI, tableName, pID } = this.props.navigation.state.params;
this.state = {
imageURI,
tableName,
pID,
tags: ['身份证', '红本', '绿本'],
text: '',
imageName: '',
......@@ -93,75 +82,36 @@ class UploadPageComponent extends PureComponent {
this.props.onCancel();
};
onUploadPhoto = () => {
let token;
getToken().then((Apptoken) => {
if (!Apptoken) {
return Promise.reject(errors.tokenMissing());
}
token = encrypt(Apptoken);
const uri = `${config.apiContextPath}/resource/${token}`;
const formData = new global.FormData();
const file = { uri: this.state.imageURI, type: 'image/jpg', name: this.state.imageName !== '' ? this.state.imageName : this.state.imageURI.split('/')[this.state.imageURI.split('/').length - 1] };
formData.append('file', file);
console.info(formData);
futch(uri, {
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data',
},
body: formData,
}, (progressEvent) => {
const progress = progressEvent.loaded / progressEvent.total;
})
.then(request => request.responseText)// response.text())
.then((responseData) => {
const response = JSON.parse(responseData);
if (response.errorCode === 0) {
const name = 'addTags';// 添加标签
const PicUri = `${config.apiContextPath}/api/interface/user/${name}/invoke`;
console.info(PicUri);
const postjson = { uri: response.data[0], tags: ['当事人信息', '当事人信息'] };
console.info(JSON.stringify(postjson));
userApi.invokeInterface(name, postjson)
// futch(PicUri, {
// method: 'POST',
// headers: {
// 'Content-Type': 'application/json',
// },
// body: JSON.stringify(postjson),
// }, (progressEvent) => {
// console.info(progressEvent);
// })
.then(request => console.info(request));// response.text())
// 这里需要调用接口,对图片数据进行绑定,等待完善
// 页面跳转,跳转到前面的详情的页面
console.info('跳转');
this.props.navigation.navigate('DSRInfoDetail', this.props.navigation.state.params.pID);
}
})
.catch((error) => {
console.info(error);
});
});
uploadResource(
this.state.imageURI,
(uploadId, arg) => {
editResource(arg, createOperations().setName(this.state.imageName).setTags(this.state.tags).use(`rel://path/${this.state.tableName}/${this.state.pID}`)).then().catch(err => console.info(`上传后改名字改tag:${err}`));
console.info('跳转');
this.props.navigation.navigate('DSRInfoDetail', this.props.navigation.state.params.pID);
},
(uploadId, arg) => console.info(arg),
)
.then(uploadId => console.log(`start task ${uploadId}`))
.catch(err => console.log(`上传失败:${err}`));
};
setImageName = (val) => {
console.info(`val:${val}`);
this.setState({ imageName: val });
}
labelExtractor = tag => tag;
renderHeaderMenu() {
renderHeaderMenu = () => {
return (
<View style={[styles.view_header_container, { backgroundColor: 'lightgray' }]}>
<TouchableOpacity
onPress={this.onCancel}
>
<Text style={[styles.text_title, { color: this.props.titleColor }]}>取消</Text>
<Text style={[styles.text_left_title, { color: '#2196F3' }]}>取消</Text>
</TouchableOpacity>
<Text style={[styles.text_title, { color: this.props.titleColor }]}>传照片</Text>
<Text style={styles.text_title}>传照片</Text>
<TouchableOpacity
onPress={this.onUploadPhoto}
>
<Text style={styles.text_right_title}>
<Text style={[styles.text_right_title, { color: '#2196F3' }]}>
上传
</Text>
</TouchableOpacity>
......
import React, { PureComponent } from 'react';
import { BackHandler, Animated, Easing } from 'react-native';
import { BackHandler, Animated, Easing, ToastAndroid } from 'react-native';
import { StackNavigator, addNavigationHelpers, NavigationActions } from 'react-navigation';
import { connect } from 'react-redux';
import NavigatorService from './services/navigator';
......@@ -59,7 +59,7 @@ function getCurrentScreen(navigationState) {
}
return route.routeName;
}
let firstClick = 0;
@connect(({ router }) => ({ router }))
class Router extends PureComponent {
componentWillMount() {
......@@ -68,17 +68,22 @@ class Router extends PureComponent {
componentWillUnmount() {
BackHandler.removeEventListener('hardwareBackPress', this.backHandle);
}
backHandle = () => {
const currentScreen = getCurrentScreen(this.props.router);
if (currentScreen === 'Login' || currentScreen === 'Welcome') {
return true;
}
if (currentScreen !== 'Home') {
console.info(currentScreen);
if (currentScreen !== 'HouseList') {
this.props.dispatch(NavigationActions.back());
return true;
} else {
const timestamp = (new Date()).valueOf();
if (timestamp - firstClick > 2000) {
firstClick = timestamp;
ToastAndroid.show('再按一次退出', ToastAndroid.SHORT);
return true;
} else {
return false;
}
}
return false;
};
render() {
......
......@@ -21,7 +21,7 @@ class Login extends Component {
<Image source={LoginBg} style={LoginStyles.loginView} resizeMode="cover">
<View style={LoginStyles.TextInputView}>
<List
renderHeader={() => <View><Text style={LoginStyles.listText}>深圳房屋普查系统</Text></View>}
renderHeader={() => <View><Text style={LoginStyles.listText}>深圳棚改云</Text></View>}
>
<InputItem
{...getFieldProps('userName')}
......@@ -95,7 +95,7 @@ const LoginStyles = StyleSheet.create({
flexDirection: 'row',
},
loginText: {
loginText: {
color: '#ffffff',
fontWeight: 'bold',
width: 30,
......
......@@ -17,7 +17,7 @@ class DSRInfoDetailScreen extends React.Component {
}
onEdit =() => {
// this.props.dispatch(createAction('DSRInfoDetail/setEnable')(true));
this.props.navigation.navigate('CameraPhoto', { pID: this.props.navigation.state.params });
this.props.navigation.navigate('CameraPhoto', { pID: this.props.navigation.state.params, TableName: 'DangShiRenInfo' });
};
onSubmit = () => {
this.props.form.validateFields({ force: true }, (error, value) => {
......@@ -30,7 +30,7 @@ class DSRInfoDetailScreen extends React.Component {
};
goToViewPage =() => {
// this.props.dispatch(createAction('DSRInfoDetail/setEnable')(true));
this.props.navigation.navigate('DSRInfoFileView', { pID: this.props.navigation.state.params });
this.props.navigation.navigate('DSRInfoFileView', { usage: `rel://DangShiRenInfo/${this.props.navigation.state.params.id}` });
};
validateNoNull = (rule, value, callback) => {
if (value) {
......
import React, { Component } from 'react';
import { Text, FlatList, View } from 'react-native';
import { WingBlank, WhiteSpace } from 'antd-mobile';
import { connect } from 'react-redux';
import { createAction } from '../../../utils/index';
import PicFlatListItem from '../../../components/picFlatListItem';
import SearchComponent from '../../../components/searchComponent';
import { StackNavigator } from 'react-navigation';
import HomeScreen from '../../../components/photo-browser/photoBrowserHome';
import DetailScreen from '../../../components/photo-browser/photoBrowserDetail';
@connect(({ DSRInfo }) => ({ DSRInfo/* , loading: !!loading.effects['obligeeInfo/getObligeeInfo'] */ }))
class FileViewList extends Component {
componentDidMount() {
const { dispatch } = this.props;
dispatch(createAction('DSRInfo/getDSRList')({ clear: '', pDangShiRenBianHao: this.props.DSRInfo.searchValue }));
}
onSearchSubmit = (pDangShiRenBianHao) => {
this.props.dispatch(createAction('DSRInfo/getDSRList')({ clear: 'clear', pDangShiRenBianHao }));
};
onSearchChange = (pName) => {
this.props.dispatch(createAction('DSRInfo/setSearchValue')(pName));
};
// 上拉加载更多
onEndReached = () => {
// 以下是制造新数据
if (!this.props.loading) {
// console.info('执行了上啦加载');
this.props.dispatch(createAction('DSRInfo/getDSRList')({ clear: '', pDangShiRenBianHao: this.props.DSRInfo.searchValue }));
}
};
onPressItem = (id) => {
this.props.dispatch(createAction('DSRInfo/jumpPage')(id));
};
getItemLayout = (data, index) => (
{ length: 200, offset: (200 + 1) * index, index }
);
/**
* 此函数用于为给定的item生成一个不重复的Key。
* Key的作用是使React能够区分同类元素的不同个体,以便在刷新时能够确定其变化的位置,减少重新渲染的开销。
* 若不指定此函数,则默认抽取item.key作为key值。
* 若item.key也不存在,则使用数组下标
*
* @param item
* @private
*/
// 这里指定使用数组下标作为唯一索引
keyExtractor = item => `${item.id}`;
// Footer布局
renderFooter = () => (
<WingBlank size="lg">
<WhiteSpace size="lg" />
<Text style={{ textAlign: 'center', justifyContent: 'center' }}>到底了!!!</Text>
<WhiteSpace size="lg" />
</WingBlank>
);
// 空布局
renderEmptyView = () => (
<WingBlank size="lg">
<WhiteSpace size="lg" />
<Text style={{ textAlign: 'center', justifyContent: 'center' }}>当前无内容</Text>
<WhiteSpace size="lg" />
</WingBlank>
);
// 下拉刷新
renderRefresh = () => {
if (!this.props.loading) {
this.props.dispatch(createAction('DSRInfo/getDSRList')({ clear: 'clear', pDangShiRenBianHao: this.props.DSRInfo.searchValue }));
}
};
/**
* 使用箭头函数防止不必要的re-render;
* 如果使用bind方式来绑定onPressItem,每次都会生成一个新的函数,导致props在===比较时返回false,
* 从而触发自身的一次不必要的重新render,也就是FlatListItem组件每次都会重新渲染。
*
* @param id
* @private
*/
renderItem = ({ item }) => {
return (
<PicFlatListItem
height={150}
title={item.dangShiRenXingMing}
meta={this.props.DSRInfo.metas}
item={item}
onPressItem={this.onPressItem}
/>
);
};
render() {
return (
<View style={{ marginBottom: 50 }}>
<SearchComponent onSearchSubmit={this.onSearchSubmit} onSearchChange={this.onSearchChange} />
<FlatList
data={this.props.DSRInfo.sourceData}
keyExtractor={this.keyExtractor}
renderItem={this.renderItem}
// 决定当距离内容最底部还有多远时触发onEndReached回调;数值范围0~1,例如:0.5表示可见布局的最底端距离content最底端等于可见布局一半高度的时候调用该回调
onEndReachedThreshold={0.3}
// 当列表被滚动到距离内容最底部不足onEndReacchedThreshold设置的距离时调用
onEndReached={this.onEndReached}
ListFooterComponent={this.renderFooter}
ListEmptyComponent={this.renderEmptyView}
refreshing={this.props.loading || false}
onRefresh={this.renderRefresh}
// 是一个可选的优化,用于避免动态测量内容,+1是加上分割线的高度
/>
</View>
);
}
}
const FileViewList = StackNavigator(
{
PhotoViewHome: { screen: HomeScreen },
PhotoViewDetail: { screen: DetailScreen },
},
{
headerMode: 'none',
navigationOptions: {
gesturesEnabled: false,
},
},
);
export default FileViewList;
......@@ -110,7 +110,7 @@ const MainWindow = StackNavigator(
class MainPage extends Component {
onActionSelected = () => {
this.props.navigation.navigate('personCenter');
}
};
render() {
return (
<View style={{ flex: 1 }}>
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论