base.jsx 12 KB

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