followUp.jsx 23 KB

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