accountlist.jsx 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821
  1. import React from "react";
  2. import $ from "jquery/src/ajax";
  3. import moment from "moment";
  4. import {
  5. Button,
  6. Form,
  7. Input,
  8. Spin,
  9. Table,
  10. Select,
  11. message,
  12. Tabs,
  13. AutoComplete,
  14. DatePicker,
  15. Modal,
  16. } from "antd";
  17. import { ChooseList } from "../../order/orderNew/chooseList";
  18. import { ShowModal, getVehicleName, getTypeName, commonAdd, dealBigMoney } from "../../../tools"
  19. import ShowModalDiv from "@/showModal.jsx";
  20. import AccountDetails from "./accountDetails";
  21. import { accountType, accountStatus } from "@/dataDic";
  22. const FormItem = Form.Item;
  23. const { RangePicker } = DatePicker;
  24. const { TabPane } = Tabs;
  25. const AccountList = React.createClass({
  26. getInitialState() {
  27. return {
  28. showDetails: false,
  29. data: {},
  30. logvisible: false,
  31. logdataSour: [],
  32. visible: "",
  33. reason: "",
  34. checkData: {},
  35. aname: "",
  36. searchValues: {}, // 列表筛选条件
  37. loading: false, //加载动画
  38. changeList: undefined, // 更改后的表格显示数据
  39. dataSource: [], // 列表数据
  40. departmentArr: [],
  41. pagination: {
  42. defaultCurrent: 1,
  43. defaultPageSize: 10,
  44. showQuickJumper: true,
  45. pageSize: 10,
  46. onChange: function (page) {
  47. this.loadData(page);
  48. }.bind(this),
  49. showTotal: function (total) {
  50. return "共" + total + "条数据";
  51. },
  52. },
  53. columns: [
  54. {
  55. title: "类型",
  56. dataIndex: "type",
  57. key: "type",
  58. width: 140,
  59. render: (text, record) => {
  60. return (
  61. <span>
  62. {text == 0 ? record.typeOther : accountType.find(item => item.value === text).label}
  63. </span>
  64. );
  65. },
  66. },
  67. {
  68. title: "报销金额(元)",
  69. dataIndex: "totalAmount",
  70. key: "totalAmount",
  71. },
  72. {
  73. title: "实报金额(元)",
  74. dataIndex: "realAmount",
  75. key: "realAmount",
  76. },
  77. {
  78. title: "报销编号",
  79. dataIndex: "checkNo",
  80. key: "checkNo",
  81. },
  82. {
  83. title: "报销至订单",
  84. dataIndex: "buyerName",
  85. key: "buyerName",
  86. render: (text, record) => {
  87. return (
  88. record.targetType == 0
  89. ? <div>固定费用</div>
  90. : <div>
  91. <div>{text || ""}</div>
  92. <div>{record.contractNo || ""}</div>
  93. </div>
  94. );
  95. },
  96. },
  97. {
  98. title: "报销至部门",
  99. dataIndex: "applyDepName",
  100. key: "applyDepName",
  101. render: (text, record) => {
  102. return (
  103. <span>{record.targetType == 0 && text}</span>
  104. );
  105. },
  106. },
  107. {
  108. title: "报销人",
  109. dataIndex: "aname",
  110. key: "aname",
  111. },
  112. {
  113. title: "财务负责人",
  114. dataIndex: "financeName",
  115. key: "financeName",
  116. },
  117. {
  118. title: "状态",
  119. dataIndex: "status",
  120. key: "status",
  121. render: (text, record) => {
  122. return (
  123. <span style={{ color: accountStatus[text].color }}>
  124. {accountStatus[text].label}
  125. </span>
  126. );
  127. },
  128. },
  129. {
  130. title: "报销公司/支付公司",
  131. dataIndex: "payDepName",
  132. key: "payDepName",
  133. render: (text, record) => {
  134. return (
  135. <div>
  136. <div>{record.applyDepName || ""}</div>
  137. <div>{text || ""}</div>
  138. </div>
  139. );
  140. },
  141. },
  142. {
  143. title: "报销时间",
  144. dataIndex: "createTimeStr",
  145. key: "createTimeStr",
  146. },
  147. {
  148. title: "操作",
  149. dataIndex: "operate",
  150. key: "operate",
  151. render: (text, record) => {
  152. return (
  153. <div>
  154. <div>
  155. {this.props.isOperate &&
  156. <Button type="primary"
  157. style={{ margin: 4 }}
  158. onClick={() => { this.download(record.attachmentUrl) }}
  159. >下载</Button>}
  160. {this.props.isOperate && record.examine == 1 &&
  161. <Button type="primary"
  162. style={{ margin: 4 }}
  163. onClick={(e) => {
  164. e.stopPropagation();
  165. this.setState({
  166. visible: "adopt",
  167. checkData: record,
  168. })
  169. }}
  170. >同意</Button>}
  171. {this.props.isOperate && record.examine == 1 &&
  172. <Button type="danger"
  173. style={{ margin: 4 }}
  174. onClick={(e) => {
  175. e.stopPropagation();
  176. this.setState({
  177. visible: "reject",
  178. checkData: record,
  179. })
  180. }}
  181. >驳回</Button>}
  182. {record.status != 0 && <Button
  183. style={{ margin: 4 }}
  184. onClick={() => {
  185. this.setState({
  186. logvisible: true
  187. })
  188. this.getLogData(record.mainId || record.id)
  189. }}>日志</Button>}
  190. </div>
  191. </div>
  192. )
  193. }
  194. },
  195. ],
  196. logcolumns: [
  197. {
  198. title: "审核人",
  199. dataIndex: "auditorName",
  200. key: "auditorName"
  201. },
  202. {
  203. title: "操作",
  204. dataIndex: "status",
  205. key: "status",
  206. width: 120,
  207. render: (text, record) => {
  208. return (
  209. <span style={{ color: ["#1D4FEA", "#34DE38", "#108EE9", "red", "#808080", "#1D4FEA"][text] }}>
  210. {["【发起】", "【通过】", "【完成】", "【驳回】", "【撤销】", "【修改】"][text]}
  211. {this.state.processStatus == record.processStatus && !record.id &&
  212. <span style={{ color: "#FFA500" }}>&nbsp;审核中...</span>}
  213. </span>
  214. );
  215. },
  216. },
  217. {
  218. title: "操作时间",
  219. dataIndex: "createTimeStr",
  220. key: "createTimeStr",
  221. width: 88,
  222. },
  223. {
  224. title: "备注",
  225. dataIndex: "remarks",
  226. key: "remarks",
  227. render: (text, record) => {
  228. return (
  229. <div style={{ minWidth: 250 }}>{text}</div>
  230. )
  231. }
  232. }
  233. ],
  234. };
  235. },
  236. componentWillMount() {
  237. this.departmentList();
  238. this.loadData();
  239. },
  240. // 列表接口
  241. loadData(pageNo) {
  242. const { searchValues, pagination } = this.state;
  243. this.setState({
  244. loading: true,
  245. });
  246. let datas = Object.assign(searchValues, {
  247. pageNo: pageNo || 1,
  248. pageSize: pagination.pageSize,
  249. expenseMain: 0,
  250. processStatus: this.props.isOperate ? 1 : 2,
  251. });
  252. $.ajax({
  253. method: "get",
  254. dataType: "json",
  255. crossDomain: false,
  256. url: globalConfig.context + "/api/admin/expenseAccount/pageList",
  257. data: datas,
  258. success: function (data) {
  259. ShowModal(this);
  260. this.setState({
  261. loading: false,
  262. });
  263. if (data.error && data.error.length === 0) {
  264. if (data.data.list) {
  265. pagination.current = data.data.pageNo;
  266. pagination.total = data.data.totalCount;
  267. if (data.data && data.data.list && !data.data.list.length) {
  268. pagination.current = 0;
  269. pagination.total = 0;
  270. }
  271. this.setState({
  272. dataSource: data.data.list,
  273. pagination: this.state.pagination,
  274. pageNo: data.data.pageNo,
  275. totalAmount: data.data.totalAmount,
  276. });
  277. } else {
  278. this.setState({
  279. dataSource: data.data,
  280. pagination: false,
  281. });
  282. }
  283. } else {
  284. message.warning(data.error[0].message);
  285. }
  286. }.bind(this),
  287. }).always(
  288. function () {
  289. this.setState({
  290. loading: false,
  291. });
  292. }.bind(this)
  293. );
  294. },
  295. // 日志
  296. getLogData(eaid) {
  297. $.ajax({
  298. method: "get",
  299. dataType: "json",
  300. crossDomain: false,
  301. url: globalConfig.context + "/api/admin/expenseAccount/log/list",
  302. data: { eaid },
  303. success: function (data) {
  304. if (data.error.length === 0) {
  305. this.setState({
  306. logdataSour: data.data || []
  307. });
  308. this.isHere(data.data || [])
  309. } else {
  310. message.warning(data.error[0].message);
  311. }
  312. }.bind(this)
  313. }).always(
  314. function () {
  315. }.bind(this)
  316. );
  317. },
  318. //
  319. isHere(list = []) {
  320. for (var i = 0; i < list.length; i++) {
  321. if (!list[i].id) {
  322. this.setState({
  323. processStatus: list[i].processStatus
  324. })
  325. return
  326. }
  327. }
  328. },
  329. download(urls) {
  330. if (!urls) {
  331. message.error("暂无可下载的附件!");
  332. } else {
  333. let list = urls.split(',') || []
  334. list.forEach(e => {
  335. var aLink = document.createElement('a');
  336. aLink.download = e;
  337. aLink.href = globalConfig.context + `/open/download?fileName=${e}&delete=false`;
  338. document.body.appendChild(aLink);
  339. aLink.click();
  340. document.body.removeChild(aLink);
  341. });
  342. }
  343. },
  344. departmentList() {
  345. $.ajax({
  346. method: "get",
  347. dataType: "json",
  348. crossDomain: false,
  349. url: globalConfig.context + "/api/admin/organization/selectSuperId",
  350. data: {},
  351. success: function (data) {
  352. let thedata = data.data;
  353. let theArr = [];
  354. if (!thedata) {
  355. if (data.error && data.error.length) {
  356. message.warning(data.error[0].message);
  357. }
  358. } else {
  359. thedata.map(function (item, index) {
  360. theArr.push({
  361. key: index,
  362. name: item.name,
  363. id: item.id
  364. });
  365. });
  366. }
  367. this.setState({
  368. departmentArr: theArr
  369. });
  370. }.bind(this)
  371. }).always(
  372. function () {
  373. }.bind(this)
  374. );
  375. },
  376. // 审核
  377. toExamine(num) {
  378. const { checkData, reason } = this.state
  379. if (!reason) {
  380. message.warning("请填写审核说明~");
  381. return;
  382. }
  383. this.setState({
  384. loading: true,
  385. });
  386. $.ajax({
  387. method: "POST",
  388. dataType: "json",
  389. crossDomain: false,
  390. url: globalConfig.context + "/api/admin/expenseAccount/examine",
  391. data: {
  392. id: checkData.id,
  393. reason,
  394. status: num,//1同意 3驳回
  395. },
  396. }).done(
  397. function (data) {
  398. if (!data.error.length) {
  399. message.success("审核成功!");
  400. this.setState({
  401. visible: "",
  402. reason: "",
  403. showDetails: false,
  404. checkData: {},
  405. });
  406. this.loadData()
  407. } else {
  408. message.warning(data.error[0].message);
  409. }
  410. }.bind(this)
  411. );
  412. },
  413. tableRowClick(e) {
  414. this.setState({
  415. showDetails: true,
  416. id: e.id,
  417. })
  418. // this.getDetails(e.id)
  419. },
  420. // 查询负责人
  421. followUp(e) {
  422. this.setState({
  423. aname: e
  424. });
  425. $.ajax({
  426. method: "get",
  427. dataType: "json",
  428. crossDomain: false,
  429. url: globalConfig.context + "/api/admin/customer/listAdminByName",
  430. data: {
  431. adminName: e,
  432. },
  433. success: function (data) {
  434. let thedata = data.data || [];
  435. if (!thedata) {
  436. if (data.error && data.error.length) {
  437. message.warning(data.error[0].message);
  438. }
  439. thedata = {};
  440. }
  441. this.setState({
  442. fjlist: thedata,
  443. });
  444. }.bind(this),
  445. }).always(
  446. function () {
  447. this.setState({
  448. loading: false,
  449. });
  450. }.bind(this)
  451. );
  452. },
  453. // 选中负责人
  454. selectF(value) {
  455. const { searchValues, fjlist } = this.state;
  456. const newdataSources = JSON.stringify(fjlist) == "{}" ? [] : fjlist;
  457. this.setState({
  458. searchValues: Object.assign(searchValues, {
  459. aid: newdataSources.find((item) => item.name == value).id,
  460. }),
  461. });
  462. },
  463. // 搜索
  464. search() {
  465. this.loadData();
  466. },
  467. // 重置
  468. reset() {
  469. this.setState({
  470. aname: "",
  471. searchValues: JSON.parse(JSON.stringify({})),
  472. }, () => {
  473. this.loadData();
  474. })
  475. },
  476. changeList(arr) {
  477. const newArr = [];
  478. this.state.columns.forEach((item) => {
  479. arr.forEach((val) => {
  480. if (val === item.title) {
  481. newArr.push(item);
  482. }
  483. });
  484. });
  485. this.setState({
  486. changeList: newArr,
  487. });
  488. },
  489. render() {
  490. const { TextArea } = Input
  491. const { searchValues, visible, } = this.state
  492. const formItemLayout = {
  493. labelCol: { span: 5 },
  494. wrapperCol: { span: 18 },
  495. };
  496. const dataSources = this.state.fjlist || [];
  497. const options = dataSources.map((group) => (
  498. <Select.Option key={group.id} value={group.name}>
  499. {group.name}
  500. </Select.Option>
  501. ));
  502. return (
  503. <div className="user-content">
  504. <ShowModalDiv ShowModal={this.state.showModal} onClose={() => { this.setState({ showModal: false }) }} />
  505. <div className="content-title" style={{ marginBottom: 10 }}>
  506. <span style={{ fontWeight: 900, fontSize: 16 }}>费用单列表</span>
  507. </div>
  508. <Tabs defaultActiveKey="2" className="test">
  509. <TabPane tab="搜索" key="2">
  510. <div className="user-search" style={{ marginLeft: 10 }}>
  511. <Input
  512. placeholder="合同编号"
  513. value={searchValues["contractNo"]
  514. ? searchValues["contractNo"]
  515. : ""}
  516. onChange={(e) => {
  517. searchValues["contractNo"] = e.target.value;
  518. this.setState({
  519. searchValues: searchValues,
  520. });
  521. }}
  522. />
  523. <Input
  524. placeholder="客户名称"
  525. value={searchValues["username"]
  526. ? searchValues["username"]
  527. : ""}
  528. onChange={(e) => {
  529. searchValues["username"] = e.target.value;
  530. this.setState({
  531. searchValues: searchValues,
  532. });
  533. }}
  534. />
  535. <Select
  536. style={{ width: 140 }}
  537. placeholder="报销类型"
  538. value={searchValues["type"]
  539. ? searchValues["type"]
  540. : undefined}
  541. onChange={(e) => {
  542. searchValues["type"] = e;
  543. this.setState({
  544. searchValues: searchValues,
  545. });
  546. }}
  547. >
  548. <Option value="1">差旅费</Option>
  549. <Option value="2">非业务报销</Option>
  550. <Option value="3">第三方付款</Option>
  551. <Option value="4">申请借支</Option>
  552. <Option value="5">申请抵扣</Option>
  553. <Option value="0">其他</Option>
  554. </Select>
  555. <AutoComplete
  556. className="certain-category-search"
  557. dropdownClassName="certain-category-search-dropdown"
  558. dropdownMatchSelectWidth={false}
  559. style={{ width: 140 }}
  560. dataSource={options}
  561. placeholder="报销人"
  562. value={this.state.aname}
  563. onChange={this.followUp.bind(this)}
  564. filterOption={true}
  565. onSelect={this.selectF.bind(this)}
  566. >
  567. <Input />
  568. </AutoComplete>
  569. <Select
  570. placeholder="所属部门"
  571. style={{ width: 200, marginRight: 10 }}
  572. value={searchValues["depId"]
  573. ? searchValues["depId"]
  574. : undefined}
  575. onChange={e => {
  576. searchValues["depId"] = e;
  577. this.setState({
  578. searchValues: searchValues,
  579. });
  580. }}
  581. >
  582. {this.state.departmentArr.map(function (item) {
  583. return <Select.Option key={item.id}>{item.name}</Select.Option>;
  584. })}
  585. </Select>
  586. <Select
  587. placeholder="申请部门"
  588. style={{ width: 200, marginRight: 10 }}
  589. value={searchValues["applyDep"]
  590. ? searchValues["applyDep"]
  591. : undefined}
  592. onChange={e => {
  593. searchValues["applyDep"] = e;
  594. this.setState({
  595. searchValues: searchValues,
  596. });
  597. }}
  598. >
  599. {this.state.departmentArr.map(function (item) {
  600. return <Select.Option key={item.id}>{item.name}</Select.Option>;
  601. })}
  602. </Select>
  603. <Select
  604. placeholder="支付部门"
  605. style={{ width: 200, marginRight: 10 }}
  606. value={searchValues["payDep"]
  607. ? searchValues["payDep"]
  608. : undefined}
  609. onChange={e => {
  610. searchValues["payDep"] = e;
  611. this.setState({
  612. searchValues: searchValues,
  613. });
  614. }}
  615. >
  616. {this.state.departmentArr.map(function (item) {
  617. return <Select.Option key={item.id}>{item.name}</Select.Option>;
  618. })}
  619. </Select>
  620. <Select
  621. style={{ width: 140 }}
  622. placeholder="审核状态"
  623. value={searchValues["status"]
  624. ? searchValues["status"]
  625. : undefined}
  626. onChange={(e) => {
  627. searchValues["status"] = e;
  628. this.setState({
  629. searchValues: searchValues,
  630. });
  631. }}
  632. >
  633. <Option value="0">未提交</Option>
  634. <Option value="1">待审核</Option>
  635. <Option value="2">已审核</Option>
  636. <Option value="3">已驳回</Option>
  637. <Option value="4">已删除</Option>
  638. </Select>
  639. <Input
  640. placeholder="报销编号"
  641. value={searchValues["checkNo"]
  642. ? searchValues["checkNo"]
  643. : ""}
  644. onChange={(e) => {
  645. searchValues["checkNo"] = e.target.value;
  646. this.setState({
  647. searchValues: searchValues,
  648. });
  649. }}
  650. />
  651. <div style={{ marginTop: 10 }}>
  652. <span>报销时间:</span>
  653. <RangePicker
  654. style={{ width: 300 }}
  655. value={[
  656. searchValues.startTime ? moment(searchValues.startTime) : null,
  657. searchValues.endTime ? moment(searchValues.endTime) : null,
  658. ]}
  659. onChange={(data, dataString) => {
  660. this.setState({
  661. searchValues: Object.assign(searchValues, {
  662. startTime: dataString[0],
  663. endTime: dataString[1],
  664. }),
  665. });
  666. }}
  667. />
  668. <Button
  669. type="primary"
  670. onClick={this.search}
  671. style={{ margin: "0 10px" }}
  672. >
  673. 搜索
  674. </Button>
  675. <Button onClick={this.reset}>重置</Button>
  676. </div>
  677. </div>
  678. </TabPane>
  679. <TabPane tab="更改表格显示数据" key="1">
  680. <div style={{ marginLeft: 10 }}>
  681. <ChooseList
  682. columns={this.state.columns}
  683. changeFn={this.changeList}
  684. changeList={this.state.changeList}
  685. top={55}
  686. margin={11}
  687. />
  688. </div>
  689. </TabPane>
  690. </Tabs>
  691. <div className="patent-table">
  692. <Spin spinning={this.state.loading}>
  693. <Table
  694. bordered
  695. columns={
  696. this.state.changeList == undefined
  697. ? this.state.columns
  698. : this.state.changeList
  699. }
  700. dataSource={this.state.dataSource}
  701. pagination={this.state.pagination}
  702. // onRowDoubleClick={this.tableRowClick.bind(this)}
  703. size="small"
  704. />
  705. </Spin>
  706. <p
  707. style={{ display: "inline-block", fontSize: "14px", color: "red" }}
  708. >
  709. {
  710. <span style={{ marginRight: 10 }}>
  711. {`金额总计(元):${this.state.totalAmount}`}
  712. </span>
  713. }
  714. </p>
  715. </div>
  716. {
  717. //审核弹窗
  718. this.state.visible != "" &&
  719. <Modal
  720. width="400px"
  721. maskClosable={false}
  722. title="审核"
  723. confirmLoading={this.state.loading}
  724. visible={this.state.visible != ""}
  725. onOk={() => { this.toExamine(visible == "adopt" ? 1 : visible == "reject" && 3) }}
  726. okText={this.state.visible == "adopt" ? "通过" : this.state.visible == "reject" && "驳回"}
  727. onCancel={() => {
  728. this.setState({
  729. visible: '',
  730. reason: "",
  731. checkData: {},
  732. })
  733. }}
  734. >
  735. <div style={{ width: "90%", margin: "0 auto" }}>
  736. <TextArea
  737. rows={4}
  738. value={this.state.reason}
  739. onChange={(e) => {
  740. this.setState({
  741. reason: e.target.value,
  742. })
  743. }}
  744. placeholder="请填写审核内容"
  745. />
  746. </div>
  747. </Modal>
  748. }
  749. {
  750. this.state.showDetails &&
  751. <AccountDetails
  752. showDetails={this.state.showDetails}
  753. id={this.state.id}
  754. isOperate={this.props.isOperate}
  755. onCancel={() => { this.setState({ showDetails: false }) }}
  756. />
  757. }
  758. {
  759. // 审核日志
  760. this.state.logvisible &&
  761. <Modal
  762. visible={this.state.logvisible}
  763. className="admin-desc-content"
  764. width="800px"
  765. maskClosable={false}
  766. title="审核日志"
  767. footer={null}
  768. onCancel={() => {
  769. this.setState({
  770. logvisible: false,
  771. })
  772. }}
  773. >
  774. <div className="patent-table">
  775. <Spin spinning={this.state.loading}>
  776. <Table
  777. columns={this.state.logcolumns}
  778. dataSource={this.state.logdataSour}
  779. pagination={false}
  780. bordered
  781. size="small"
  782. />
  783. </Spin>
  784. </div>
  785. </Modal>
  786. }
  787. </div>
  788. );
  789. },
  790. });
  791. export default AccountList;