followUp.jsx 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573
  1. import React,{Component} from "react";
  2. import {Button, DatePicker, Icon, Input, message, Select, Spin, Table, Tabs, Tag, Tooltip} from "antd";
  3. import {ChooseList} from "../../order/orderNew/chooseList";
  4. import FollowUpDetails from './followUpDetails';
  5. import CorrespondingDetails from './correspondingDetails';
  6. import $ from "jquery";
  7. import {ShowModal} from "@/tools";
  8. import ShowModalDiv from "@/showModal.jsx";
  9. import moment from "moment";
  10. const {TabPane} = Tabs;
  11. const { RangePicker } = DatePicker;
  12. class FollowUp extends Component{
  13. constructor(props) {
  14. super(props);
  15. this.state={
  16. columns:[
  17. {
  18. title: "合同编号",
  19. dataIndex: "contractNo",
  20. key: "contractNo",
  21. width: 120,
  22. fixed:'left',
  23. },
  24. {
  25. title: "订单编号",
  26. dataIndex: "orderNo",
  27. key: "orderNo",
  28. width: 140,
  29. fixed:'left',
  30. },
  31. {
  32. title: "状态",
  33. dataIndex: "deleteSign",
  34. key: "deleteSign",
  35. width:90,
  36. fixed:'left',
  37. render: (text) => {
  38. //0=正常, 1=作废, 2=锁定, 3=变更中
  39. return <Tag color="#f50">{
  40. text === 0 ? '正常' :
  41. text === 1 ? '作废' :
  42. text === 2 ? '锁定' :
  43. text === 3 ? '变更中' : '未知'
  44. }</Tag>
  45. }
  46. },
  47. {
  48. title: "订单部门",
  49. dataIndex: "depName",
  50. key: "depName",
  51. width: 130,
  52. fixed:'left',
  53. },
  54. {
  55. title: "客户名称",
  56. dataIndex: "userName",
  57. key: "userName",
  58. width:120,
  59. fixed:'left',
  60. },
  61. {
  62. title: "合同签订时间",
  63. dataIndex: "signTimes",
  64. key: "signTimes",
  65. },
  66. {
  67. title: "下单时间",
  68. dataIndex: "orderTimes",
  69. key: "orderTimes",
  70. },
  71. {
  72. title: "申报项目",
  73. dataIndex: "projects",
  74. key: "projects",
  75. width: 80,
  76. render: (text) => {
  77. return (
  78. <Tooltip placement="topLeft" title={text}>
  79. <div style={{
  80. maxWidth:'80px',
  81. overflow:'hidden',
  82. textOverflow: "ellipsis",
  83. whiteSpace:'nowrap',
  84. }}>{text}</div>
  85. </Tooltip>
  86. )
  87. }
  88. },
  89. {
  90. title: "咨询师",
  91. dataIndex: "consultants",
  92. key: "consultants",
  93. width: 80,
  94. render: (text) => {
  95. return (
  96. <Tooltip placement="topLeft" title={text}>
  97. <div style={{
  98. maxWidth:'80px',
  99. overflow:'hidden',
  100. textOverflow: "ellipsis",
  101. whiteSpace:'nowrap',
  102. }}>{text}</div>
  103. </Tooltip>
  104. )
  105. }
  106. },
  107. {
  108. title: "申报批次",
  109. dataIndex: "declareBatchs",
  110. key: "declareBatchs",
  111. width: 80,
  112. render: (text) => {
  113. return (
  114. <Tooltip placement="topLeft" title={text}>
  115. <div style={{
  116. maxWidth:'80px',
  117. overflow:'hidden',
  118. textOverflow: "ellipsis",
  119. whiteSpace:'nowrap',
  120. }}>{text}</div>
  121. </Tooltip>
  122. )
  123. }
  124. },
  125. {
  126. title: "证书编号",
  127. dataIndex: "certificationNos",
  128. key: "certificationNos",
  129. width: 80,
  130. render: (text) => {
  131. return (
  132. <Tooltip placement="topLeft" title={text}>
  133. <div style={{
  134. maxWidth:'80px',
  135. overflow:'hidden',
  136. textOverflow: "ellipsis",
  137. whiteSpace:'nowrap',
  138. }}>{text}</div>
  139. </Tooltip>
  140. )
  141. }
  142. },
  143. {
  144. title: "客服最新跟进",
  145. dataIndex: "newTimes",
  146. key: "newTimes",
  147. },
  148. {
  149. title: "跟进客服",
  150. dataIndex: "adminName",
  151. key: "adminName",
  152. },
  153. {
  154. title: "是否已添微信",
  155. dataIndex: "addWechat",
  156. key: "addWechat",
  157. width: 100,
  158. render: (text,record) => {
  159. let str = text === 1 ? '是('+record.wechat+')' : text === 0 ? '否' : '未知';
  160. return (
  161. <Tooltip placement="topLeft" title={str}>
  162. <div style={{
  163. maxWidth:'100px',
  164. overflow:'hidden',
  165. textOverflow: "ellipsis",
  166. whiteSpace:'nowrap',
  167. }}>{str}</div>
  168. </Tooltip>
  169. )
  170. }
  171. },
  172. {
  173. title: "续签情况",
  174. dataIndex: "renewal",
  175. key: "renewal",
  176. width: 80,
  177. render: (text,record) => {
  178. let str = text === 0 ? '其他' :
  179. text === 1 ? '否,企业已签其他机构' :
  180. text === 2 ? '否,企业自己申报' :
  181. text === 3 ? '否,企业不打算申报/注销' :
  182. text === 4 ? '否,客户考虑中,无报价' :
  183. text === 5 ? '否,客户考虑中,已报价' :
  184. text === 6 ? '是,已续签/复审,续签时间、续签项目('+record.renewalTimes+')' : '未知'
  185. return (
  186. <Tooltip placement="topLeft" title={str}>
  187. <div style={{
  188. maxWidth:'80px',
  189. overflow:'hidden',
  190. textOverflow: "ellipsis",
  191. whiteSpace:'nowrap',
  192. }}>{str}</div>
  193. </Tooltip>
  194. )
  195. }
  196. },
  197. {
  198. title: "备注",
  199. dataIndex: "remarks",
  200. key: "remarks",
  201. width: 80,
  202. render: (text) => {
  203. return (
  204. <Tooltip placement="topLeft" title={text}>
  205. <div style={{
  206. maxWidth:'80px',
  207. overflow:'hidden',
  208. textOverflow: "ellipsis",
  209. whiteSpace:'nowrap',
  210. }}>{text}</div>
  211. </Tooltip>
  212. )
  213. }
  214. },
  215. {
  216. title: "操作",
  217. dataIndex: "a",
  218. key: "a",
  219. width: 100,
  220. render: (_,record) => {
  221. if(record.projects){
  222. let projectsArr = record.projects.split('/');
  223. let consultantsArr = record.consultants.split('/');
  224. let declareBatchsArr = record.declareBatchs.split('/');
  225. let certificationNosArr = record.certificationNos.split('/');
  226. let data = [];
  227. for (let i in projectsArr){
  228. data.push({
  229. project:projectsArr[i],
  230. consultant:consultantsArr[i],
  231. declareBatch:declareBatchsArr[i],
  232. certificationNo:certificationNosArr[i],
  233. })
  234. }
  235. return (
  236. <Button type="primary" onClick={(e)=>{
  237. e.stopPropagation();
  238. this.setState({
  239. detailsVisible:true,
  240. detailsInfor:data
  241. })
  242. }}>查看项目</Button>
  243. )
  244. }
  245. }
  246. },
  247. ],
  248. changeList:[],
  249. listLoading:false,
  250. page:1,
  251. pagination: {
  252. defaultCurrent: 1,
  253. defaultPageSize: 10,
  254. showQuickJumper: true,
  255. pageSize: 10,
  256. onChange: function (page) {
  257. this.loadData(page);
  258. }.bind(this),
  259. showTotal: function (total) {
  260. return "共" + total + "条数据";
  261. },
  262. },
  263. departmentArr:[],
  264. customerName:'',
  265. releaseDate:[],
  266. signTimes:[],
  267. }
  268. this.changeList = this.changeList.bind(this);
  269. this.loadData = this.loadData.bind(this);
  270. this.search = this.search.bind(this);
  271. this.reset = this.reset.bind(this);
  272. this.departmentList = this.departmentList.bind(this);
  273. }
  274. componentDidMount() {
  275. this.departmentList();
  276. this.loadData();
  277. }
  278. search(){
  279. this.loadData();
  280. }
  281. reset(){
  282. this.setState({
  283. customerName:undefined,
  284. depId:undefined,
  285. addWechat:undefined,
  286. renewal:undefined,
  287. releaseDate:[],
  288. signTimes:[],
  289. },()=>{
  290. this.loadData();
  291. })
  292. }
  293. loadData(pageNo) {
  294. this.setState({
  295. listLoading: true,
  296. });
  297. $.ajax({
  298. method: "get",
  299. dataType: "json",
  300. crossDomain: false,
  301. url: globalConfig.context + "/api/admin/listOrderUseService",
  302. data: {
  303. pageNo: pageNo || 1,
  304. pageSize: this.state.pagination.pageSize,
  305. userName:this.state.customerName || undefined,
  306. depId:this.state.depId || undefined,
  307. addWechat:this.state.addWechat || undefined,
  308. renewal:this.state.renewal || undefined,
  309. startFollowTimes:this.state.releaseDate[0] || undefined,
  310. endFollowTimes:this.state.releaseDate[1] || undefined,
  311. startSignTimes:this.state.signTimes[0] || undefined,
  312. endSignTimes:this.state.signTimes[1] || undefined,
  313. },
  314. success: function (data) {
  315. ShowModal(this);
  316. let theArr = [];
  317. if (!data.data || !data.data.list) {
  318. if (data.error && data.error.length) {
  319. message.warning(data.error[0].message);
  320. }
  321. } else {
  322. for (let i = 0; i < data.data.list.length; i++) {
  323. let thisdata = data.data.list[i];
  324. theArr.push(thisdata);
  325. }
  326. this.state.pagination.current = data.data.pageNo;
  327. this.state.pagination.total = data.data.totalCount;
  328. if (data.data && data.data.list && !data.data.list.length) {
  329. this.state.pagination.current = 0;
  330. this.state.pagination.total = 0;
  331. }
  332. this.setState({
  333. dataSource: theArr,
  334. page: data.data.pageNo,
  335. pagination: this.state.pagination,
  336. });
  337. }
  338. }.bind(this),
  339. }).always(
  340. function () {
  341. this.setState({
  342. listLoading: false,
  343. });
  344. }.bind(this)
  345. );
  346. }
  347. changeList(arr) {
  348. const newArr = [];
  349. this.state.columns.forEach(item => {
  350. arr.forEach(val => {
  351. if (val === item.title) {
  352. newArr.push(item);
  353. }
  354. });
  355. });
  356. this.setState({
  357. changeList: newArr
  358. });
  359. }
  360. //部门
  361. departmentList() {
  362. $.ajax({
  363. method: "get",
  364. dataType: "json",
  365. crossDomain: false,
  366. url: globalConfig.context + "/api/admin/organization/selectSuperId",
  367. data: {},
  368. success: function (data) {
  369. let thedata = data.data;
  370. let theArr = [];
  371. if (!thedata) {
  372. if (data.error && data.error.length) {
  373. message.warning(data.error[0].message);
  374. }
  375. } else {
  376. thedata.map(function (item, index) {
  377. theArr.push({
  378. key: index,
  379. name: item.name,
  380. id: item.id,
  381. });
  382. });
  383. }
  384. this.setState({
  385. departmentArr: theArr,
  386. });
  387. }.bind(this),
  388. }).always(
  389. function () {
  390. }.bind(this)
  391. );
  392. }
  393. download() {
  394. window.location.href =
  395. globalConfig.context +
  396. "/api/admin/userServiceExport"
  397. }
  398. render() {
  399. return (
  400. <div className="user-content">
  401. <ShowModalDiv ShowModal={this.state.showModal} />
  402. <div className="content-title">
  403. <span>客服跟进详情</span>
  404. </div>
  405. <Tabs defaultActiveKey="1" className="test">
  406. <TabPane tab="搜索" key="1" style={{padding:'10px 0'}}>
  407. <Input
  408. placeholder="客户名称"
  409. style={{ width: "150px", marginRight: 10,marginBottom: "10px" }}
  410. value={this.state.customerName}
  411. onChange={(e) => {
  412. this.setState({ customerName: e.target.value });
  413. }}
  414. />
  415. <Select
  416. placeholder="订单部门"
  417. style={{ width: 150, marginRight: 10,marginBottom: "10px" }}
  418. value={this.state.depId}
  419. onChange={(e) => {
  420. this.setState({ depId: e });
  421. }}
  422. >
  423. {this.state.departmentArr.map(function (item) {
  424. return <Option key={item.id}>{item.name}</Option>;
  425. })}
  426. </Select>
  427. <Select
  428. placeholder="是否已添微信"
  429. style={{ width: 150, marginRight: 10,marginBottom: "10px" }}
  430. value={this.state.addWechat}
  431. onChange={(e) => {
  432. this.setState({ addWechat: e });
  433. }}
  434. >
  435. <Option value={0}>否</Option>
  436. <Option value={1}>是</Option>
  437. </Select>
  438. <Select
  439. placeholder="续签情况"
  440. style={{ width: 250, marginRight: 10,marginBottom: "10px" }}
  441. value={this.state.renewal}
  442. onChange={(e) => {
  443. this.setState({ renewal: e });
  444. }}
  445. >
  446. <Option value={6}>是,已续签/复审,续签时间、续签项目</Option>
  447. <Option value={5}>否,客户考虑中,已报价</Option>
  448. <Option value={4}>否,客户考虑中,无报价</Option>
  449. <Option value={3}>否,企业不打算申报/注销</Option>
  450. <Option value={2}>否,企业自己申报</Option>
  451. <Option value={1}>否,企业已签其他机构</Option>
  452. <Option value={0}>其他</Option>
  453. </Select>
  454. <span style={{ marginRight: "10px",marginBottom: "10px" }}>跟进时间 :</span>
  455. <RangePicker
  456. style={{marginBottom: "10px",width:'187px'}}
  457. value={[
  458. this.state.releaseDate[0]
  459. ? moment(this.state.releaseDate[0])
  460. : null,
  461. this.state.releaseDate[1]
  462. ? moment(this.state.releaseDate[1])
  463. : null,
  464. ]}
  465. onChange={(data, dataString) => {
  466. this.setState({ releaseDate: dataString });
  467. }}
  468. />
  469. <span style={{ marginRight: "10px",marginLeft: "10px",marginBottom: "10px" }}>下单时间 :</span>
  470. <RangePicker
  471. style={{marginBottom: "10px",width:'187px'}}
  472. value={[
  473. this.state.signTimes[0]
  474. ? moment(this.state.signTimes[0])
  475. : null,
  476. this.state.signTimes[1]
  477. ? moment(this.state.signTimes[1])
  478. : null,
  479. ]}
  480. onChange={(data, dataString) => {
  481. this.setState({ signTimes: dataString });
  482. }}
  483. />
  484. <Button
  485. type="primary"
  486. onClick={this.search}
  487. style={{ marginLeft: "10px",marginBottom: "10px" }}
  488. >
  489. 搜索
  490. <Icon type="search" />
  491. </Button>
  492. <Button onClick={this.reset} style={{ marginLeft: "10px",marginBottom: "10px" }}>
  493. 重置 <Icon type="reload" />
  494. </Button>
  495. </TabPane>
  496. <TabPane tab="更改表格显示数据" key="2">
  497. <div style={{ marginLeft: 10 }}>
  498. <ChooseList
  499. columns={this.state.columns}
  500. changeFn={this.changeList}
  501. changeList={this.state.changeList}
  502. top={55}
  503. margin={11}
  504. />
  505. </div>
  506. </TabPane>
  507. <TabPane tab="操作" key="3">
  508. <Button
  509. type="primary"
  510. style={{margin: '10px'}}
  511. onClick={this.download}
  512. >
  513. 导出
  514. </Button>
  515. </TabPane>
  516. </Tabs>
  517. <div className="patent-table">
  518. <Spin spinning={this.state.listLoading}>
  519. <Table
  520. columns={this.state.columns}
  521. dataSource={this.state.dataSource}
  522. pagination={this.state.pagination}
  523. scroll={{ x: "max-content", y: 0 }}
  524. onRowClick={(record)=>{
  525. this.setState({
  526. visible:true,
  527. orderNo:record.orderNo,
  528. uid:record.uid,
  529. })
  530. }}
  531. />
  532. </Spin>
  533. </div>
  534. {this.state.visible ? <FollowUpDetails
  535. visible={this.state.visible}
  536. orderNo={this.state.orderNo}
  537. uid={this.state.uid}
  538. onCancel={()=>{
  539. this.setState({
  540. visible:false,
  541. orderNo:'',
  542. uid:'',
  543. })
  544. }}/> : ''}
  545. {this.state.detailsVisible ?
  546. <CorrespondingDetails
  547. visible={this.state.detailsVisible}
  548. detailsInfor={this.state.detailsInfor}
  549. onCancel={()=>{
  550. this.setState({
  551. detailsVisible:false,
  552. detailsInfor:[],
  553. })
  554. }}/> : ''}
  555. </div>
  556. )
  557. }
  558. }
  559. export default FollowUp;