person.jsx 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. import React from 'react';
  2. import { Input, Button, Form, Select, Radio, Upload, Icon, Spin, message } from 'antd';
  3. import './person.less';
  4. import { addressInit } from '../../tools.js';
  5. import ajax from 'jquery/src/ajax/xhr.js'
  6. import $ from 'jquery/src/ajax';
  7. const FormItem = Form.Item;
  8. const Option = Select.Option;
  9. const RadioGroup = Radio.Group;
  10. function getBase64(img, callback) {
  11. const reader = new FileReader();
  12. reader.addEventListener('load', () => callback(reader.result));
  13. reader.readAsDataURL(img);
  14. };
  15. function beforeUpload(file) {
  16. const isJPG = file.type === 'image/jpeg';
  17. if (!isJPG) {
  18. message.error('You can only upload JPG file!');
  19. }
  20. const isLt2M = file.size / 1024 / 1024 < 2;
  21. if (!isLt2M) {
  22. message.error('Image must smaller than 2MB!');
  23. }
  24. return isJPG && isLt2M;
  25. };
  26. class Avatar extends React.Component {
  27. constructor(props) {
  28. super(props);
  29. this.state = {
  30. imageUrl: ''
  31. }
  32. }
  33. handleChange(info) {
  34. if (info.file.status === 'done') {
  35. // Get this url from response in real world.
  36. getBase64(info.file.originFileObj, imageUrl => this.setState({ imageUrl }));
  37. this.props.urlData(globalConfig.uploadPath + info.file.response.data);
  38. }
  39. }
  40. render() {
  41. const imageUrl = this.state.imageUrl;
  42. return (
  43. <Upload
  44. className="avatar-uploader"
  45. name="avatar"
  46. showUploadList={false}
  47. action={globalConfig.context + "/api/user/avatar/upload"}
  48. beforeUpload={beforeUpload}
  49. onChange={this.handleChange.bind(this)}
  50. >
  51. {
  52. imageUrl ?
  53. <img src={imageUrl} role="presentation" className="avatar" /> :
  54. <Icon type="plus" className="avatar-uploader-trigger" />
  55. }
  56. </Upload>
  57. );
  58. }
  59. };
  60. const PersonFrom = Form.create()(React.createClass({
  61. getData() {
  62. this.props.spinState(true);
  63. $.ajax({
  64. method: "get",
  65. dataType: "json",
  66. url: globalConfig.context + "/api/user/member",
  67. success: function (data) {
  68. if (data.data) {
  69. addressInit('cmbProvince', 'cmbCity', 'cmbArea',
  70. data.data.residenceProvince, data.data.residenceCity, data.data.residenceArea);
  71. this.setState({
  72. nickname: data.data.nickname,
  73. cmbP: data.data.residenceProvince,
  74. cmbC: data.data.residenceCity,
  75. cmbA: data.data.residenceArea,
  76. intro: data.data.personalProfile,
  77. email: data.data.email,
  78. fixTelArea: data.data.fixedTelArea,
  79. fixTel: data.data.fixedTel,
  80. fixTelExtension: data.data.fixedTelExtension,
  81. qq: data.data.qq,
  82. address: data.data.postalAddress,
  83. postcode: data.data.postcode,
  84. });
  85. }
  86. //"personPortraitUrl": "/avadar/4303502988139.jpg",
  87. //"lifePhotoUrl": "/avadar/4303502988131.jpg",
  88. }.bind(this),
  89. }).always(function () {
  90. this.props.spinState(false);
  91. }.bind(this));
  92. },
  93. getInitialState() {
  94. return {
  95. loading: false,
  96. livePicUrlArr: []
  97. };
  98. },
  99. handleSubmit(e) {
  100. e.preventDefault();
  101. this.props.form.validateFields((err, values) => {
  102. //地址值
  103. let cmbP = document.getElementById('cmbProvince').value;
  104. let cmbC = document.getElementById('cmbCity').value;
  105. let cmbA = document.getElementById('cmbArea').value;
  106. if (!err) {
  107. this.props.spinState(true);
  108. $.ajax({
  109. method: "POST",
  110. dataType: "json",
  111. crossDomain: false,
  112. url: globalConfig.context + "/api/user/userInfo",
  113. data: {
  114. "nickname": values.nickname,
  115. "residenceProvince": cmbP,
  116. "residenceCity": cmbC,
  117. "residenceArea": cmbA,
  118. "personPortraitUrl": "/avadar/4303502988139.jpg",
  119. "lifePhotoUrl": "/avadar/4303502988131.jpg",
  120. "personalProfile": values.intro,
  121. "email": values.email,
  122. "fixedTelArea": this.state.fixTelArea,
  123. "fixedTel": this.state.fixTel,
  124. "fixedTelExtension": this.state.fixTelExtension,
  125. "qq": values.qq,
  126. "postalAddress": values.address,
  127. "postcode": values.postcode
  128. }
  129. }).done(function (data) {
  130. if (!data.error.length) {
  131. message.success('保存成功!');
  132. } else {
  133. message.warning(data.error[0].message);
  134. }
  135. }.bind(this)).always(function () {
  136. this.props.spinState(false);
  137. }.bind(this));
  138. }
  139. });
  140. },
  141. avatarUrl(e) {
  142. this.state.avatarUrl = e;
  143. },
  144. livePicUpload(info) {
  145. if (info.file.status === 'done') {
  146. // Get this url from response in real world.
  147. getBase64(info.file.originFileObj, imageUrl => this.setState({ imageUrl }));
  148. this.state.livePicUrlArr.push(globalConfig.uploadPath + info.file.response.data);
  149. }
  150. },
  151. livePicDel(info) {
  152. },
  153. componentDidMount() {
  154. addressInit('cmbProvince', 'cmbCity', 'cmbArea');
  155. this.getData();
  156. },
  157. fixTelAreaChange(e) {
  158. this.setState({
  159. fixTelArea: e.target.value
  160. });
  161. },
  162. fixTelChange(e) {
  163. this.setState({
  164. fixTel: e.target.value
  165. });
  166. },
  167. fixTelExtensionChange(e) {
  168. this.setState({
  169. fixTelExtension: e.target.value
  170. });
  171. },
  172. render() {
  173. const { getFieldDecorator } = this.props.form;
  174. const formItemLayout = {
  175. labelCol: { span: 3 },
  176. wrapperCol: { span: 12 },
  177. };
  178. const _me = this;
  179. return (
  180. <Form horizontal onSubmit={this.handleSubmit} className="person-form">
  181. <FormItem
  182. {...formItemLayout}
  183. label="社区昵称"
  184. >
  185. {getFieldDecorator('nickname', {
  186. initialValue: this.state.nickname || null
  187. })(
  188. <Input />
  189. )}
  190. </FormItem>
  191. <FormItem
  192. {...formItemLayout}
  193. label="居住地"
  194. >
  195. {getFieldDecorator('province', {
  196. initialValue: this.state.cmbA || null
  197. })(
  198. <div>
  199. <select id="cmbProvince" name="cmbProvince"></select>
  200. <select id="cmbCity" name="cmbCity"></select>
  201. <select id="cmbArea" name="cmbArea"></select>
  202. </div>
  203. )}
  204. </FormItem>
  205. <FormItem
  206. {...formItemLayout}
  207. label="个人头像"
  208. labelCol={{ span: 3 }}
  209. wrapperCol={{ span: 20 }}
  210. >
  211. {getFieldDecorator('avatar')(
  212. <Avatar urlData={this.avatarUrl} />
  213. )}
  214. </FormItem>
  215. <div className="set-explain">
  216. <p>请上传清晰的个人身份证正反面原件照片/扫描件 (不能截图、图片内容要求完整 ),</p>
  217. <p>要求2M 以下的jpg、jpeg格式的图片。该资料不会公开展示,仅作为审核材料使用。</p>
  218. </div>
  219. <FormItem
  220. {...formItemLayout}
  221. label="生活照"
  222. >
  223. {getFieldDecorator('livePic', {
  224. valuePropName: 'fileList',
  225. })(
  226. <Upload
  227. name="livePic"
  228. action={globalConfig.context + "/api/user/avatar/upload"}
  229. listType="picture"
  230. beforeUpload={beforeUpload}
  231. onChange={this.livePicUpload}
  232. onRemove={this.livePicDel}>
  233. <Button type="primary">
  234. <Icon type="upload" /> 点击选择文件
  235. </Button>
  236. <p>上传的照片图片格式应为jpg格式,大小在2M以内</p>
  237. </Upload>
  238. )}
  239. </FormItem>
  240. <FormItem
  241. labelCol={{ span: 3 }}
  242. wrapperCol={{ span: 20 }}
  243. label="个人简介"
  244. >
  245. {getFieldDecorator('intro', {
  246. initialValue: this.state.intro || null
  247. })(
  248. <Input type="textarea"
  249. placeholder="全面介绍自己,让商友更深入了解您,内容长度不超过1000个字。"
  250. rows={6} />
  251. )}
  252. <p>还可输入{
  253. (() => {
  254. if (_me.props.form.getFieldValue('intro') && _me.props.form.getFieldValue('intro').length) {
  255. return 1000 - _me.props.form.getFieldValue('intro').length;
  256. } else {
  257. return 1000;
  258. }
  259. })()
  260. }字/1000</p>
  261. </FormItem>
  262. <FormItem
  263. {...formItemLayout}
  264. label="电子邮箱"
  265. hasFeedback
  266. >
  267. {getFieldDecorator('email', {
  268. rules: [{
  269. type: 'email', message: '请输入正确的邮箱地址!',
  270. }],
  271. initialValue: this.state.email || null
  272. })(
  273. <Input />
  274. )}
  275. </FormItem>
  276. <FormItem
  277. {...formItemLayout}
  278. label="固定电话"
  279. >
  280. {getFieldDecorator('telephone')(
  281. <p>
  282. <Input value={this.state.fixTelArea} id="fixTelArea" onChange={this.fixTelAreaChange} /> - <Input value={this.state.fixTel} id="fixTel" onChange={this.fixTelChange} /> - <Input value={this.state.fixTelExtension} id="fixTelExtension" onChange={this.fixTelExtensionChange} />
  283. </p>
  284. )}
  285. </FormItem>
  286. <FormItem
  287. {...formItemLayout}
  288. label="QQ"
  289. >
  290. {getFieldDecorator('qq', {
  291. initialValue: this.state.qq || null
  292. })(
  293. <Input />
  294. )}
  295. </FormItem>
  296. <FormItem
  297. {...formItemLayout}
  298. label="通讯地址"
  299. >
  300. {getFieldDecorator('address', {
  301. initialValue: this.state.address || null
  302. })(
  303. <Input />
  304. )}
  305. </FormItem>
  306. <FormItem
  307. {...formItemLayout}
  308. label="邮编"
  309. >
  310. {getFieldDecorator('postcode', {
  311. initialValue: this.state.postcode || null
  312. })(
  313. <Input />
  314. )}
  315. </FormItem>
  316. <FormItem wrapperCol={{ span: 12, offset: 3 }}>
  317. <Button className="set-submit" type="primary" htmlType="submit">保存</Button>
  318. </FormItem>
  319. </Form >
  320. );
  321. },
  322. }));
  323. const Person = React.createClass({
  324. getInitialState() {
  325. return {
  326. loading: false
  327. };
  328. },
  329. spinChange(e) {
  330. this.setState({
  331. loading: e
  332. });
  333. },
  334. render() {
  335. return (
  336. <Spin spinning={this.state.loading} className='spin-box'>
  337. <div className="set-person">
  338. <div className="acc-detail">
  339. <p className="acc-title">个人资料</p>
  340. <PersonFrom spinState={this.spinChange} />
  341. </div>
  342. </div>
  343. </Spin>
  344. )
  345. }
  346. });
  347. export default Person;