signCustomer.jsx 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748
  1. import React from 'react';
  2. import {
  3. Radio,
  4. Icon,
  5. Button,
  6. AutoComplete,
  7. Cascader,
  8. Input,
  9. Select,
  10. Tabs,
  11. Spin,
  12. Popconfirm,
  13. Table,
  14. Switch,
  15. message,
  16. DatePicker,
  17. Upload,
  18. Form,
  19. Modal, Tooltip
  20. } from 'antd';
  21. import ajax from 'jquery/src/ajax/xhr.js';
  22. import $ from 'jquery/src/ajax';
  23. import moment from 'moment';
  24. import { citySelect, provinceList } from '@/NewDicProvinceList';
  25. import { socialAttribute, industry, auditStatusL, lvl, currentMember } from '@/dataDic.js';
  26. import { getSocialAttribute, beforeUploadFile, ShowModal } from "@/tools.js";
  27. import FollowDetail from './followDetail.jsx'
  28. import ShowModalDiv from "@/showModal.jsx";
  29. import ZhuanjiaoDetail from "@/zhuanjiaoDetail.jsx";
  30. import IntentionDetail from './intentionDetail/intentionDetail.jsx'
  31. import './customer.less';
  32. import {ChooseList} from "../../../order/orderNew/chooseList";
  33. import EnterpriseNameChange from "../../../../common/enterpriseNameChange";
  34. const {TabPane} = Tabs
  35. const IntentionCustomer = Form.create()(React.createClass({
  36. loadData(pageNo, apiUrl) {
  37. this.setState({
  38. visitModul:false,
  39. loading: true,
  40. ispage:pageNo,
  41. modalVisible:false
  42. });
  43. let api=apiUrl?apiUrl:this.props.ApiUrl;
  44. $.ajax({
  45. method: "post",
  46. dataType: "json",
  47. crossDomain: false,
  48. url: globalConfig.context + api,
  49. data: {
  50. pageNo: pageNo || 1,
  51. pageSize: this.state.pagination.pageSize,
  52. name: this.state.nameSearch,
  53. channel: this.state.channelSearch,
  54. province: !(this.state.addressSearch).length ? this.state.provinceSearch : this.state.addressSearch[0],
  55. city: !(this.state.addressSearch).length ? '' : this.state.addressSearch[1],
  56. startDate: this.state.releaseDate[0],
  57. endDate: this.state.releaseDate[1],
  58. },
  59. success: function(data) {
  60. ShowModal(this);
  61. let theArr = [];
  62. if(data.error.length || data.data.list == "") {
  63. if(data.error && data.error.length) {
  64. message.warning(data.error[0].message);
  65. };
  66. } else {
  67. for(let i = 0; i < data.data.list.length; i++) {
  68. let thisdata = data.data.list[i];
  69. let diqu=(thisdata.province==null?"":thisdata.province)+(thisdata.city==null?"":"-"+thisdata.city)+(thisdata.area==null?"":"-"+thisdata.area);
  70. thisdata.key = i;
  71. thisdata.id = thisdata.uid;
  72. thisdata.transferTime = thisdata.transferTime && thisdata.transferTime.split(" ")[0];
  73. thisdata.lastSignTime = thisdata.lastSignTime && thisdata.lastSignTime.split(" ")[0];
  74. thisdata.lastFollowTime = thisdata.lastFollowTime && thisdata.lastFollowTime.split(" ")[0];
  75. thisdata.locationProvince = diqu
  76. theArr.push(thisdata);
  77. };
  78. this.state.pagination.current = data.data.pageNo;
  79. this.state.pagination.total = data.data.totalCount;
  80. };
  81. if(data.data&&data.data.list&&!data.data.list.length){
  82. this.state.pagination.current=0
  83. this.state.pagination.total=0
  84. };
  85. this.setState({
  86. dataSource: theArr,
  87. pagination: this.state.pagination,
  88. selectedRowKeys:[]
  89. });
  90. }.bind(this),
  91. }).always(function() {
  92. this.setState({
  93. loading: false
  94. });
  95. }.bind(this));
  96. },
  97. getInitialState() {
  98. return {
  99. addressSearch: [],
  100. orgCodeUrl: [],
  101. companyLogoUrl: [],
  102. visible: false,
  103. searchMore: true,
  104. releaseDate: [],
  105. visitModul: false,
  106. keys: false,
  107. detailApi: "",
  108. followData: {},
  109. selectedRowKeys: [],
  110. selectedRowKey: [],
  111. selectedRows: [],
  112. loading: false,
  113. defaultActiveKey: '',
  114. modalVisible: false,
  115. pagination: {
  116. defaultCurrent: 1,
  117. defaultPageSize: 10,
  118. showQuickJumper: true,
  119. pageSize: 10,
  120. onChange: function (page) {
  121. this.loadData(page);
  122. }.bind(this),
  123. showTotal: function (total) {
  124. return "共" + total + "条数据";
  125. },
  126. },
  127. columns: [
  128. {
  129. title: "客户名称",
  130. dataIndex: "name",
  131. key: "name",
  132. width: 100,
  133. render: (text,record) => {
  134. return (
  135. <span>
  136. {record.channel === 1 ? <div style={{
  137. background:'#ef7207',
  138. color:'#FFF',
  139. padding: '1px 7px',
  140. borderRadius:'5px',
  141. fontSize:'12px',
  142. display: 'inline-block',
  143. marginRight:'10px'
  144. }}>
  145. 渠道
  146. </div> : null}
  147. <Tooltip title={text}>
  148. <div style={{
  149. maxWidth:'100px',
  150. overflow:'hidden',
  151. textOverflow: "ellipsis",
  152. whiteSpace:'nowrap',
  153. }}>{text}</div>
  154. </Tooltip>
  155. </span>
  156. )
  157. },
  158. },
  159. {
  160. title: "地区",
  161. dataIndex: "locationProvince",
  162. key: "locationProvince",
  163. },
  164. {
  165. title: "最新签单日期",
  166. dataIndex: "transferTime",
  167. key: "transferTime",
  168. },
  169. // {
  170. // title: "最新跟进日期",
  171. // dataIndex: "lastFollowTime",
  172. // key: "lastFollowTime",
  173. // },
  174. // {
  175. // title: "剩余私有天数",
  176. // dataIndex: "surplusFollowTime",
  177. // key: "surplusFollowTime",
  178. // },
  179. // {
  180. // title: "剩余签单天数",
  181. // dataIndex: "surplusSignTime",
  182. // key: "surplusSignTime",
  183. // },
  184. // {
  185. // title: "联系人",
  186. // dataIndex: "contacts",
  187. // key: "contacts",
  188. // },
  189. // {
  190. // title: "联系电话",
  191. // dataIndex: "contactMobile",
  192. // key: "contactMobile",
  193. // },
  194. {
  195. title: "社会属性",
  196. dataIndex: "societyTag",
  197. key: "societyTag",
  198. render: (text) => {
  199. return getSocialAttribute(text);
  200. },
  201. },
  202. {
  203. title: "操作",
  204. dataIndex: "abc",
  205. key: "abc",
  206. render: (text, record, index) => {
  207. return (
  208. <div>
  209. <Button
  210. onClick={(e) => {
  211. e.stopPropagation(), this.visit(record);
  212. }}
  213. type="primary"
  214. >
  215. 客户跟进
  216. </Button>
  217. <Button
  218. style={{ marginLeft: 10 }}
  219. onClick={(e) => {
  220. e.stopPropagation(), this.zhuanjiaoDetail(record);
  221. }}
  222. type="primary"
  223. >
  224. 转交记录
  225. </Button>
  226. <Button
  227. style={{ marginLeft: 10 }}
  228. type="primary"
  229. onClick={(e)=>{
  230. e.stopPropagation();
  231. this.setState({
  232. defaultActiveKey: '6'
  233. },()=>{
  234. this.tableRowClick(record);
  235. })
  236. }}
  237. >
  238. 转交业务
  239. </Button>
  240. </div>
  241. );
  242. },
  243. },
  244. ],
  245. data: [],
  246. dataSource: [],
  247. };
  248. },
  249. zhuanjiaoDetail(record) {
  250. this.setState({
  251. zhuanjiaoVisible: true,
  252. zhuanjiaoId: record.id
  253. })
  254. },
  255. zhuanjiaoDetailCancel() {
  256. this.setState({
  257. zhuanjiaoVisible: false
  258. })
  259. },
  260. //进入新增拜访记录
  261. visit(e) {
  262. this.setState({
  263. followData:e,
  264. visitModul:true,
  265. modalVisible:false
  266. })
  267. },
  268. //列表删除功能
  269. delectRow() {
  270. let deletedIds;
  271. for(let idx = 0; idx < this.state.selectedRows.length; idx++) {
  272. let rowItem = this.state.selectedRows[idx];
  273. if(rowItem.id) {
  274. deletedIds = rowItem.id;
  275. };
  276. };
  277. this.setState({
  278. loading: true,
  279. selectedRowKeys: [],
  280. });
  281. $.ajax({
  282. method: "get",
  283. dataType: "json",
  284. crossDomain: false,
  285. url: globalConfig.context + "/api/admin/customer/deleteCustomer",
  286. data: {
  287. uid: deletedIds, //删除的ID
  288. }
  289. }).done(function(data) {
  290. if(!data.error.length) {
  291. message.success('删除成功!');
  292. this.setState({
  293. loading: false,
  294. });
  295. } else {
  296. message.warning(data.error[0].message);
  297. };
  298. this.loadData(this.state.ispage);
  299. }.bind(this));
  300. },
  301. componentWillMount() {
  302. //城市
  303. let Province = [];
  304. provinceList.map(function(item) {
  305. var id = String(item.id)
  306. Province.push(
  307. <Select.Option value={id} key={item.name}>{item.name}</Select.Option>
  308. )
  309. });
  310. //行业
  311. let intentionalArr = [];
  312. industry.map(function(item) {
  313. intentionalArr.push(
  314. <Select.Option value={item.value} key={item.key}>{item.key}</Select.Option>
  315. )
  316. });
  317. this.state.Provinces = Province;
  318. this.state.intentionalOption = intentionalArr;
  319. this.loadData();
  320. },
  321. closeDesc(e, s) {
  322. this.state.basicState=e
  323. this.state.visitModul=e;
  324. this.state.modalVisible=e;
  325. this.state.showDesc = e;
  326. this.setState({
  327. defaultActiveKey:''
  328. })
  329. if(s) {
  330. this.loadData(this.state.ispage);
  331. };
  332. },
  333. search() {
  334. this.loadData();
  335. },
  336. reset() {
  337. this.state.nameSearch = '';
  338. this.state.addressSearch = [];
  339. this.state.provinceSearch = undefined;
  340. this.state.channelSearch = undefined;
  341. this.state.citySearch = undefined;
  342. this.state.releaseDate[0] = undefined;
  343. this.state.releaseDate[1] = undefined;
  344. this.loadData();
  345. },
  346. searchSwitch() {
  347. this.setState({
  348. visitModul:false,
  349. searchMore: !this.state.searchMore
  350. });
  351. },
  352. //整行点击
  353. tableRowClick(record) {
  354. this.state.visitModul=false;
  355. this.state.RowData = record;
  356. this.setState({
  357. // selectedRowKeys: [],
  358. modalVisible:true,
  359. basicState:true,
  360. contactState:true,
  361. modalName: record.name
  362. })
  363. },
  364. //指定转交人自动补全
  365. supervisor(e){
  366. $.ajax({
  367. method: "get",
  368. dataType: "json",
  369. crossDomain: false,
  370. url: globalConfig.context + "/api/admin/customer/listAdminByName",
  371. data:{
  372. adminName:e
  373. },
  374. success: function (data) {
  375. let thedata=data.data;
  376. if (!thedata) {
  377. if (data.error && data.error.length) {
  378. message.warning(data.error[0].message);
  379. };
  380. thedata = {};
  381. };
  382. this.setState({
  383. customerArr:thedata,
  384. });
  385. }.bind(this),
  386. }).always(function () {
  387. this.setState({
  388. loading: false
  389. });
  390. }.bind(this));
  391. },
  392. componentWillReceiveProps(nextProps) {
  393. if(nextProps.ApiUrl!=this.props.ApiUrl) {
  394. if(!this.state.searchMore){
  395. this.state.searchMore=true
  396. }
  397. this.state.nameSearch = '';
  398. this.state.addressSearch = [];
  399. this.state.provinceSearch = undefined;
  400. this.state.channelSearch = undefined
  401. this.state.citySearch = undefined;
  402. this.state.releaseDate[0] = undefined;
  403. this.state.releaseDate[1] = undefined;
  404. this.loadData(null,nextProps.ApiUrl);
  405. };
  406. },
  407. changeList(arr) {
  408. const newArr = [];
  409. this.state.columns.forEach(item => {
  410. arr.forEach(val => {
  411. if (val === item.title) {
  412. newArr.push(item);
  413. }
  414. });
  415. });
  416. this.setState({
  417. changeList: newArr
  418. });
  419. },
  420. //上级主管输入框失去焦点是判断客户是否存在
  421. selectAuto(value, options) {
  422. this.setState({
  423. auto: value,
  424. });
  425. },
  426. //值改变时请求客户名称
  427. httpChange(e) {
  428. if (e.length >= 1) {
  429. this.supervisor(e);
  430. }
  431. this.setState({
  432. auto: e,
  433. });
  434. },
  435. showConfirm(fn, record) {
  436. if(this.state.confirmLoading){
  437. return false;
  438. }
  439. Modal.confirm({
  440. title: "提示",
  441. content: (
  442. <span style={{ color: "red" }}>
  443. 确定要转交以下客户吗?
  444. {
  445. this.state.selectedRows.map((value,index)=>(
  446. <div key={index} style={{marginTop:'5px',color: "#000"}}>
  447. {value.name}
  448. </div>
  449. ))
  450. }
  451. </span>
  452. ),
  453. onOk() {
  454. fn(record);
  455. },
  456. onCancel() {},
  457. });
  458. },
  459. //转交
  460. changeAssigner() {
  461. if (this.state.theTypes) {
  462. this.setState({
  463. confirmLoading: true
  464. })
  465. const hide = message.loading('转交中...', 0);
  466. let changeIds = '';
  467. let oldAid = '';
  468. for (let idx = 0; idx < this.state.selectedRows.length; idx++) {
  469. let rowItem = this.state.selectedRows[idx];
  470. if (rowItem.id) {
  471. oldAid = rowItem.aid;
  472. changeIds = this.state.selectedRows.length-1 === idx ? changeIds +rowItem.id : changeIds + rowItem.id + ',' ;
  473. }
  474. }
  475. $.ajax({
  476. method: "get",
  477. dataType: "json",
  478. crossDomain: false,
  479. url: globalConfig.context + "/api/admin/customer/transferToOther",
  480. data: {
  481. uid: changeIds, //这一行数据的ID
  482. aid: this.state.theTypes, //指定转交人的ID
  483. oldAid: window.adminData.uid,
  484. operatorType:4
  485. },
  486. }).done(
  487. function (data) {
  488. if (!data.error.length) {
  489. message.success("转交成功!");
  490. this.setState({
  491. auto: "",
  492. loading: false,
  493. selectedRowKeys: [],
  494. });
  495. } else {
  496. message.warning(data.error[0].message);
  497. }
  498. this.loadData(
  499. Math.min(
  500. this.state.ispage == undefined ? 1 : this.state.ispage,
  501. Math.ceil((this.state.pagination.total - 1) / 10)
  502. )
  503. );
  504. hide();
  505. this.setState({
  506. confirmLoading: false
  507. })
  508. }.bind(this)
  509. );
  510. } else {
  511. message.warning("请输入转交人姓名");
  512. }
  513. },
  514. blurChange(e) {
  515. let theType = "";
  516. let contactLists = this.state.customerArr || [];
  517. if (e) {
  518. contactLists.map(function (item) {
  519. if (item.name == e.toString()) {
  520. theType = item.id;
  521. }
  522. });
  523. }
  524. this.setState({
  525. theTypes: theType,
  526. });
  527. },
  528. render() {
  529. const rowSelection = {
  530. selectedRowKeys: this.state.selectedRowKeys,
  531. onChange: (selectedRowKeys, selectedRows) => {
  532. this.setState({
  533. modalVisible:false,
  534. selectedRows: selectedRows,
  535. selectedRowKeys: selectedRowKeys
  536. });
  537. },
  538. onSelect: (recordt, selected, selectedRows) => {
  539. this.setState({
  540. modalVisible:false,
  541. recordt: recordt.id
  542. })
  543. },
  544. };
  545. const hasSelected = this.state.selectedRowKeys.length > 0;
  546. const { RangePicker } = DatePicker;
  547. const dataSources=this.state.customerArr || [];
  548. const options = dataSources.map((group) =>
  549. <Select.Option key={group.id} value={group.name}>{group.name}</Select.Option>
  550. )
  551. const intentionState = this.props.intentionState ||'';
  552. return (
  553. <div className="user-content">
  554. <ShowModalDiv ShowModal={this.state.showModal} />
  555. {this.state.zhuanjiaoVisible ? (
  556. <ZhuanjiaoDetail
  557. cancel={this.zhuanjiaoDetailCancel}
  558. visible={this.state.zhuanjiaoVisible}
  559. type={1}
  560. id={this.state.zhuanjiaoId}
  561. />
  562. ) : (
  563. ""
  564. )}
  565. <div className="content-title">
  566. <span>{!intentionState ? "签单客户" : "签单客户"}</span>
  567. </div>
  568. <Tabs defaultActiveKey="1" className="test">
  569. <TabPane tab="搜索" key="1">
  570. <div className="user-search">
  571. <Input
  572. placeholder="客户名称"
  573. value={this.state.nameSearch}
  574. onChange={(e) => {
  575. this.setState({ nameSearch: e.target.value });
  576. }}
  577. />
  578. <Select
  579. placeholder="是否为渠道"
  580. style={{ width: 110 }}
  581. value={this.state.channelSearch}
  582. onChange={(e) => {
  583. this.setState({ channelSearch: e });
  584. }}
  585. >
  586. <Select.Option value={0}>
  587. 非渠道
  588. </Select.Option>
  589. <Select.Option value={1}>
  590. 渠道
  591. </Select.Option>
  592. </Select>
  593. <Select
  594. placeholder="省"
  595. style={{ width: 80 }}
  596. value={this.state.provinceSearch}
  597. onChange={(e) => {
  598. this.setState({ provinceSearch: e });
  599. }}
  600. >
  601. {this.state.Provinces}
  602. </Select>
  603. <span style={{ marginRight: "10px" }}>
  604. <Cascader
  605. options={citySelect()}
  606. value={this.state.addressSearch}
  607. placeholder="选择城市"
  608. onChange={(e, pre) => {
  609. this.setState({ addressSearch: e });
  610. }}
  611. />
  612. </span>
  613. {/* <div className="clearfix" style={{ marginTop: "5px" }}>
  614. <div
  615. className="search-more"
  616. style={this.state.searchMore ? { display: "none" } : {}}
  617. > */}
  618. <span>签单时间:</span>
  619. <RangePicker
  620. value={[
  621. this.state.releaseDate[0]
  622. ? moment(this.state.releaseDate[0])
  623. : null,
  624. this.state.releaseDate[1]
  625. ? moment(this.state.releaseDate[1])
  626. : null,
  627. ]}
  628. onChange={(data, dataString) => {
  629. this.setState({ releaseDate: dataString });
  630. }}
  631. />
  632. {/* </div>
  633. </div> */}
  634. <Button
  635. type="primary"
  636. onClick={this.search}
  637. style={{ marginLeft: 10 }}
  638. >
  639. 搜索
  640. </Button>
  641. <Button onClick={this.reset}>重置</Button>
  642. {/* {adminData.isSuperAdmin?<Popconfirm title="是否删除?" onConfirm={this.delectRow} okText="是" cancelText="否">
  643. <Button type="danger" style={{marginLeft:'10px'}}
  644. disabled={!hasSelected}
  645. >删除<Icon type="minus" />
  646. </Button>
  647. </Popconfirm>:''
  648. }*/}
  649. {/* <span style={{ marginLeft: "10px", marginRight: "20px" }}>
  650. 更多搜索
  651. <Switch
  652. checked={!this.state.searchMore}
  653. onChange={this.searchSwitch}
  654. />
  655. </span> */}
  656. </div>
  657. </TabPane>
  658. <TabPane tab="操作" key="2">
  659. <div className="user-search">
  660. <AutoComplete
  661. className="certain-category-search"
  662. dropdownClassName="certain-category-search-dropdown"
  663. dropdownMatchSelectWidth={false}
  664. dropdownStyle={{ width: 120 }}
  665. style={{ width: "120px" }}
  666. dataSource={options}
  667. placeholder="输入转交人姓名"
  668. value={this.state.auto}
  669. onChange={this.httpChange}
  670. filterOption={true}
  671. onBlur={this.blurChange}
  672. onSelect={this.selectAuto}
  673. disabled={!hasSelected}
  674. >
  675. <Input />
  676. </AutoComplete>
  677. <Button
  678. type="primary"
  679. onClick={(e) => {
  680. e.stopPropagation();
  681. this.showConfirm(this.changeAssigner);
  682. }}
  683. disabled={!hasSelected}
  684. style={{ marginRight: 10 }}
  685. >
  686. 转交客户
  687. </Button>
  688. <EnterpriseNameChange
  689. type='journal'
  690. disabled={!(hasSelected && this.state.selectedRows.length === 1)}
  691. style={{ marginLeft: 10 }}
  692. enterpriseId={this.state.selectedRows[0] && this.state.selectedRows[0].id}/>
  693. </div>
  694. </TabPane>
  695. <TabPane tab="更改表格显示数据" key="3">
  696. <div style={{ marginLeft: 10 }}>
  697. <ChooseList
  698. columns={this.state.columns}
  699. changeFn={this.changeList}
  700. changeList={this.state.changeList}
  701. top={55}
  702. margin={11}
  703. />
  704. </div>
  705. </TabPane>
  706. </Tabs>
  707. <div className="patent-table">
  708. <Spin spinning={this.state.loading}>
  709. <Table
  710. size="middle"
  711. columns={
  712. this.state.changeList
  713. ? this.state.changeList
  714. : this.state.columns
  715. }
  716. dataSource={this.state.dataSource}
  717. rowSelection={rowSelection}
  718. pagination={this.state.pagination}
  719. onRowClick={this.tableRowClick}
  720. />
  721. </Spin>
  722. </div>
  723. <FollowDetail
  724. followData={this.state.followData}
  725. visitModul={this.state.visitModul}
  726. closeDesc={this.closeDesc}
  727. loadData={this.loadData}
  728. />
  729. <IntentionDetail
  730. detailApi={this.props.detailApi}
  731. IntentionData={this.state.RowData}
  732. loadData={this.loadData}
  733. modalVisible={this.state.modalVisible}
  734. defaultActiveKey={this.state.defaultActiveKey}
  735. name={this.state.modalName}
  736. closeDesc={this.closeDesc}
  737. basicState={this.state.basicState}
  738. contactState={this.state.contactState}
  739. />
  740. </div>
  741. );
  742. }
  743. }));
  744. export default IntentionCustomer;