activityCostList.jsx 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622
  1. import React from 'react';
  2. import { Icon, Form, Upload, Button, Input, Spin, Table, message, Select, Modal, DatePicker, InputNumber } from 'antd';
  3. import './activityCostList.less';
  4. import { beforeUploadFile, newDownloadFile } from '../../tools.js';
  5. import YearSelect from '../../yearSelect.jsx';
  6. import moment from 'moment';
  7. import ajax from 'jquery/src/ajax/xhr.js';
  8. import $ from 'jquery/src/ajax';
  9. const ActivityDescFrom = Form.create()(React.createClass({
  10. getInitialState() {
  11. return {
  12. loading: false,
  13. activityNumberOption: [],
  14. };
  15. },
  16. allCostCount() {
  17. this.state.internalAllCost = this.props.form.getFieldValue('internalLaborCost') + this.props.form.getFieldValue('internalDirectCost') +
  18. this.props.form.getFieldValue('internalDepreciationCost') + this.props.form.getFieldValue('internalAmortizationCost') +
  19. this.props.form.getFieldValue('internalDesignCost') + this.props.form.getFieldValue('internalEquipmentCost') +
  20. this.props.form.getFieldValue('internalOtherCost');
  21. this.state.allCost = this.props.form.getFieldValue('internalLaborCost') + this.props.form.getFieldValue('internalDirectCost') +
  22. this.props.form.getFieldValue('internalDepreciationCost') + this.props.form.getFieldValue('internalAmortizationCost') +
  23. this.props.form.getFieldValue('internalDesignCost') + this.props.form.getFieldValue('internalEquipmentCost') +
  24. this.props.form.getFieldValue('internalOtherCost') + this.props.form.getFieldValue('externalTotalCost');
  25. },
  26. componentDidMount() {
  27. this.allCostCount();
  28. this.setState({
  29. loading: false
  30. });
  31. },
  32. componentWillReceiveProps(nextProps) {
  33. this.allCostCount();
  34. let _me = this;
  35. if (!this.props.visible && nextProps.visible && nextProps.activityNumberList) {
  36. nextProps.activityNumberList.map(function (item) {
  37. _me.state.activityNumberOption.push(
  38. <Select.Option value={item.aid} key={item.uid}>{item.activityNumber}</Select.Option>
  39. )
  40. });
  41. this.state.fileList = [];
  42. };
  43. },
  44. handleSubmit(e) {
  45. e.preventDefault();
  46. this.props.form.validateFields((err, values) => {
  47. if (!err) {
  48. this.props.spinState(true);
  49. $.ajax({
  50. method: "POST",
  51. dataType: "json",
  52. crossDomain: false,
  53. url: globalConfig.context + "/api/user/cognizance/activityCost",
  54. data: {
  55. id: this.props.data.id,
  56. aid: this.props.data.aid,
  57. activityNumber: this.state.activityNumber,
  58. year: this.state.year,
  59. internalLaborCost: values.internalLaborCost,
  60. internalDirectCost: values.internalDirectCost,
  61. internalDepreciationCost: values.internalDepreciationCost,
  62. internalAmortizationCost: values.internalAmortizationCost,
  63. internalDesignCost: values.internalDesignCost,
  64. internalEquipmentCost: values.internalEquipmentCost,
  65. internalOtherCost: values.internalOtherCost,
  66. externalTotalCost: values.externalTotalCost,
  67. externalAbroadCost: values.externalAbroadCost,
  68. //enterpriseFiller: values.enterpriseFiller,
  69. //signDateFormattedDate: values.signDate.format('YYYY-MM-DD'),
  70. sortNumber: values.sortNumber,
  71. accountUrl: this.state.accountUrl
  72. }
  73. }).done(function (data) {
  74. if (!data.error.length) {
  75. message.success('保存成功!');
  76. } else {
  77. message.warning(data.error[0].message);
  78. }
  79. }.bind(this)).always(function () {
  80. this.props.spinState(false);
  81. this.props.clickOk();
  82. this.props.form.resetFields();
  83. }.bind(this));
  84. }
  85. });
  86. },
  87. render() {
  88. const FormItem = Form.Item;
  89. const { getFieldDecorator } = this.props.form;
  90. const theData = this.props.data;
  91. const formItemLayout = {
  92. labelCol: { span: 14 },
  93. wrapperCol: { span: 8 },
  94. };
  95. const _me = this;
  96. return (
  97. <Form onSubmit={this.handleSubmit} className="activityCost-form">
  98. <p className="activityCost-title">项目编号</p>
  99. {
  100. theData.activityNumber ? <span>{theData.activityNumber}</span> :
  101. <Select placeholder="请选择项目编号" style={{ width: 200 }}
  102. onSelect={(e, n) => { this.state.aid = e; this.state.activityNumber = n.props.children }}>
  103. {this.state.activityNumberOption}
  104. </Select>
  105. }
  106. <p className="activityCost-title">费用年份</p>
  107. <div><YearSelect defValue={this.state.year} handleyear={(e) => { this.state.year = e; }} /></div>
  108. <p className="activityCost-title">内部研究开发费用(万元)</p>
  109. <div className="clearfix activityCost-box">
  110. <FormItem className="half-item"
  111. {...formItemLayout}
  112. label="共计(万元)"
  113. >
  114. {getFieldDecorator('internalAllCost')(
  115. <span className="number-box">
  116. {this.state.internalAllCost}
  117. </span>
  118. )}
  119. </FormItem>
  120. <FormItem className="half-item"
  121. {...formItemLayout}
  122. label="人员人工费用(万元)"
  123. >
  124. {getFieldDecorator('internalLaborCost', {
  125. rules: [{ type: "number", required: true, message: '此项为必填项!' }],
  126. initialValue: theData.internalLaborCost
  127. })(
  128. <InputNumber />
  129. )}
  130. </FormItem>
  131. <FormItem className="half-item"
  132. {...formItemLayout}
  133. label="直接投入费用(万元)"
  134. >
  135. {getFieldDecorator('internalDirectCost', {
  136. rules: [{ type: "number", required: true, message: '此项为必填项!' }],
  137. initialValue: theData.internalDirectCost
  138. })(
  139. <InputNumber />
  140. )}
  141. </FormItem>
  142. <FormItem className="half-item"
  143. {...formItemLayout}
  144. label="折旧费用与长期待摊费用(万元)"
  145. >
  146. {getFieldDecorator('internalDepreciationCost', {
  147. rules: [{ type: "number", required: true, message: '此项为必填项!' }],
  148. initialValue: theData.internalDepreciationCost
  149. })(
  150. <InputNumber />
  151. )}
  152. </FormItem>
  153. <FormItem className="half-item"
  154. {...formItemLayout}
  155. label="无形资产摊销费用(万元)"
  156. >
  157. {getFieldDecorator('internalAmortizationCost', {
  158. rules: [{ type: "number", required: true, message: '此项为必填项!' }],
  159. initialValue: theData.internalAmortizationCost
  160. })(
  161. <InputNumber />
  162. )}
  163. </FormItem>
  164. <FormItem className="half-item"
  165. {...formItemLayout}
  166. label="设计费用(万元)"
  167. >
  168. {getFieldDecorator('internalDesignCost', {
  169. rules: [{ type: "number", required: true, message: '此项为必填项!' }],
  170. initialValue: theData.internalDesignCost
  171. })(
  172. <InputNumber />
  173. )}
  174. </FormItem>
  175. <FormItem className="half-item"
  176. {...formItemLayout}
  177. label="装备调试费用与实验费用(万元)"
  178. >
  179. {getFieldDecorator('internalEquipmentCost', {
  180. rules: [{ type: "number", required: true, message: '此项为必填项!' }],
  181. initialValue: theData.internalEquipmentCost
  182. })(
  183. <InputNumber />
  184. )}
  185. </FormItem>
  186. <FormItem className="half-item"
  187. {...formItemLayout}
  188. label="其他费用(万元)"
  189. >
  190. {getFieldDecorator('internalOtherCost', {
  191. rules: [{ type: "number", required: true, message: '此项为必填项!' }],
  192. initialValue: theData.internalOtherCost
  193. })(
  194. <InputNumber />
  195. )}
  196. </FormItem>
  197. </div>
  198. <p className="activityCost-title">委托外部研究开发费用(万元)</p>
  199. <div className="clearfix activityCost-box">
  200. <FormItem className="half-item"
  201. {...formItemLayout}
  202. label="共计(万元)"
  203. >
  204. {getFieldDecorator('externalTotalCost', {
  205. rules: [{ type: "number", required: true, message: '此项为必填项!' }],
  206. initialValue: theData.externalTotalCost
  207. })(
  208. <InputNumber />
  209. )}
  210. </FormItem>
  211. <FormItem className="half-item"
  212. {...formItemLayout}
  213. label="境内的外部研发费用"
  214. >
  215. {getFieldDecorator('externalAbroadCost', {
  216. rules: [{ type: "number", required: true, message: '此项为必填项!' }],
  217. initialValue: theData.externalAbroadCost
  218. })(
  219. <InputNumber />
  220. )}
  221. </FormItem>
  222. </div>
  223. <p className="activityCost-title">研发开发费用(内、外部)小计(万元)</p>
  224. <div className="clearfix activityCost-box">
  225. <FormItem className="half-item"
  226. {...formItemLayout}
  227. label="共计(万元)"
  228. >
  229. {getFieldDecorator('allCost')(
  230. <span className="number-box">
  231. {this.state.allCost}
  232. </span>
  233. )}
  234. </FormItem>
  235. <FormItem className="half-item"
  236. {...formItemLayout}
  237. label="排序号"
  238. >
  239. {getFieldDecorator('sortNumber', {
  240. rules: [{ required: true, message: '此项为必填项!' }],
  241. initialValue: theData.sortNumber
  242. })(
  243. <Input />
  244. )}
  245. </FormItem>
  246. </div>
  247. <div style={{ width: '50%', marginTop: '20px' }}>
  248. <Upload
  249. name="ratepay"
  250. action={globalConfig.context + "/api/user/cognizance/uploadActivityCost"}
  251. data={{ 'sign': 'activity_cost_account' }}
  252. beforeUpload={beforeUploadFile}
  253. fileList={this.state.fileList}
  254. onChange={(info) => {
  255. if (info.file.status !== 'uploading') {
  256. console.log(info.file, info.fileList);
  257. }
  258. if (info.file.status === 'done') {
  259. if (!info.file.response.error.length) {
  260. message.success(`${info.file.name} 文件上传成功!`);
  261. } else {
  262. message.warning(info.file.response.error[0].message);
  263. return;
  264. };
  265. this.state.accountUrl = info.file.response.data;
  266. } else if (info.file.status === 'error') {
  267. message.error(`${info.file.name} 文件上传失败。`);
  268. };
  269. this.setState({ fileList: info.fileList.slice(-1) });
  270. }}
  271. >
  272. <Button><Icon type="upload" /> 上传研发费用台账 </Button>
  273. </Upload>
  274. <p style={{ marginTop: '20px' }}>{theData.accountUrl ? <a onClick={newDownloadFile.bind(null, theData.id, 'activity_cost_account', '/api/user/cognizance/downloadActivityCost')}>{theData.accountDownloadFileName}</a> : <span><Icon type="exclamation-circle" style={{ color: '#ffbf00', marginRight: '6px' }} />未上传!</span>}</p>
  275. </div>
  276. <FormItem style={{ marginTop: '20px' }}>
  277. <Button className="set-submit" type="primary" htmlType="submit">保存</Button>
  278. <Button type="ghost" style={{ marginLeft: '20px' }} onClick={this.props.closeModal}>取消</Button>
  279. </FormItem>
  280. </Form >
  281. );
  282. },
  283. }));
  284. const ActivityDesc = React.createClass({
  285. getInitialState() {
  286. return {
  287. visible: false,
  288. loading: false
  289. };
  290. },
  291. componentWillReceiveProps(nextProps) {
  292. this.state.visible = nextProps.showDesc
  293. },
  294. showModal() {
  295. this.setState({
  296. visible: true,
  297. });
  298. },
  299. handleOk() {
  300. this.setState({
  301. visible: false,
  302. });
  303. this.props.closeDesc(false, true);
  304. },
  305. handleCancel(e) {
  306. this.setState({
  307. visible: false,
  308. });
  309. this.props.closeDesc(false);
  310. },
  311. spinChange(e) {
  312. this.setState({
  313. loading: e
  314. });
  315. },
  316. render() {
  317. return (
  318. <div className="patent-addNew">
  319. <Spin spinning={this.state.loading} className='spin-box'>
  320. <Modal title="企业研究开发费用结构明细" visible={this.state.visible}
  321. onOk={this.handleOk} onCancel={this.handleCancel}
  322. width='800px'
  323. footer=''
  324. >
  325. <ActivityDescFrom data={this.props.data}
  326. visible={this.state.visible}
  327. activityNumberList={this.props.activityNumberList}
  328. spinState={this.spinChange}
  329. closeModal={this.handleCancel}
  330. clickOk={this.handleOk} />
  331. </Modal>
  332. </Spin>
  333. </div>
  334. );
  335. },
  336. });
  337. const Activity = React.createClass({
  338. loadData(pageNo) {
  339. this.state.data = [];
  340. this.setState({
  341. loading: true
  342. });
  343. $.when($.ajax({
  344. method: "post",
  345. dataType: "json",
  346. crossDomain: false,
  347. url: globalConfig.context + "/api/user/cognizance/activityCostList",
  348. data: {
  349. pageNo: pageNo || 1,
  350. pageSize: this.state.pagination.pageSize,
  351. activityNumber: this.state.activityNumber,
  352. year: this.state.year
  353. }
  354. }), $.ajax({
  355. method: "get",
  356. dataType: "json",
  357. crossDomain: false,
  358. url: globalConfig.context + "/api/user/cognizance/activityNumber",
  359. })).done((data1, data2) => {
  360. let data = data1[0];
  361. let activityNumber = data2[0];
  362. if (!data.data || !data.data.list) {
  363. if (data.error && data.error.length) {
  364. message.warning(data.error[0].message);
  365. this.state.ButtonDisabled = true;
  366. };
  367. return;
  368. };
  369. if (!activityNumber.data) {
  370. if (activityNumber.error && activityNumber.error.length) {
  371. message.warning(activityNumber.error[0].message);
  372. this.state.ButtonDisabled = true;
  373. };
  374. return;
  375. };
  376. for (let i = 0; i < data.data.list.length; i++) {
  377. let thisdata = data.data.list[i];
  378. this.state.data.push({
  379. key: i,
  380. id: thisdata.id,
  381. uid: thisdata.uid,
  382. aid: thisdata.aid,
  383. activityNumber: thisdata.activityNumber,
  384. year: thisdata.year,
  385. startDate: thisdata.startDate,
  386. endDate: thisdata.endDate,
  387. internalAllCost:
  388. thisdata.internalLaborCost + thisdata.internalDirectCost + thisdata.internalDepreciationCost +
  389. thisdata.internalAmortizationCost + thisdata.internalAmortizationCost + thisdata.internalDesignCost +
  390. thisdata.internalEquipmentCost + thisdata.internalOtherCost,
  391. internalLaborCost: thisdata.internalLaborCost,
  392. internalDirectCost: thisdata.internalDirectCost,
  393. internalDepreciationCost: thisdata.internalDepreciationCost,
  394. internalAmortizationCost: thisdata.internalAmortizationCost,
  395. internalDesignCost: thisdata.internalDesignCost,
  396. internalEquipmentCost: thisdata.internalEquipmentCost,
  397. internalOtherCost: thisdata.internalOtherCost,
  398. externalTotalCost: thisdata.externalTotalCost,
  399. externalAbroadCost: thisdata.externalAbroadCost,
  400. allCost:
  401. thisdata.internalLaborCost + thisdata.internalDirectCost + thisdata.internalDepreciationCost +
  402. thisdata.internalAmortizationCost + thisdata.internalAmortizationCost + thisdata.internalDesignCost +
  403. thisdata.internalEquipmentCost + thisdata.internalOtherCost + thisdata.externalTotalCost,
  404. //enterpriseFiller: thisdata.enterpriseFiller,
  405. //signDate: thisdata.signDate,
  406. //signDateFormattedDate: thisdata.signDateFormattedDate,
  407. sortNumber: thisdata.sortNumber,
  408. startDateFormattedDate: thisdata.startDateFormattedDate,
  409. endDateFormattedDate: thisdata.endDateFormattedDate,
  410. accountDownloadFileName: thisdata.accountDownloadFileName,
  411. accountUrl: thisdata.accountUrl
  412. });
  413. };
  414. this.state.activityNumberList = activityNumber.data;
  415. this.state.pagination.current = data.data.pageNo;
  416. this.state.pagination.total = data.data.totalCount;
  417. this.setState({
  418. dataSource: this.state.data,
  419. pagination: this.state.pagination
  420. });
  421. }).always(function () {
  422. this.setState({
  423. loading: false
  424. });
  425. }.bind(this));
  426. },
  427. getInitialState() {
  428. return {
  429. selectedRowKeys: [],
  430. selectedRows: [],
  431. loading: false,
  432. pagination: {
  433. defaultCurrent: 1,
  434. defaultPageSize: 10,
  435. showQuickJumper: true,
  436. pageSize: 10,
  437. onChange: function (page) {
  438. this.loadData(page);
  439. }.bind(this),
  440. showTotal: function (total) {
  441. return '共' + total + '条数据';
  442. }
  443. },
  444. columns: [
  445. {
  446. title: '研发活动编号',
  447. dataIndex: 'activityNumber',
  448. key: 'activityNumber'
  449. }, {
  450. title: '费用年份',
  451. dataIndex: 'year',
  452. key: 'year'
  453. }, {
  454. title: '内部研究开发费用',
  455. dataIndex: 'internalAllCost',
  456. key: 'internalAllCost'
  457. }, {
  458. title: '人员人工费用',
  459. dataIndex: 'internalLaborCost',
  460. key: 'internalLaborCost'
  461. }, {
  462. title: '直接投入费用',
  463. dataIndex: 'internalDirectCost',
  464. key: 'internalDirectCost'
  465. }, {
  466. title: '折旧费用与长期待摊费用',
  467. dataIndex: 'internalDepreciationCost',
  468. key: 'internalDepreciationCost'
  469. }, {
  470. title: '设计费用',
  471. dataIndex: 'internalDesignCost',
  472. key: 'internalDesignCost'
  473. }, {
  474. title: '装备调试费用与试验费用',
  475. dataIndex: 'internalEquipmentCost',
  476. key: 'internalEquipmentCost'
  477. }, {
  478. title: '无形资产摊销费用',
  479. dataIndex: 'internalAmortizationCost',
  480. key: 'internalAmortizationCost'
  481. }, {
  482. title: '其他费用',
  483. dataIndex: 'internalOtherCost',
  484. key: 'internalOtherCost'
  485. }, {
  486. title: '委托外部研究开发费用',
  487. dataIndex: 'externalTotalCost',
  488. key: 'externalTotalCost'
  489. }, {
  490. title: '境内外部研发费用',
  491. dataIndex: 'externalAbroadCost',
  492. key: 'externalAbroadCost'
  493. }, {
  494. title: '研发费用合计',
  495. dataIndex: 'allCost',
  496. key: 'allCost'
  497. }, {
  498. title: '排序号',
  499. dataIndex: 'sortNumber',
  500. key: 'sortNumber'
  501. }
  502. ],
  503. dataSource: []
  504. };
  505. },
  506. componentWillMount() {
  507. this.loadData();
  508. },
  509. tableRowClick(record, index) {
  510. this.state.RowData = record;
  511. this.setState({
  512. showDesc: true
  513. });
  514. },
  515. delectRow() {
  516. let deletedIds = [];
  517. for (let idx = 0; idx < this.state.selectedRows.length; idx++) {
  518. let rowItem = this.state.selectedRows[idx];
  519. if (rowItem.id) {
  520. deletedIds.push(rowItem.id)
  521. }
  522. }
  523. this.setState({
  524. selectedRowKeys: [],
  525. loading: deletedIds.length > 0
  526. });
  527. $.ajax({
  528. method: "POST",
  529. dataType: "json",
  530. crossDomain: false,
  531. url: globalConfig.context + "/api/user/cognizance/deleteActivityCost",
  532. data: {
  533. ids: deletedIds
  534. }
  535. }).done(function (data) {
  536. if (!data.error.length) {
  537. message.success('保存成功!');
  538. this.setState({
  539. loading: false,
  540. });
  541. } else {
  542. message.warning(data.error[0].message);
  543. };
  544. this.loadData();
  545. }.bind(this));
  546. },
  547. closeDesc(e, s) {
  548. this.state.showDesc = e;
  549. if (s) {
  550. this.loadData();
  551. };
  552. },
  553. search() {
  554. this.loadData();
  555. },
  556. reset() {
  557. this.state.year = undefined;
  558. this.state.activityNumber = undefined;
  559. this.loadData();
  560. },
  561. render() {
  562. const rowSelection = {
  563. selectedRowKeys: this.state.selectedRowKeys,
  564. onChange: (selectedRowKeys, selectedRows) => {
  565. this.setState({
  566. selectedRows: selectedRows,
  567. selectedRowKeys: selectedRowKeys
  568. });
  569. }
  570. };
  571. const hasSelected = this.state.selectedRowKeys.length > 0;
  572. return (
  573. <div className="user-content" >
  574. <div className="content-title">
  575. <span>企业研究开发费用结构明细</span>
  576. </div>
  577. <div className="user-search">
  578. <Input placeholder="研发活动编号" value={this.state.activityNumber}
  579. onChange={(e) => { this.setState({ activityNumber: e.target.value }); }} />
  580. <span>年份:</span>
  581. <YearSelect value={this.state.year} handleyear={(e) => { this.state.year = e; }} />
  582. <Button type="primary" onClick={this.search}>搜索</Button>
  583. <Button onClick={this.reset}>重置</Button>
  584. <p>
  585. <Button style={{ background: "#ea0862", border: "none", color: "#fff" }}
  586. disabled={this.state.ButtonDisabled}
  587. onClick={this.tableRowClick}>添加<Icon type="plus" /></Button>
  588. <Button style={{ background: "#3fcf9e", border: "none", color: "#fff" }}
  589. disabled={!hasSelected}
  590. onClick={this.delectRow}>删除<Icon type="minus" /></Button>
  591. </p>
  592. </div>
  593. <div className="patent-table">
  594. <Spin spinning={this.state.loading}>
  595. <Table columns={this.state.columns}
  596. dataSource={this.state.dataSource}
  597. pagination={this.state.pagination}
  598. rowSelection={rowSelection}
  599. onRowClick={this.tableRowClick} />
  600. </Spin>
  601. </div>
  602. <ActivityDesc data={this.state.RowData}
  603. activityNumberList={this.state.activityNumberList}
  604. showDesc={this.state.showDesc} closeDesc={this.closeDesc} />
  605. </div >
  606. );
  607. }
  608. });
  609. export default Activity;