base.jsx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. import React from 'react';
  2. import { Input, Button, Select, Form, Radio, Upload, Icon, DatePicker, Spin, message } from 'antd';
  3. import moment from 'moment';
  4. import './base.less';
  5. import ajax from 'jquery/src/ajax/xhr.js'
  6. import $ from 'jquery/src/ajax';
  7. import ChangePw from './changePassword.jsx';
  8. import ChangeMobile from './changeMobile.jsx';
  9. const FormItem = Form.Item;
  10. const Option = Select.Option;
  11. const RadioGroup = Radio.Group;
  12. const { MonthPicker, RangePicker } = DatePicker
  13. import weixin from '../../../../image/weixin-w.png';
  14. import qq from '../../../../image/qq-w.png';
  15. import weibo from '../../../../image/weibo-w.png';
  16. import card1 from '../../../../image/idcard1.jpg';
  17. import card2 from '../../../../image/idcard2.jpg';
  18. function getBase64(img, callback) {
  19. const reader = new FileReader();
  20. reader.addEventListener('load', () => callback(reader.result));
  21. reader.readAsDataURL(img);
  22. };
  23. function beforeUpload(file) {
  24. const isJPG = file.type === 'image/jpeg';
  25. if (!isJPG) {
  26. message.error('You can only upload JPG file!');
  27. }
  28. const isLt2M = file.size / 1024 / 1024 < 2;
  29. if (!isLt2M) {
  30. message.error('Image must smaller than 2MB!');
  31. }
  32. return isJPG && isLt2M;
  33. };
  34. class Avatar extends React.Component {
  35. constructor(props) {
  36. super(props);
  37. this.state = {
  38. imageUrl: ''
  39. }
  40. }
  41. handleChange(info) {
  42. if (info.file.status === 'done') {
  43. // Get this url from response in real world.
  44. getBase64(info.file.originFileObj, imageUrl => this.setState({ imageUrl }));
  45. this.props.urlData(info.file.response.data);
  46. }
  47. }
  48. theObj() {
  49. return {
  50. 'sign': this.props.name
  51. }
  52. }
  53. render() {
  54. const imageUrl = this.state.imageUrl;
  55. return (
  56. <Upload
  57. className="avatar-uploader"
  58. name={this.props.name}
  59. showUploadList={false}
  60. action={globalConfig.context + "/api/user/identity/upload"}
  61. data={this.theObj.bind(this)}
  62. beforeUpload={beforeUpload}
  63. onChange={this.handleChange.bind(this)}
  64. >
  65. {
  66. imageUrl ?
  67. <img src={imageUrl} role="presentation" id={this.props.name} /> :
  68. <Icon type="plus" className="avatar-uploader-trigger" />
  69. }
  70. </Upload>
  71. );
  72. }
  73. };
  74. const BaseFrom = Form.create()(React.createClass({
  75. getData() {
  76. this.props.spinState(true);
  77. $.ajax({
  78. method: "get",
  79. dataType: "json",
  80. url: globalConfig.context + "/api/user/base",
  81. success: function (data) {
  82. if (data.data) {
  83. let d = new Date();
  84. d.setMonth(data.data.dateOfBirthMonth - 1);
  85. d.setYear(parseInt(data.data.dateOfBirthYear));
  86. this.setState({
  87. username : data.data.username,
  88. sex : data.data.sex === '女' ? 'female' : 'male',
  89. birth : d,
  90. idnumber : data.data.idNumber,
  91. idcard1 : data.data.oppositeIdUrl,
  92. idcard2 : data.data.positiveIdUrl,
  93. })
  94. };
  95. }.bind(this),
  96. }).done(function (data) {
  97. if (data.error.length) {
  98. message.warning(data.error[0].message);
  99. }
  100. }.bind(this)).always(function () {
  101. this.props.spinState(false);
  102. }.bind(this));
  103. },
  104. getInitialState() {
  105. return {
  106. };
  107. },
  108. componentDidMount() {
  109. this.getData();
  110. },
  111. handleSubmit(e) {
  112. e.preventDefault();
  113. this.props.form.validateFields((err, values) => {
  114. if (!err) {
  115. this.props.spinState(true);
  116. $.ajax({
  117. method: "POST",
  118. dataType: "json",
  119. crossDomain: false,
  120. url: globalConfig.context + "/api/user/userIndentity",
  121. data: {
  122. "username": values.username,
  123. "sex": values.sex === 'female' ? '女' : '男',
  124. "dateOfBirthYear": values.birth ? values.birth._d.getFullYear() : undefined,
  125. "dateOfBirthMonth": values.birth ? values.birth._d.getMonth() + 1 : undefined,
  126. "idNumber": values.idcardnum,
  127. "positiveIdUrl": this.state.idcard1,
  128. "oppositeIdUrl": this.state.idcard2
  129. }
  130. }).done(function (data) {
  131. if (!data.error.length) {
  132. message.success('保存成功!');
  133. } else {
  134. message.warning(data.error[0].message);
  135. }
  136. }.bind(this)).always(function () {
  137. this.props.spinState(false);
  138. }.bind(this));
  139. }
  140. });
  141. },
  142. checkIdcardnum(rule, value, callback) {
  143. if (!/(^\d{15}$)|(^\d{17}(\d|X)$)/.test(value)) {
  144. callback('请输入正确的身份证号!');
  145. } else {
  146. callback();
  147. }
  148. },
  149. urlData1(e) {
  150. this.state.idcard1 = e;
  151. },
  152. urlData2(e) {
  153. this.state.idcard2 = e;
  154. },
  155. render() {
  156. const { getFieldDecorator } = this.props.form;
  157. const formItemLayout = {
  158. labelCol: { span: 4 },
  159. wrapperCol: { span: 12 },
  160. };
  161. return (
  162. <Form horizontal onSubmit={this.handleSubmit} className="base-form">
  163. <FormItem
  164. {...formItemLayout}
  165. label="姓名"
  166. >
  167. {getFieldDecorator('username', {
  168. initialValue: this.state.username || null
  169. })(
  170. <Input />
  171. )}
  172. </FormItem>
  173. <FormItem
  174. {...formItemLayout}
  175. label="性别"
  176. >
  177. {getFieldDecorator('sex', {
  178. initialValue: this.state.sex || null
  179. })(
  180. <RadioGroup>
  181. <Radio value="male">男</Radio>
  182. <Radio value="female">女</Radio>
  183. </RadioGroup>
  184. )}
  185. </FormItem>
  186. <FormItem
  187. {...formItemLayout}
  188. label="出生日期"
  189. >
  190. {getFieldDecorator('birth', {
  191. rules: [{ type: 'object', message: '请选择日期!' }],
  192. initialValue: moment(this.state.birth, 'YYYY/MM') || null
  193. })(
  194. <MonthPicker />
  195. )}
  196. </FormItem>
  197. <FormItem
  198. {...formItemLayout}
  199. label="身份证号"
  200. >
  201. {getFieldDecorator('idcardnum', {
  202. rules: [{
  203. validator: this.checkIdcardnum,
  204. }],
  205. initialValue: this.state.idnumber || null
  206. })(
  207. <Input />
  208. )}
  209. </FormItem>
  210. <FormItem wrapperCol={{ span: 21, offset: 4 }}>
  211. <p>请上传清晰的个人身份证正反面原件照片/扫描件 (不能截图、图片内容要求完整 ),</p>
  212. <p>要求2M 以下的jpg、jpeg、gif、png格式的图片。该资料不会公开展示,仅作为审核材料使用。</p>
  213. </FormItem>
  214. <FormItem
  215. {...formItemLayout}
  216. label="身份证正面"
  217. >
  218. {getFieldDecorator('idcard1')(
  219. <Avatar name="idcard1" urlData={this.urlData1} />
  220. )}
  221. <p>{
  222. this.state.idcard1 !== "" ?
  223. <span><Icon style={{ 'color': '#79b5ff', 'fontSize': '14px', 'margin': '0 6px' }} type="check-circle" />已上传</span> :
  224. <span><Icon style={{ 'color': '#fa0', 'fontSize': '14px', 'margin': '0 6px' }} type="exclamation-circle" />未上传</span>
  225. }
  226. </p>
  227. </FormItem>
  228. <FormItem
  229. {...formItemLayout}
  230. label="身份证反面"
  231. >
  232. {getFieldDecorator('idcard2')(
  233. <Avatar name="idcard2" urlData={this.urlData2} />
  234. )}
  235. <p>{
  236. this.state.idcard2 !== "" ?
  237. <span><Icon style={{ 'color': '#79b5ff', 'fontSize': '14px', 'margin': '0 6px' }} type="check-circle" />已上传</span> :
  238. <span><Icon style={{ 'color': '#fa0', 'fontSize': '14px', 'margin': '0 6px' }} type="exclamation-circle" />未上传</span>
  239. }
  240. </p>
  241. </FormItem>
  242. <FormItem wrapperCol={{ span: 21, offset: 4 }}>
  243. <p className="acc-title">示例</p>
  244. <div className="idcard-img clearfix">
  245. <div>
  246. <div className="idcard-imgbox">
  247. <img src={card1} alt="" />
  248. </div>
  249. </div>
  250. <div>
  251. <div className="idcard-imgbox">
  252. <img src={card2} alt="" />
  253. </div>
  254. </div>
  255. </div>
  256. </FormItem>
  257. <FormItem wrapperCol={{ span: 12, offset: 4 }}>
  258. <Button className="set-submit" type="primary" htmlType="submit">保存</Button>
  259. </FormItem>
  260. </Form >
  261. );
  262. },
  263. }));
  264. const Base = React.createClass({
  265. getInitialState() {
  266. return {
  267. loading: false
  268. };
  269. },
  270. spinChange(e) {
  271. this.setState({
  272. loading: e
  273. });
  274. },
  275. render() {
  276. return (
  277. <Spin spinning={this.state.loading} className='spin-box'>
  278. <div className="set-base">
  279. <div className="acc-detail">
  280. <p className="acc-title">您登录的账号</p>
  281. <p>阿凡提号: <span>{userData.number || undefined}</span></p>
  282. <p>登录手机号: <span>{userData.mobile || undefined}</span></p>
  283. <div className="clearfix">
  284. <ChangeMobile />
  285. <ChangePw />
  286. </div>
  287. </div>
  288. <div className="acc-bind" style={{ 'display': 'none' }}>
  289. <p className="acc-title">绑定账号 <span>绑定后,可使用第三方账号直接登录阿凡提网</span></p>
  290. <p>
  291. <Button className="relateqq"><img src={qq} alt="" /> QQ账号登录</Button>
  292. <Button className="relateweibo"><img src={weibo} alt="" />微博账号登录</Button>
  293. <Button className="relateweixin"><img src={weixin} alt="" />微信账号登录</Button>
  294. </p>
  295. </div>
  296. <div className="acc-info">
  297. <p className="acc-title">身份信息 <span>提供正确的身份信息,有助于进行身份验证,提升信用形象</span></p>
  298. <BaseFrom spinState={this.spinChange} />
  299. </div>
  300. </div>
  301. </Spin>
  302. )
  303. }
  304. });
  305. export default Base;