channel.jsx 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066
  1. import React,{Component} from "react";
  2. import {
  3. AutoComplete,
  4. Button,
  5. Cascader,
  6. DatePicker,
  7. Input,
  8. message,
  9. Select,
  10. Spin,
  11. Table,
  12. Tabs,
  13. Tooltip,
  14. Upload,
  15. Modal, Tag
  16. } from "antd";
  17. import {ChooseList} from "../../../order/orderNew/chooseList";
  18. import $ from "jquery/src/ajax";
  19. import {
  20. getSocialAttribute,
  21. ShowModal,
  22. getChannelAllocationStatus
  23. } from "@/tools.js";
  24. import {
  25. channelAllocationStatus
  26. } from "@/dataDic.js";
  27. import { citySelect, provinceList } from '@/NewDicProvinceList';
  28. import moment from "moment";
  29. import FollowDetail from "./followDetail";
  30. import IntentionDetail from "./intentionDetail/intentionDetail";
  31. import TransferRecords from './transferRecords';
  32. import DuplicateData from './duplicateData';
  33. import OperationTips from './operationTips';
  34. import ShowModalDiv from "@/showModal.jsx";
  35. import './channel.less';
  36. const {TabPane} = Tabs;
  37. const { RangePicker } = DatePicker;
  38. class Channel extends Component{
  39. constructor(props) {
  40. super(props);
  41. this.state={
  42. isGuidance:false,
  43. isEditGuidance: true,
  44. upLoadFileLoading:false,
  45. channelAllocationStatusList : channelAllocationStatus.slice(0,channelAllocationStatus.length-2),
  46. columns: [
  47. {
  48. title: "客户名称",
  49. dataIndex: "userName",
  50. key: "userName",
  51. render: (text,record) => {
  52. return (
  53. <span>
  54. {record.recovery === 1 ? <div style={{
  55. background:'#ef7207',
  56. color:'#FFF',
  57. padding: '1px 7px',
  58. borderRadius:'5px',
  59. fontSize:'12px',
  60. display: 'inline-block',
  61. marginRight:'10px'
  62. }}>
  63. 回收
  64. </div> : null}
  65. {text}
  66. </span>
  67. )
  68. },
  69. },
  70. {
  71. title: "地区",
  72. dataIndex: "locationProvince",
  73. key: "locationProvince",
  74. },
  75. {
  76. title: "社会性质",
  77. dataIndex: "societyTag",
  78. key: "societyTag",
  79. render: (text) => {
  80. return getSocialAttribute(text);
  81. },
  82. },
  83. {
  84. title: "渠道专员",
  85. dataIndex: "channelName",
  86. key: "channelName",
  87. },
  88. {
  89. title: "客户联系人",
  90. dataIndex: "contacts",
  91. key: "contacts",
  92. },
  93. {
  94. title: "联系电话",
  95. dataIndex: "contactMobile",
  96. key: "contactMobile",
  97. },
  98. {
  99. title: "渠道初始时间",
  100. dataIndex: "createTimes",
  101. key: "createTimes",
  102. },
  103. {
  104. title: "分配状态",
  105. dataIndex: "status",
  106. key: "status",
  107. render: (text) => (
  108. getChannelAllocationStatus(text,true)
  109. )
  110. },
  111. ],
  112. changeList:[],
  113. dataSource:[],
  114. pagination: {
  115. defaultCurrent: 1,
  116. defaultPageSize: 10,
  117. showQuickJumper: true,
  118. pageSize: 10,
  119. onChange: function (page) {
  120. this.loadData(page);
  121. }.bind(this),
  122. showTotal: function (total) {
  123. return "共" + total + "条数据";
  124. },
  125. },
  126. pageNo:1,
  127. listLoading:false,
  128. selectedRowKeys:[],
  129. selectedRows:[],
  130. modalVisible:false,
  131. nameSearch:'',
  132. statusSearch:undefined,
  133. provinceSearch:undefined,
  134. addressSearch:[],
  135. releaseDate:[],
  136. upLoad: {
  137. customRequest: (options) => {
  138. this.setState({
  139. upLoadFileLoading: true,
  140. })
  141. let params = new FormData();
  142. params.append("file", options.file);
  143. $.ajax({
  144. method: "post",
  145. url: globalConfig.context + "/api/user/channel/import",
  146. async: true,
  147. cache: false,
  148. contentType: false,
  149. processData: false,
  150. data:params
  151. }).done(
  152. function (data) {
  153. this.setState({
  154. upLoadFileLoading: false,
  155. })
  156. if (data.error.length === 0) {
  157. if(data.data === 1){
  158. message.success("导入成功!");
  159. }else if(data.data.list.length > 0){
  160. message.warning('已成功导入!错误/重复客户无法导入,请查看错误渠道数据!');
  161. this.setState({
  162. duplicateData: [],
  163. duplicateDataVisible: true
  164. })
  165. }
  166. this.loadData();
  167. } else {
  168. message.warning(data.error[0].message);
  169. this.loadData();
  170. }
  171. }.bind(this)
  172. ).always(
  173. function () {
  174. this.loadData();
  175. this.setState({
  176. upLoadFileLoading: false,
  177. });
  178. }.bind(this)
  179. );
  180. },
  181. name: "file",
  182. action: globalConfig.context + "/api/user/channel/import",
  183. },
  184. followData: '',
  185. visitModul: false,
  186. categoryArr:[],
  187. tabsKey:'',
  188. }
  189. this.loadData = this.loadData.bind(this);
  190. this.search = this.search.bind(this);
  191. this.reset = this.reset.bind(this);
  192. this.changeList = this.changeList.bind(this);
  193. this.download = this.download.bind(this);
  194. this.category = this.category.bind(this);
  195. this.closeDesc = this.closeDesc.bind(this);
  196. this.guidanceRead = this.guidanceRead.bind(this);
  197. this.tableRowClick = this.tableRowClick.bind(this);
  198. this.detailCloseDesc = this.detailCloseDesc.bind(this);
  199. this.supervisor = this.supervisor.bind(this);
  200. this.httpChange = this.httpChange.bind(this);
  201. this.blurChange = this.blurChange.bind(this);
  202. this.selectAuto = this.selectAuto.bind(this);
  203. this.changeAssigner = this.changeAssigner.bind(this);
  204. }
  205. componentWillReceiveProps (nextProps) {
  206. let next = JSON.stringify(nextProps);
  207. let props = JSON.stringify(this.props);
  208. if(next !== props){
  209. location.reload();
  210. }
  211. }
  212. componentDidMount() {
  213. this.initialization();
  214. }
  215. initialization(){
  216. //城市
  217. let provinces = [];
  218. provinceList.map(function (item) {
  219. var id = String(item.id);
  220. provinces.push(
  221. <Select.Option value={id} key={item.name}>
  222. {item.name}
  223. </Select.Option>
  224. );
  225. });
  226. this.setState({
  227. provinces
  228. })
  229. this.loadData();
  230. this.category();
  231. if(this.props.type === 0 || this.props.type === 3){
  232. this.state.columns.push({
  233. title: "分配时间",
  234. dataIndex: "distributionTimes",
  235. key: "distributionTimes",
  236. });
  237. this.state.columns.push({
  238. title: "剩余签单(天)",
  239. dataIndex: "days",
  240. key: "days",
  241. render: (text,record) => (
  242. record.status !== 7 ? <Tag color='#f00'>{text}天</Tag> : ''
  243. )
  244. });
  245. }
  246. if(this.props.followUp){
  247. this.state.columns.push({
  248. title: "当前跟进人",
  249. dataIndex: "adminName",
  250. key: "adminName",
  251. render: (text, record) => {
  252. return (
  253. record.status !== 0 ? text : ''
  254. )
  255. }
  256. });
  257. this.state.columns.push({
  258. title: "跟进操作",
  259. dataIndex: "abc",
  260. key: "abc",
  261. render: (text, record, index) => {
  262. return (
  263. <div style={{
  264. display: 'flex',
  265. flexFlow:'row',
  266. alignItems:'center',
  267. }}>
  268. <Button
  269. disabled={this.props.deliver === 2 && record.status === 2 && this.props.isEditGuidanceLv}
  270. onClick={(e) => {
  271. e.stopPropagation();
  272. if(this.props.isEditGuidanceLv){
  273. this.visit(record);
  274. }else{
  275. this.tableRowClick(record);
  276. }
  277. }}
  278. type="primary"
  279. >
  280. {this.props.isEditGuidanceLv ? '客户跟进' : '查看指导'}
  281. </Button>
  282. </div>
  283. );
  284. },
  285. });
  286. if(this.props.isEditGuidanceLv){
  287. this.state.columns.push({
  288. title: "指导意见",
  289. dataIndex: "guidance",
  290. key: "guidance",
  291. render: (text, record, index) => {
  292. return (
  293. <div style={{
  294. display: 'flex',
  295. flexFlow:'row',
  296. alignItems:'center',
  297. }}>
  298. {/*指导 0无 1未读 2已读*/}
  299. {text === 1 || text === 2 ? <Button
  300. style={text === 1 ? {
  301. background:'#F00000',
  302. borderColor:'#F00000'
  303. } : {}}
  304. onClick={(e)=>{
  305. e.stopPropagation();
  306. this.guidanceRead(record.uid).then(()=>{
  307. this.setState({
  308. tabsKey:"4",
  309. },()=>{
  310. this.tableRowClick(record)
  311. })
  312. })
  313. }}
  314. type="primary"
  315. >
  316. {text === 1 ? '未读' : '查看'}
  317. </Button> : <div>暂无指导</div>}
  318. </div>
  319. );
  320. },
  321. });
  322. }
  323. }
  324. this.state.columns.push({
  325. title: "备注",
  326. dataIndex: "remarks",
  327. key: "remarks",
  328. render: (text) => {
  329. return (
  330. <Tooltip placement="topLeft" title={text}>
  331. <div style={{
  332. maxWidth:'150px',
  333. overflow:'hidden',
  334. textOverflow: "ellipsis",
  335. whiteSpace:'nowrap',
  336. }}>{text}</div>
  337. </Tooltip>
  338. )
  339. }
  340. });
  341. this.setState({
  342. columns:this.state.columns
  343. })
  344. }
  345. visit(e) {
  346. this.setState({
  347. followData: e,
  348. visitModul: true,
  349. });
  350. }
  351. loadData(pageNo = 1) {
  352. this.setState({
  353. listLoading: true,
  354. selectedRows: [],
  355. selectedRowKeys: [],
  356. });
  357. $.ajax({
  358. method: "post",
  359. dataType: "json",
  360. crossDomain: false,
  361. url: globalConfig.context + '/api/admin/customer/listChannelCustomer',
  362. data: {
  363. type:this.props.type,
  364. pageNo: pageNo || 1,
  365. pageSize: this.state.pagination.pageSize,
  366. name: this.state.nameSearch,
  367. status:this.state.statusSearch,
  368. province: !this.state.addressSearch.length
  369. ? this.state.provinceSearch
  370. : this.state.addressSearch[0],
  371. city: !this.state.addressSearch.length
  372. ? ""
  373. : this.state.addressSearch[1],
  374. startTime: this.state.releaseDate[0],
  375. endTime: this.state.releaseDate[1],
  376. },
  377. success: function (data) {
  378. ShowModal(this);
  379. let theArr = [];
  380. if (data.error.length > 0) {
  381. message.warning(data.error[0].message);
  382. } else {
  383. if(data.data.list.length === 0 && pageNo !== 1){
  384. this.loadData(pageNo - 1)
  385. }else{
  386. for (let i = 0; i < data.data.list.length; i++) {
  387. let thisdata = data.data.list[i];
  388. let diqu =
  389. (thisdata.province == null ? "" : thisdata.province) +
  390. (thisdata.city == null ? "" : "-" + thisdata.city) +
  391. (thisdata.area == null ? "" : "-" + thisdata.area);
  392. thisdata.key = i;
  393. thisdata.id = thisdata.uid;
  394. thisdata.lastFollowTime = thisdata.lastFollowTime &&
  395. thisdata.lastFollowTime.split(" ")[0];
  396. thisdata.transferTime= thisdata.transferTime && thisdata.transferTime.split(" ")[0];
  397. thisdata.surplusFollowTime = thisdata.surplusFollowTime && thisdata.surplusFollowTime.split(" ")[0];
  398. thisdata.surplusSignTime = thisdata.surplusSignTime && thisdata.surplusSignTime.split(" ")[0];
  399. thisdata.locationProvince = diqu;
  400. theArr.push(thisdata);
  401. }
  402. this.state.pagination.current = data.data.pageNo;
  403. this.state.pagination.total = data.data.totalCount;
  404. this.setState({
  405. pageNo: data.data.pageNo,
  406. dataSource: theArr,
  407. pagination: this.state.pagination,
  408. })
  409. }
  410. }
  411. }.bind(this),
  412. }).always(
  413. function () {
  414. this.setState({
  415. listLoading: false,
  416. });
  417. }.bind(this)
  418. );
  419. }
  420. search(){
  421. this.loadData();
  422. }
  423. reset(){
  424. this.setState({
  425. nameSearch:'',
  426. provinceSearch:undefined,
  427. addressSearch:[],
  428. releaseDate:[],
  429. statusSearch:undefined,
  430. },()=>{
  431. this.loadData();
  432. })
  433. }
  434. download() {
  435. window.location.href =
  436. globalConfig.context +
  437. "/api/user/channel/downloadTemplate?" +
  438. "sign=user_channel";
  439. }
  440. changeList(arr) {
  441. const newArr = [];
  442. this.state.columns.forEach(item => {
  443. arr.forEach(val => {
  444. if (val === item.title) {
  445. newArr.push(item);
  446. }
  447. });
  448. });
  449. this.setState({
  450. changeList: newArr
  451. });
  452. }
  453. category() {
  454. $.ajax({
  455. method: "get",
  456. dataType: "json",
  457. crossDomain: false,
  458. url: globalConfig.context + "/api/admin/Varieties/getSuperList",
  459. data: {},
  460. success: function (data) {
  461. let thedata = data.data;
  462. let theArr = [];
  463. if (!thedata) {
  464. if (data.error && data.error.length) {
  465. message.warning(data.error[0].message);
  466. }
  467. thedata = {};
  468. } else {
  469. thedata.map(function (item, index) {
  470. theArr.push({
  471. value: item.id,
  472. key: item.cname,
  473. });
  474. });
  475. }
  476. this.setState({
  477. categoryArr: theArr,
  478. });
  479. }.bind(this),
  480. });
  481. }
  482. closeDesc(){
  483. this.setState({
  484. categoryArr:[],
  485. followData:'',
  486. visitModul:false
  487. })
  488. }
  489. //已读指导记录
  490. guidanceRead(id) {
  491. return new Promise((resolve,reject)=>{
  492. $.ajax({
  493. method: "post",
  494. dataType: "json",
  495. crossDomain: false,
  496. url: globalConfig.context + "/api/admin/customer/pushGuidance",
  497. data: {
  498. uid: id,
  499. }
  500. }).done(function(data) {
  501. if(!data.error.length) {
  502. resolve();
  503. } else {
  504. message.warning(data.error[0].message);
  505. reject();
  506. };
  507. }.bind(this));
  508. })
  509. }
  510. tableRowClick(record) {
  511. if(this.props.deliver === 2 && record.status === 2 && this.props.isEditGuidanceLv){
  512. this.setState({
  513. isGuidance: true,
  514. tabsKey:"4",
  515. })
  516. }
  517. //营销经理人员 取消指导自己的操作
  518. if(this.props.deliver === 2 && record.status === 1 && this.props.isEditGuidanceLv){
  519. this.setState({
  520. isEditGuidance: false,
  521. })
  522. }
  523. //营销人员 取消指导的操作
  524. if(this.props.deliver === 0 && record.status === 2 && this.props.isEditGuidanceLv){
  525. this.setState({
  526. isEditGuidance: false,
  527. })
  528. }
  529. this.setState({
  530. rowData:record,
  531. modalVisible: true,
  532. basicState: true,
  533. contactState: true,
  534. modalName: record.userName
  535. })
  536. }
  537. detailCloseDesc(){
  538. this.setState({
  539. rowData:'',
  540. modalVisible: false,
  541. basicState: false,
  542. contactState: false,
  543. modalName: '',
  544. isGuidance: false,
  545. isEditGuidance: true,
  546. tabsKey: '',
  547. },()=>{
  548. this.loadData(this.state.pageNo);
  549. })
  550. }
  551. supervisor(e) {
  552. $.ajax({
  553. method: "get",
  554. dataType: "json",
  555. crossDomain: false,
  556. url: globalConfig.context + "/api/admin/customer/listAdminByName",
  557. data: {
  558. adminName: e,
  559. },
  560. success: function (data) {
  561. let thedata = data.data;
  562. if (!thedata) {
  563. if (data.error && data.error.length) {
  564. message.warning(data.error[0].message);
  565. }
  566. thedata = {};
  567. }
  568. this.setState({
  569. customerArr: thedata,
  570. });
  571. }.bind(this),
  572. }).always(
  573. function () {
  574. }.bind(this)
  575. );
  576. }
  577. httpChange(e) {
  578. if (e.length >= 1) {
  579. this.supervisor(e);
  580. }
  581. this.setState({
  582. auto: e,
  583. });
  584. }
  585. blurChange(e) {
  586. let theType = "";
  587. let contactLists = this.state.customerArr || [];
  588. if (e) {
  589. contactLists.map(function (item) {
  590. if (item.name == e.toString()) {
  591. theType = item.id;
  592. }
  593. });
  594. }
  595. this.setState({
  596. theTypes: theType,
  597. });
  598. }
  599. selectAuto(value, options) {
  600. this.setState({
  601. auto: value,
  602. });
  603. }
  604. changeAssigner(remarks,type,lv) {
  605. //type 0 总监分配 1经理分配 2回收
  606. let arr = this.state.selectedRows.filter(v=>v.status === 1);
  607. let arr1 = this.state.selectedRows.filter(v=>v.status === 2);
  608. let arr2 = this.state.selectedRows.filter(v=>v.status === 7);
  609. let arr3 = this.state.selectedRows.filter(v=>v.status === 6);
  610. if(type === 0 && (arr.length>0 || arr1.length>0)){
  611. message.warning('选中的信息中存在“已分配”数据,请取消这些选项后重新提交')
  612. return;
  613. }
  614. if(type === 1 && arr1.length>0){
  615. message.warning('选中的信息中存在“经理已分配”数据,请取消这些选项后重新提交')
  616. return;
  617. }
  618. //处于回收状态的客户经理和营销员不能点击回收
  619. if(this.props.deliver !== 1 && arr3.length>0){
  620. message.warning('渠道客户已回收!待营销总监,重新分配')
  621. return;
  622. }
  623. //this.props.deliver && this.props.recovery 用于判断是否为经理
  624. if(this.props.deliver === 2 && this.props.recovery && type === 2 && arr1.length>0){
  625. message.warning('操作失败,存在客户已被分配营销员')
  626. return;
  627. }
  628. if(arr2.length>0){
  629. message.warning('不能操作已签单客户')
  630. return;
  631. }
  632. if(!remarks){
  633. message.warning(type === 1 ? "请输入分配原因" : type === 2 ? "请输入回收原因" : type === 0 ? "请输入分配原因" : "");
  634. return;
  635. }
  636. if (this.state.theTypes || lv) {
  637. this.setState({
  638. listLoading: true,
  639. })
  640. let changeIds = '';
  641. let oldAid = '';
  642. for (let idx = 0; idx < this.state.selectedRows.length; idx++) {
  643. let rowItem = this.state.selectedRows[idx];
  644. if(rowItem.recovery === 1 && type === 2){
  645. let arr = this.state.selectedRows.filter(v => v.recovery === 1)
  646. Modal.info({
  647. title: '以下数据属于回收再分配资源,无法再次回收',
  648. content: (
  649. <div>
  650. {
  651. arr.map(i=>(
  652. <div style={{paddingBottom:'7px'}}>{i.userName}</div>
  653. ))
  654. }
  655. </div>
  656. ),
  657. onOk() {},
  658. });
  659. return ;
  660. }
  661. if (rowItem.id) {
  662. oldAid = rowItem.aid;
  663. changeIds = this.state.selectedRows.length-1 === idx ? changeIds +rowItem.id : changeIds + rowItem.id + ',' ;
  664. }
  665. }
  666. $.ajax({
  667. method: "post",
  668. dataType: "json",
  669. crossDomain: false,
  670. url: globalConfig.context + "/api/admin/customer/channelCustomerDeliver",
  671. data: {
  672. userIds: changeIds, //这一行数据的ID
  673. receiveId: this.state.theTypes, //指定分配人的ID
  674. remarks: remarks,
  675. type, //0总监分配 1经理分配 2回收
  676. },
  677. }).done(
  678. function (data) {
  679. this.setState({
  680. listLoading: false,
  681. })
  682. if (!data.error.length) {
  683. message.success(type === 1 ? "分配成功!" : type === 2 ? "回收成功!" : type === 0 ? "分配成功!" : "");
  684. this.setState({
  685. auto: "",
  686. loading: false,
  687. selectedRowKeys: [],
  688. visible:false,
  689. recoveryVisible: false,
  690. },()=>{
  691. this.loadData(this.state.pageNo);
  692. });
  693. } else {
  694. message.warning(data.error[0].message);
  695. }
  696. }.bind(this)
  697. );
  698. } else {
  699. message.warning("请输入分配人姓名");
  700. }
  701. }
  702. render() {
  703. const rowSelection = {
  704. hideDefaultSelections: true,
  705. selectedRowKeys: this.state.selectedRowKeys,
  706. onChange: (selectedRowKeys, selectedRows) => {
  707. this.setState({
  708. modalVisible: false,
  709. selectedRows: selectedRows,
  710. selectedRowKeys: selectedRowKeys,
  711. });
  712. },
  713. onSelect: (recordt, selected, selectedRows) => {
  714. this.setState({
  715. modalVisible: false,
  716. });
  717. },
  718. };
  719. const dataSources = this.state.customerArr || [];
  720. const options = dataSources.map((group) => (
  721. <Select.Option key={group.id} value={group.name}>
  722. {group.name}
  723. </Select.Option>
  724. ));
  725. const hasSelected = this.state.selectedRowKeys.length > 0;
  726. return (
  727. <div className="user-content">
  728. <ShowModalDiv ShowModal={this.state.showModal} />
  729. <div className="content-title">
  730. <span>渠道客户</span>
  731. </div>
  732. <div className="user-search">
  733. <Tabs
  734. defaultActiveKey="1"
  735. className="test"
  736. >
  737. <TabPane tab="搜索" key="1">
  738. <Input
  739. placeholder="请输入客户名称"
  740. value={this.state.nameSearch}
  741. style={{ width: 150, marginRight: 10, marginLeft: 10 }}
  742. onChange={(e) => {
  743. this.setState({ nameSearch: e.target.value });
  744. }}
  745. />
  746. <Select
  747. placeholder="分配状态"
  748. style={{ width: 170 }}
  749. value={this.state.statusSearch}
  750. onChange={(e) => {
  751. this.setState({ statusSearch: e });
  752. }}
  753. >
  754. {
  755. this.state.channelAllocationStatusList.map((v,key)=>(
  756. <Select.Option value={v.value} key={key}>
  757. {v.key}
  758. </Select.Option>
  759. ))
  760. }
  761. </Select>
  762. <Select
  763. placeholder="省"
  764. style={{ width: 80 }}
  765. value={this.state.provinceSearch}
  766. onChange={(e) => {
  767. this.setState({ provinceSearch: e });
  768. }}
  769. >
  770. {this.state.provinces}
  771. </Select>
  772. <span style={{ marginRight: "10px" }}>
  773. <Cascader
  774. options={citySelect()}
  775. value={this.state.addressSearch}
  776. placeholder="选择城市"
  777. onChange={(e, pre) => {
  778. this.setState({ addressSearch: e });
  779. }}
  780. />
  781. </span>
  782. <RangePicker
  783. value={[
  784. this.state.releaseDate[0]
  785. ? moment(this.state.releaseDate[0])
  786. : null,
  787. this.state.releaseDate[1]
  788. ? moment(this.state.releaseDate[1])
  789. : null,
  790. ]}
  791. onChange={(data, dataString) => {
  792. this.setState({ releaseDate: dataString });
  793. }}
  794. />
  795. <Button
  796. type="primary"
  797. style={{ marginLeft: "10px", marginRight: 10 }}
  798. onClick={this.search}
  799. >
  800. 搜索
  801. </Button>
  802. <Button onClick={this.reset}>重置</Button>
  803. </TabPane>
  804. <TabPane tab="操作" key="2">
  805. <div style={{
  806. marginTop: 10,
  807. }}>
  808. {this.props.deliver ? <AutoComplete
  809. className="certain-category-search"
  810. dropdownClassName="certain-category-search-dropdown"
  811. dropdownMatchSelectWidth={false}
  812. dropdownStyle={{ width: 120 }}
  813. style={{ width: "120px" }}
  814. dataSource={options}
  815. placeholder={this.props.deliver === 1 ? '输入分配人姓名' : '输入分配人姓名'}
  816. value={this.state.auto}
  817. onChange={this.httpChange}
  818. filterOption={true}
  819. onBlur={this.blurChange}
  820. onSelect={this.selectAuto}
  821. disabled={!hasSelected}
  822. >
  823. <Input />
  824. </AutoComplete> : ''}
  825. {this.props.deliver ? <Button
  826. type="primary"
  827. onClick={(e) => {
  828. e.stopPropagation();
  829. this.setState({
  830. visible:true
  831. })
  832. }}
  833. disabled={!hasSelected}
  834. style={{ marginRight: 10 }}
  835. >
  836. {this.props.deliver === 1 ? '分配' : '分配'}
  837. </Button> : ''}
  838. {this.props.recovery ? <Button
  839. type="primary"
  840. onClick={(e) => {
  841. e.stopPropagation();
  842. this.setState({
  843. recoveryVisible:true
  844. })
  845. }}
  846. disabled={!hasSelected}
  847. style={{ marginRight: 10 }}
  848. >
  849. 回收
  850. </Button> : ''}
  851. {this.props.deliver || this.props.recovery ? <Button
  852. type="primary"
  853. onClick={(e) => {
  854. e.stopPropagation();
  855. this.setState({
  856. transferVisible:true,
  857. transferId: this.state.selectedRows[0].uid
  858. })
  859. }}
  860. disabled={!hasSelected || this.state.selectedRows.length > 1}
  861. style={{ marginRight: 10 }}
  862. >
  863. 日志
  864. </Button> : ''}
  865. {this.props.channel ? <Upload {...this.state.upLoad} disabled={this.state.upLoadFileLoading}>
  866. <Button
  867. loading={this.state.upLoadFileLoading}
  868. type="primary"
  869. style={{ marginRight: "10px" }}
  870. >
  871. +批量导入渠道客户
  872. </Button>
  873. </Upload> : null}
  874. {this.props.channel ? <Button
  875. onClick={(e) => {
  876. e.stopPropagation();
  877. this.download();
  878. }}
  879. type="primary"
  880. style={{
  881. marginRight: "10px",
  882. background:'#f49f36',
  883. borderColor:'#f49f36'
  884. }}
  885. >
  886. 下载渠道客户模板
  887. </Button> : ''}
  888. {this.props.channel ? <Button
  889. onClick={(e) => {
  890. e.stopPropagation();
  891. this.setState({
  892. duplicateData: [],
  893. duplicateDataVisible: true
  894. })
  895. }}
  896. type="primary"
  897. style={{
  898. marginRight: "10px",
  899. background:'#ff2f00',
  900. borderColor:'#ff2f00'
  901. }}
  902. >
  903. 查看导入失败列表
  904. </Button> : ''}
  905. </div>
  906. </TabPane>
  907. <TabPane tab="更改表格显示数据" key="3">
  908. <div style={{ marginLeft: 10 }}>
  909. <ChooseList
  910. columns={this.state.columns}
  911. changeFn={this.changeList}
  912. changeList={this.state.changeList}
  913. top={55}
  914. margin={11}
  915. />
  916. </div>
  917. </TabPane>
  918. </Tabs>
  919. </div>
  920. <div className="patent-table">
  921. <Spin spinning={this.state.listLoading}>
  922. <Table
  923. size="middle"
  924. className={'intentionCustomerTable'}
  925. columns={
  926. this.state.changeList.length !== 0
  927. ? this.state.changeList
  928. : this.state.columns
  929. }
  930. dataSource={this.state.dataSource}
  931. rowSelection={this.props.deliver || this.props.recovery ? rowSelection : ''}
  932. pagination={this.state.pagination}
  933. onRowDoubleClick={this.tableRowClick}
  934. />
  935. </Spin>
  936. </div>
  937. <FollowDetail
  938. categoryArr={this.state.categoryArr}
  939. followData={this.state.followData}
  940. visitModul={this.state.visitModul}
  941. closeDesc={this.closeDesc}
  942. />
  943. <IntentionDetail
  944. tabsKey={this.state.tabsKey}
  945. categoryArr={this.state.categoryArr}
  946. detailApi={this.props.detailApi}
  947. IntentionData={this.state.rowData}
  948. modalVisible={this.state.modalVisible}
  949. name={this.state.modalName}
  950. closeDesc={this.detailCloseDesc}
  951. basicState={this.state.basicState}
  952. contactState={this.state.contactState}
  953. isGuidanceLv={this.props.isGuidanceLv || this.state.isGuidance}
  954. isEditGuidanceLv={this.props.isEditGuidanceLv && this.state.isEditGuidance}
  955. />
  956. {this.state.duplicateDataVisible ? <DuplicateData
  957. duplicateData={this.state.duplicateData || []}
  958. visible={this.state.duplicateDataVisible}
  959. onCancel={()=>{
  960. this.setState({
  961. duplicateData:[],
  962. duplicateDataVisible: false
  963. },()=>{
  964. this.loadData(this.state.pageNo);
  965. })
  966. }}
  967. /> : null}
  968. {this.state.transferVisible || this.state.returnVisible ? <TransferRecords
  969. type={this.state.transferVisible ? (this.props.deliver === 1 ? 0 : 1) : this.state.returnVisible ? 2 : 0}
  970. id={this.state.transferId}
  971. visible={this.state.transferVisible || this.state.returnVisible}
  972. cancel={()=>{
  973. this.setState({
  974. transferVisible:false,
  975. returnVisible: false,
  976. transferId:''
  977. })
  978. }}
  979. /> : '' }
  980. {/*渠道客户分配*/}
  981. {this.state.visible ? <OperationTips
  982. title={'渠道客户分配'}
  983. selectedRows={this.state.selectedRows}
  984. visible={this.state.visible}
  985. onOk={(value)=>{
  986. // 0 总监分配 1经理分配 2回收
  987. this.changeAssigner(value,this.props.deliver === 1 ? 0 : this.props.deliver === 2 ? 1 : '')
  988. }}
  989. onCancel={()=>{
  990. this.setState({
  991. visible:false
  992. })
  993. }}/> : ''}
  994. {/*渠道客户回收*/}
  995. {this.state.recoveryVisible ? <OperationTips
  996. title={'渠道客户回收'}
  997. selectedRows={this.state.selectedRows}
  998. visible={this.state.recoveryVisible}
  999. onOk={(value)=>{
  1000. this.changeAssigner(value,2,true)
  1001. }}
  1002. onCancel={()=>{
  1003. this.setState({
  1004. recoveryVisible:false
  1005. })
  1006. }}/> : ''}
  1007. {this.state.upLoadFileLoading ? <div style={{
  1008. position:'fixed',
  1009. display:'flex',
  1010. flexFlow:'column',
  1011. justifyContent:'center',
  1012. alignItems:'center',
  1013. top:0,
  1014. bottom:0,
  1015. left:0,
  1016. right:0,
  1017. background:'rgba(0,0,0,.7)',
  1018. color:"#58a3ff",
  1019. fontSize:'20px',
  1020. zIndex:99999,
  1021. }}>
  1022. <Spin spinning={this.state.upLoadFileLoading}/>
  1023. <div style={{paddingTop:'10px'}}>客户名称匹配中...</div>
  1024. </div>: null}
  1025. </div>
  1026. )
  1027. }
  1028. }
  1029. export default Channel;