Commit 89f900c1 authored by superman's avatar superman

增加身份认证审核

parent 1ec72cd6
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
import React, {Component, PropTypes} from 'react'; import React, {Component, PropTypes} from 'react';
import {Button, Icon, Popconfirm, Menu, Row, Col, Popover} from 'antd'; import {Button, Icon, Popconfirm, Menu, Row, Col, Popover, Tooltip} from 'antd';
import {connect} from 'react-redux'; import {connect} from 'react-redux';
import {Link} from 'react-router'; import {Link} from 'react-router';
...@@ -78,6 +78,9 @@ export default class HeaderOperation extends Component { ...@@ -78,6 +78,9 @@ export default class HeaderOperation extends Component {
{ {
buttons.map(button=> { buttons.map(button=> {
const props = {...defaultButtons[button.key], ...button}; const props = {...defaultButtons[button.key], ...button};
const title = props.title;
delete props.title;
if (props.link) { if (props.link) {
const icon = props.icon; const icon = props.icon;
...@@ -85,15 +88,19 @@ export default class HeaderOperation extends Component { ...@@ -85,15 +88,19 @@ export default class HeaderOperation extends Component {
delete props.icon; delete props.icon;
delete props.link; delete props.link;
return ( return (
<Button type="ghost" {...props} > <Tooltip title={title} key={props.key+'tooltip'}>
<Link to={link}> <Button type="ghost" {...props} >
<Icon type={icon}/> <Link to={link}>
</Link> <Icon type={icon}/>
</Button> </Link>
</Button>
</Tooltip>
); );
} }
const btn = ( const btn = (
<Button type="ghost" {...props} /> <Tooltip title={title} key={props.key+'tooltip'}>
<Button type="ghost" {...props} />
</Tooltip>
); );
if (props.onConfirm) { if (props.onConfirm) {
return ( return (
......
...@@ -73,6 +73,10 @@ export default class App extends Component { ...@@ -73,6 +73,10 @@ export default class App extends Component {
to: '/withdraw/audits', to: '/withdraw/audits',
cn: '提现审核', cn: '提现审核',
en: 'Withdraw Money' en: 'Withdraw Money'
},{
to:'/authInfo/audits',
cn:'身份认证审核',
en: 'Auth Audits'
} }
] ]
}, { }, {
......
import React, {Component, PropTypes} from 'react';
import {connect} from 'react-redux';
import {
Row,
Col,
Form,
Input,
Button,
Checkbox,
Select,
message,
Tabs,
Cascader,
Radio,
Upload,
Icon,
Modal,
DatePicker,
Table,
Spin
} from 'antd';
import Layout from '../../components/Layout/Layout';
import MainHeader from '../../components/MainHeader/MainHeader';
import HeaderOperation, {DetailOperations} from '../../components/HeaderOperation/HeaderOperation';
import {
formatDateTime,
formItemLayout,
smallFormItemLayout,
footerFormSubmitLayout,
remittanceAuditStatusToString,
leftRightFormItemLayout,
NULL
} from '../../utils';
@connect(state=>({
loading: state.authInfo.loading,
audit: state.authInfo.audit,
}))
@Form.create()
export default class PassItem extends Component {
constructor() {
super(...arguments);
this.state = {
priviewVisible: false,
priviewImage: '',
isEdit: false
}
}
componentDidMount() {
this.fetchItem(this.props.params.id);
};
fetchItem(id) {
this.props.dispatch({
type: 'FETCH_AUTHINFO_ITEM',
id
});
};
handleSubmit(status, e) {
e.preventDefault();
const data = this.props.form.getFieldsValue();
data.id = this.props.params.id;
data.status = status;
console.log(data);
if (status == 9) {
delete data.memo;
}
this.props.dispatch({
type: 'PASS_AUTHINFO_ITEM',
data
});
}
render() {
const {audit, loading, form:{getFieldProps}, location:{query}, params, dispatch} = this.props;
let title = (audit && audit.realName ? audit.realName + ' - ' : '');
const isEdit = audit && audit.status == 1 && this.state.isEdit;
if (audit) {
switch (audit.status) {
case 1:
title += '身份认证审核详情' + (isEdit? ' - 审核中': '');
break;
case 5:
title += '审核失败';
break;
case 9:
title += '审核成功';
}
} else {
title += '身份认证审核详情';
}
const buttons = [{
key: 'rollback',
onClick: e=> {
e.preventDefault();
isEdit ?
this.setState({isEdit: !this.state.isEdit}) :
this.props.history.goBack();
}
}];
if(audit && audit.status == 1){
buttons.unshift({
key:'edit',
onClick:e=> {
e.preventDefault();
this.setState({isEdit: !this.state.isEdit})
}
});
}
const operation = (
<HeaderOperation history={this.props.history} buttons={buttons}/>
);
const header = (<MainHeader breadcrumb={['审核管理', '身份认证审核', '审核详情']} title={title} operation={operation}/>);
const imgProps = (src)=>({
src: src + '!t',
style: {maxWidth: 200, maxHeight: 160},
onClick: e => {
e.preventDefault();
this.setState({
priviewVisible: true,
priviewImage: src
});
}
});
return (
<Layout header={header}>
<Spin spinning={loading}>
{
audit &&
<Form className="main-form" horizontal>
<Row style={{padding: '0 20px'}}>
<Col span="12">
<Form.Item label="用户ID" {...leftRightFormItemLayout}>
{audit.userId || NULL}
</Form.Item>
<Form.Item label="用户名" {...leftRightFormItemLayout}>
{audit.realName || NULL}
</Form.Item>
<Form.Item label="昵称" {...leftRightFormItemLayout}>
{audit.nick || NULL}
</Form.Item>
<Form.Item label="手机号" {...leftRightFormItemLayout}>
{audit.mobile || NULL}
</Form.Item>
{
audit.status == 5 ?
<Form.Item label="拒绝理由" {...smallFormItemLayout}>
{ audit.memo || NULL }
</Form.Item>
:
(
audit.status == 1 && isEdit &&
<Form.Item label="拒绝理由" {...smallFormItemLayout}>
<Input placeholder="拒绝理由" type="textarea"
autosize
{...getFieldProps('memo', {
initialValue: ''
})} />
</Form.Item>
)
}
<Form.Item wrapperCol={{span: 16, offset: 6}} style={{marginTop: 30}}>
{
audit.status == 1 && (
isEdit ?
<span>
<Button size="large" type="primary"
onClick={this.handleSubmit.bind(this, 9)}>
<Icon type="check-circle-o"/>通过
</Button>
<Button size="large" type="ghost"
onClick={this.handleSubmit.bind(this, 5)}
style={{margin: 'auto 1em'}}>
<Icon type="cross-circle-o"/>拒绝
</Button>
</span>
:
<Button type="primary"
style={{marginRight: '1em'}}
onClick={ e=> {
e.preventDefault();
this.setState({isEdit: !this.state.isEdit})
}}>
<Icon type="edit"/>审核
</Button>
)
}
<Button onClick={e=> {
e.preventDefault();
isEdit ?
this.setState({isEdit: !this.state.isEdit}) :
this.props.history.goBack();
}}>
<Icon type="rollback"/>返回
</Button>
</Form.Item>
</Col>
<Col span="12">
<Form.Item label="身份认证照片">
{
audit.authPic ?
<img {...imgProps(audit.authPic)}/>
:
<p style={{color: '#f00'}}>
<Icon type="cross-circle-o" style={{marginRight: '.5em'}}/>
身份认证照片未上传,请拒绝!
</p>
}
</Form.Item>
</Col>
</Row>
<Modal className="img-priview-dialog" footer={null}
visible={this.state.priviewVisible}
onCancel={()=>this.setState({priviewVisible: false})}>
<img src={this.state.priviewImage}/>
</Modal>
</Form>
}
</Spin>
</Layout>
);
}
}
import React, {Component, PropTypes} from 'react';
import {connect} from 'react-redux';
import {Table, Icon} from 'antd';
import {Link} from 'react-router';
import {serialize, formatDateTime, remittanceAuditStatusToString} from '../../utils';
import Layout from '../../components/Layout/Layout';
import MainHeader from '../../components/MainHeader/MainHeader';
import HeaderOperation from '../../components/HeaderOperation/HeaderOperation';
const columns = [
{
title: 'ID',
dataIndex: 'id',
key: 'id',
width: 70
}, {
title: '用户ID',
dataIndex: 'userId',
key: 'userId',
width: 100
}, {
title: '申请时间',
dataIndex: 'dateCreated',
key: 'dateCreated',
width: 150,
className: 'tac',
render: (dateCreated, record)=>(
<span>
{dateCreated && formatDateTime(dateCreated)}
</span>
)
}, {
title: '状态',
dataIndex: 'status',
key: 'status',
width: 120,
className: 'tac',
render: (status, record)=>(<span data-status={status}>{remittanceAuditStatusToString(status)}</span>)
}, {
title: '操作',
key: 'operation',
width: 60,
className: 'tac',
render: (text, record)=>(
<span>
{
record.status == 1 &&
<Link to={'/authInfo/audits/' + record.id} onClick={e=>e.stopPropagation()}>审核</Link>
}
</span>
)
}
];
@connect(state=>({
items: state.authInfo.audits,
loading: state.authInfo.loading,
total: state.authInfo.total,
}))
export default class List extends Component {
constructor(props, context) {
super(props, context);
this.state = {
filterVisible: false
}
}
componentDidMount() {
this.fetchList(this.props.location.query);
};
fetchList(query) {
this.props.dispatch({
type: 'FETCH_AUTHINFO_LIST',
query
});
}
handleRowClick({id}) {
this.props.history.push('/authInfo/audits/' + id);
}
render() {
const {total, items, loading, history:{replace}, location:{pathname, query}} = this.props;
const pagination = {
total: total,
pageSize: parseInt(query.s, 10) || 30,
current: parseInt(query.p, 10) || 1,
showSizeChanger: true,
showTotal: total => `共 ${total} 条`,
pageSizeOptions: ['10', '30', '50', '100'],
onShowSizeChange: (current, pageSize)=> {
console.log('Current: ', current, '; PageSize: ', pageSize);
query.p = current;
query.s = pageSize;
replace(pathname + '?' + serialize(query));
this.fetchList(query);
},
onChange: (current) => {
console.log('Current: ', current);
query.p = current;
replace(pathname + '?' + serialize(query));
this.fetchList(query);
}
};
const operation = (
<HeaderOperation history={this.props.history} buttons={[{
key: 'filter',
}]}/>
);
const header = (<MainHeader breadcrumb={['审核管理', '身份认证审核']}
title="身份认证审核列表"
operation={operation}
/>);
return (
<Layout header={header}>
<Table className="list-table" columns={columns}
dataSource={Array.isArray(items) ? items : []}
loading={loading}
pagination={pagination}
scroll={{y: window.innerHeight - (this.state.filterVisible ? 203 : 150)}}
onRowClick={this.handleRowClick.bind(this)}
/>
</Layout>
);
}
}
...@@ -6,6 +6,10 @@ const Home = ({location}) => { ...@@ -6,6 +6,10 @@ const Home = ({location}) => {
<div style={{padding: '20px 50px 20px 100px'}}> <div style={{padding: '20px 50px 20px 100px'}}>
<h1 style={{marginBottom: 50}}>欢迎使用枢纽科技后台</h1> <h1 style={{marginBottom: 50}}>欢迎使用枢纽科技后台</h1>
<h3>2016-08-15 更新 1.3.1</h3>
<p>
1. 增加身份认证审核
</p>
<h3>2016-08-12 更新 1.3.0</h3> <h3>2016-08-12 更新 1.3.0</h3>
<p> <p>
1. 权限系统<br/> 1. 权限系统<br/>
......
...@@ -30,3 +30,5 @@ export AuthorityItem from './Authority/EditItem'; ...@@ -30,3 +30,5 @@ export AuthorityItem from './Authority/EditItem';
export ModifyPassword from './Users/ModifyPassword'; export ModifyPassword from './Users/ModifyPassword';
export Register from './Users/Register'; export Register from './Users/Register';
export AuthInfoList from './AuthInfo/List';
export AuthInfoItem from './AuthInfo/Item';
import {handleActions} from 'redux-actions';
import {combineReducer} from 'redux';
const authInfo = handleActions({
['FETCH_AUTHINFO_LIST'](state) {
return {...state, loading: true,};
},
['FETCH_AUTHINFO_LIST_SUCCESS'](state, action) {
return {...state, loading: false, audits: action.items, total: action.total};
},
['FETCH_AUTHINFO_LIST_FAILED'](state, action) {
return {...state, err: action.err, loading: false, audits: [], total: 0};
},
['FETCH_AUTHINFO_ITEM'](state) {
return {...state, loading: true,};
},
['FETCH_AUTHINFO_ITEM_SUCCESS'](state, action) {
return {...state, loading: false, audit: action.item};
},
['FETCH_AUTHINFO_ITEM_FAILED'](state, action) {
return {...state, err: action.err, loading: false, audit: null};
},
['PASS_AUTHINFO_ITEM'](state){
return {...state, loading: true};
},
['PASS_AUTHINFO_ITEM_SUCCESS'](state, action){
return {...state, loading: false, audit: {...state.audit, ...action.data}};
},
['PASS_AUTHINFO_ITEM_FAILED'](state, action){
return {...state, loading: false, err: action.err};
}
}, {
audits: [],
loading: false,
});
export default authInfo;
...@@ -43,6 +43,12 @@ export default (store)=> { ...@@ -43,6 +43,12 @@ export default (store)=> {
<Route path=":id" component={Containers.PassWithDrawItem}/> <Route path=":id" component={Containers.PassWithDrawItem}/>
</Route> </Route>
</Route> </Route>
<Route path="authInfo">
<Route path="audits">
<IndexRoute component={Containers.AuthInfoList}/>
<Route path=":id" component={Containers.AuthInfoItem}/>
</Route>
</Route>
<Route path="customMessages"> <Route path="customMessages">
<IndexRoute component={Containers.CustomMessageList}/> <IndexRoute component={Containers.CustomMessageList}/>
<Route path="create" component={Containers.CustomMessageAddItem}/> <Route path="create" component={Containers.CustomMessageAddItem}/>
...@@ -65,11 +71,11 @@ export default (store)=> { ...@@ -65,11 +71,11 @@ export default (store)=> {
</Route> </Route>
</Route> </Route>
<Route path="my"> <Route path="my">
<Route path="modifyPassword" component={Containers.ModifyPassword} /> <Route path="modifyPassword" component={Containers.ModifyPassword}/>
</Route> </Route>
</Route> </Route>
<Route path="/login" component={Containers.Login}/> <Route path="/login" component={Containers.Login}/>
<Route path="/register" component={Containers.Register} /> <Route path="/register" component={Containers.Register}/>
<Route path="*" component={Containers.NotFound}/> <Route path="*" component={Containers.NotFound}/>
</Route> </Route>
); );
......
import {takeLatest} from 'redux-saga';
import {take, call, put, fork, cancel, select} from 'redux-saga/effects';
import {fetchList, fetchItem, pass} from '../services/authInfo';
import {message} from 'antd';
import {watchIndex, watchShow, watchCreate, watchEdit, watch} from './RESTful';
export default function*() {
const ID = 'AUTHINFO';
yield fork(watchIndex(ID, fetchList));
yield fork(watchShow(ID, fetchItem));
yield fork(watch('PASS_AUTHINFO_ITEM', pass, '审核'));
}
...@@ -4,31 +4,6 @@ import {fetchList, fetchItem, pass} from '../services/remittance'; ...@@ -4,31 +4,6 @@ import {fetchList, fetchItem, pass} from '../services/remittance';
import {message} from 'antd'; import {message} from 'antd';
import {watchIndex, watchShow, watchCreate, watchEdit, watch} from './RESTful'; import {watchIndex, watchShow, watchCreate, watchEdit, watch} from './RESTful';
// function* passItem(item){
// try {
// yield call(pass, item);
//
// yield put({
// type: 'PASS_REMITTANCE_ITEM_SUCCESS',
// item
// });
// } catch (err) {
// console.log(err);
// message.error(err);
// yield put({
// type: 'PASS_REMITTANCE_ITEM_FAILED',
// err
// });
// }
// }
// function* watchPassItem() {
// while (true) {
// const {data} = yield take('PASS_REMITTANCE_ITEM');
// yield fork(passItem, data);
// }
// }
export default function*() { export default function*() {
const ID = 'REMITTANCE'; const ID = 'REMITTANCE';
// yield fork(watchPassItem); // yield fork(watchPassItem);
......
import xFetch from './xFetch';
import {serialize} from '../utils';
export async function fetchList(query) {
return xFetch('/api/authInfo/audits' + '?' + serialize({s: 30, ...query}));
}
export async function fetchItem(id) {
return xFetch('/api/authInfo/audits/' + id);
}
export async function pass(data) {
return xFetch('/api/authInfo/audits/' + data.id, {
method: 'PATCH',
body: serialize(data)
});
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment