customerProfile.jsx 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750
  1. import React from 'react';
  2. import {
  3. Tooltip,
  4. Button,
  5. AutoComplete,
  6. Input,
  7. Select,
  8. Spin,
  9. Table,
  10. message,
  11. Form,
  12. Tabs,
  13. DatePicker,
  14. } from 'antd';
  15. import $ from 'jquery/src/ajax';
  16. import { ShowModal, } from "@/tools.js";
  17. import { industry } from "@/dataDic.js"
  18. import ShowModalDiv from "@/showModal.jsx";
  19. import { ChooseList } from "../../../order/orderNew/chooseList";
  20. import MainBusinessLog from './mainBusinessLog';
  21. import ReceiveLog from './receiveLog';
  22. import moment from 'moment';
  23. import './customer.less';
  24. const TabPane = Tabs.TabPane;
  25. const { RangePicker } = DatePicker;
  26. const IntentionCustomer = Form.create()(React.createClass({
  27. getInitialState() {
  28. return {
  29. searchInfor: {},
  30. fjlist: [],
  31. loading: false,
  32. visible: false,
  33. changeList: undefined,
  34. uid: '',
  35. receiveVisible: false,
  36. dataSource: [],
  37. pagination: {
  38. defaultCurrent: 1,
  39. defaultPageSize: 10,
  40. showQuickJumper: true,
  41. pageSize: 10,
  42. onChange: function (page) {
  43. this.loadData(page);
  44. }.bind(this),
  45. showTotal: function (total) {
  46. return '共' + total + '条数据';
  47. }
  48. },
  49. columns: [{
  50. title: '客户名称',
  51. dataIndex: 'nickname',
  52. key: 'nickname',
  53. fixed: 'left',
  54. width: 200,
  55. render: text => {
  56. return (
  57. <Tooltip title={text}>
  58. <div>{text}</div>
  59. </Tooltip>
  60. )
  61. }
  62. },
  63. {
  64. title: '客户类型',
  65. dataIndex: 'shareType',
  66. key: 'shareType',
  67. width: 100,
  68. render: text => {
  69. return (
  70. <div>{["私有客户", "公共客户", "签单客户", "外联客户"][text]}</div>
  71. )
  72. }
  73. },
  74. {
  75. title: '是否签单',
  76. dataIndex: 'signBills',
  77. key: 'signBills',
  78. width: 90,
  79. render: text => {
  80. return (
  81. <div>{["否", "是"][text]}</div>
  82. )
  83. }
  84. },
  85. {
  86. title: '联系人',
  87. dataIndex: 'contactName',
  88. key: 'contactName',
  89. width: 120,
  90. },
  91. {
  92. title: '所属人',
  93. dataIndex: 'adminName',
  94. key: 'adminName',
  95. width: 120,
  96. },
  97. {
  98. title: '意向合作项目',
  99. dataIndex: 'intendedProject',
  100. key: 'intendedProject',
  101. width: 220,
  102. },
  103. {
  104. title: '知产情况',
  105. dataIndex: 'patentCount',
  106. key: 'patentCount',
  107. width: 220,
  108. render: (text, record) => {
  109. return (
  110. <div>
  111. 专利&nbsp;{text || ''}&nbsp;
  112. 其中发明专利&nbsp;{record.inventionPatentCount}&nbsp;
  113. 实用新型&nbsp;{record.utilityModelCount}&nbsp;
  114. 外观设计&nbsp;{record.appearancePatentCount}&nbsp;
  115. 软著&nbsp;{record.softwareWorksCount}&nbsp;
  116. 标准&nbsp;<span className="num">{String(record.standard) === '1' ? '有' : String(record.standard) === '0' ? '无' : ''}</span>&nbsp;&nbsp;&nbsp;
  117. 其他类型&nbsp;{record.otherCount}
  118. </div>
  119. )
  120. }
  121. },
  122. {
  123. title: '财务数据',
  124. dataIndex: 'financialData',
  125. key: 'financialData',
  126. width: 200,
  127. },
  128. {
  129. title: '前期沟通',
  130. dataIndex: 'earlyCommunication',
  131. key: 'earlyCommunication',
  132. width: 200,
  133. },
  134. {
  135. title: '面谈思路及目的',
  136. dataIndex: 'interviewIdeas',
  137. key: 'interviewIdeas',
  138. width: 200,
  139. },
  140. {
  141. title: '更新时间',
  142. dataIndex: 'updateTime',
  143. key: 'updateTime',
  144. width: 80,
  145. },
  146. {
  147. title: '所属部门',
  148. dataIndex: 'depName',
  149. key: 'depName',
  150. width: 160,
  151. },
  152. {
  153. title: '省市区',
  154. dataIndex: 'area',
  155. key: 'area',
  156. width: 150,
  157. render: (text, record) => {
  158. return (record.province || "") + (!record.city ? "" : "-") + (record.city || "") + (!record.area ? "" : "-") + (record.area || "");
  159. },
  160. },
  161. {
  162. title: '行业',
  163. dataIndex: 'industry',
  164. key: 'industry',
  165. width: 120,
  166. },
  167. {
  168. title: '主营',
  169. dataIndex: 'businessScope',
  170. key: 'businessScope',
  171. width: 120,
  172. },
  173. {
  174. title: '母/子公司',
  175. dataIndex: 'companyCount',
  176. key: 'companyCount',
  177. width: 120,
  178. },
  179. {
  180. title: '社保人数',
  181. dataIndex: 'socialSecurityCount',
  182. key: 'socialSecurityCount',
  183. width: 120,
  184. },
  185. {
  186. title: '对外投资控股的企业数',
  187. dataIndex: 'externalInvestCount',
  188. key: 'externalInvestCount',
  189. width: 140,
  190. },
  191. {
  192. title: '对外投资控股的行业',
  193. dataIndex: 'externalInvestIndustryName',
  194. key: 'externalInvestIndustryName',
  195. width: 140,
  196. },
  197. {
  198. title: '对外投资控股的企业名称',
  199. dataIndex: 'externalInvestName',
  200. key: 'externalInvestName',
  201. width: 140,
  202. },
  203. {
  204. title: '操作',
  205. dataIndex: 'operate',
  206. key: 'operate',
  207. width: 220,
  208. render: (text, record) => {
  209. return (
  210. <div>
  211. <Button
  212. onClick={(e) => {
  213. e.stopPropagation();
  214. this.setState({
  215. visible: true,
  216. uid: record.id
  217. })
  218. }} type="primary" style={{ marginLeft: '10px' }}>主营日志</Button>
  219. <Button
  220. onClick={(e) => {
  221. e.stopPropagation();
  222. this.setState({
  223. receiveVisible: true,
  224. uid: record.id
  225. })
  226. }} type="primary" style={{ marginLeft: '10px' }}>领取日志</Button>
  227. </div>
  228. )
  229. }
  230. }
  231. ],
  232. columnsX: [
  233. {
  234. title: '客户名称',
  235. dataIndex: 'nickname',
  236. key: 'nickname',
  237. fixed: 'left',
  238. width: 200,
  239. render: text => {
  240. return (
  241. <Tooltip title={text}>
  242. <div>{text}</div>
  243. </Tooltip>
  244. )
  245. }
  246. },
  247. {
  248. title: '客户类型',
  249. dataIndex: 'shareType',
  250. key: 'shareType',
  251. render: text => {
  252. return (
  253. <div>{["私有客户", "公共客户", "签单客户", "外联客户"][text]}</div>
  254. )
  255. }
  256. },
  257. {
  258. title: '渠道类别',
  259. dataIndex: 'channelType',
  260. key: 'channelType',
  261. render: text => {
  262. return (
  263. <div>{["", "其他", "民主党派", "园区", "民间组织", "战略合作单位"][text]}</div>
  264. )
  265. }
  266. },
  267. {
  268. title: '企业数',
  269. dataIndex: 'enterpriseCount',
  270. key: 'enterpriseCount',
  271. },
  272. {
  273. title: '联系人',
  274. dataIndex: 'contactName',
  275. key: 'contactName',
  276. },
  277. {
  278. title: '所属人',
  279. dataIndex: 'adminName',
  280. key: 'adminName',
  281. },
  282. {
  283. title: '面谈项目',
  284. dataIndex: 'intendedProject',
  285. key: 'intendedProject',
  286. width: 200,
  287. },
  288. {
  289. title: '考核指标',
  290. dataIndex: 'channelIndicators',
  291. key: 'channelIndicators',
  292. width: 200,
  293. },
  294. {
  295. title: '面谈思路及目的',
  296. dataIndex: 'interviewIdeas',
  297. key: 'interviewIdeas',
  298. width: 200,
  299. },
  300. {
  301. title: '面谈人及分工',
  302. dataIndex: 'interviewDistribution',
  303. key: 'interviewDistribution',
  304. width: 200,
  305. },
  306. {
  307. title: '所属部门',
  308. dataIndex: 'depName',
  309. key: 'depName',
  310. },
  311. {
  312. title: '省市区',
  313. dataIndex: 'area',
  314. key: 'area',
  315. width: 150,
  316. render: (text, record) => {
  317. return (record.province || "") + (!record.city ? "" : "-") + (record.city || "") + (!record.area ? "" : "-") + (record.area || "");
  318. },
  319. },
  320. {
  321. title: '操作',
  322. dataIndex: 'id',
  323. key: 'id',
  324. render: text => {
  325. return (
  326. <div>
  327. <Button
  328. onClick={(e) => {
  329. e.stopPropagation();
  330. this.setState({
  331. visible: true,
  332. uid: text
  333. })
  334. }} type="primary" style={{ marginLeft: '10px' }}>主营日志</Button>
  335. </div>
  336. )
  337. }
  338. }
  339. ],
  340. dataSource: [],
  341. };
  342. },
  343. componentWillMount() {
  344. this.loadData();
  345. },
  346. componentWillReceiveProps(nextProps) {
  347. if (nextProps.newChannel !== this.props.newChannel) {
  348. this.setState({
  349. changeList: undefined
  350. })
  351. this.reset();
  352. }
  353. },
  354. loadData(pageNo) {
  355. const { searchInfor, pagination } = this.state;
  356. this.setState({
  357. loading: true,
  358. });
  359. let datas = Object.assign(searchInfor, {
  360. newChannel: this.props.newChannel,
  361. pageNo: pageNo || 1,
  362. pageSize: pagination.pageSize,
  363. });
  364. $.ajax({
  365. method: "get",
  366. dataType: "json",
  367. crossDomain: false,
  368. url: globalConfig.context + "/api/admin/userArchives/selectUserArchives",
  369. data: datas,
  370. success: function (data) {
  371. ShowModal(this);
  372. this.setState({
  373. loading: false,
  374. });
  375. if (data.error && data.error.length === 0) {
  376. if (data.data.list) {
  377. pagination.current = data.data.pageNo;
  378. pagination.total = data.data.totalCount;
  379. if (data.data && data.data.list && !data.data.list.length) {
  380. pagination.current = 0;
  381. pagination.total = 0;
  382. }
  383. this.setState({
  384. dataSource: data.data.list,
  385. pagination: this.state.pagination,
  386. pageNo: data.data.pageNo,
  387. });
  388. } else {
  389. this.setState({
  390. dataSource: data.data,
  391. pagination: false,
  392. });
  393. }
  394. } else {
  395. message.warning(data.error[0].message);
  396. }
  397. }.bind(this),
  398. }).always(
  399. function () {
  400. this.setState({
  401. loading: false,
  402. });
  403. }.bind(this)
  404. );
  405. },
  406. followUp(e) {
  407. const { searchInfor } = this.state;
  408. this.setState({
  409. searchInfor: Object.assign(searchInfor, {
  410. aname: e,
  411. }),
  412. });
  413. $.ajax({
  414. method: "get",
  415. dataType: "json",
  416. crossDomain: false,
  417. url: globalConfig.context + "/api/admin/customer/listAdminByName",
  418. data: {
  419. adminName: e,
  420. },
  421. success: function (data) {
  422. let thedata = data.data;
  423. if (!thedata) {
  424. if (data.error && data.error.length) {
  425. message.warning(data.error[0].message);
  426. }
  427. thedata = {};
  428. }
  429. this.setState({
  430. fjlist: thedata,
  431. });
  432. }.bind(this),
  433. }).always(
  434. function () {
  435. this.setState({
  436. loading: false,
  437. });
  438. }.bind(this)
  439. );
  440. },
  441. selectF(value) {
  442. const { searchInfor, fjlist } = this.state;
  443. const newdataSources = JSON.stringify(fjlist) == "{}" ? [] : fjlist;
  444. this.setState({
  445. searchInfor: Object.assign(searchInfor, {
  446. aid: newdataSources.find((item) => item.name == value).id,
  447. }),
  448. });
  449. },
  450. changeList(arr) {
  451. const newArr = [];
  452. let list = this.props.newChannel == 1
  453. ? this.state.columnsX
  454. : this.state.columns
  455. list.forEach((item) => {
  456. arr.forEach((val) => {
  457. if (val === item.title) {
  458. newArr.push(item);
  459. }
  460. });
  461. });
  462. this.setState({
  463. changeList: newArr,
  464. });
  465. },
  466. exportAll() {
  467. message.config({
  468. duration: 20,
  469. });
  470. let loading = message.loading("下载中...");
  471. this.setState({
  472. exportPendingLoading: true,
  473. });
  474. let data = JSON.parse(JSON.stringify(this.state.searchInfor));
  475. $.ajax({
  476. method: "get",
  477. dataType: "json",
  478. crossDomain: false,
  479. url: "/api/admin/userArchives/selectUserArchives/export",
  480. data,
  481. success: function (data) {
  482. if (data.error.length === 0) {
  483. this.download(data.data);
  484. } else {
  485. message.warning(data.error[0].message);
  486. }
  487. }.bind(this),
  488. }).always(
  489. function () {
  490. loading();
  491. this.setState({
  492. exportPendingLoading: false,
  493. });
  494. }.bind(this)
  495. );
  496. },
  497. download(fileName) {
  498. window.location.href =
  499. globalConfig.context + "/open/download?fileName=" + fileName;
  500. },
  501. search() {
  502. this.loadData();
  503. },
  504. reset() {
  505. this.setState({
  506. searchInfor: JSON.parse(JSON.stringify({})),
  507. }, () => {
  508. this.loadData();
  509. })
  510. },
  511. render() {
  512. const { searchInfor } = this.state
  513. const { newChannel } = this.props
  514. const newdataSources =
  515. JSON.stringify(this.state.fjlist) == "{}" ? [] : this.state.fjlist;
  516. const newoptions = newdataSources.map((group) => (
  517. <Select.Option key={group.id} value={group.name}>
  518. {group.name}
  519. </Select.Option>
  520. ));
  521. return (
  522. <div className="user-content">
  523. <ShowModalDiv ShowModal={this.state.showModal} onClose={() => { this.setState({ showModal: false }) }} />
  524. <div className="content-title" style={{ marginBottom: 10 }}>
  525. <span style={{ fontWeight: 900, fontSize: 16 }}>{newChannel == 1 ? "渠道档案汇总" : "客户档案汇总"}</span>
  526. </div>
  527. <div className="user-search">
  528. <Tabs
  529. defaultActiveKey="1"
  530. className="test">
  531. <TabPane tab="搜索" key="1" style={{ paddingTop: '10px' }}>
  532. <Input
  533. placeholder={newChannel == 1 ? "渠道名称" : "客户名称"}
  534. value={searchInfor.name || undefined}
  535. style={{ width: 150, marginRight: 10 }}
  536. onChange={e => {
  537. this.setState({
  538. searchInfor: Object.assign(searchInfor, {
  539. name: e.target.value,
  540. }),
  541. });
  542. }}
  543. />
  544. <AutoComplete
  545. className="certain-category-search"
  546. dropdownClassName="certain-category-search-dropdown"
  547. dropdownMatchSelectWidth={false}
  548. style={{ width: "150px" }}
  549. dataSource={newoptions}
  550. placeholder="所属人"
  551. value={searchInfor.aname || undefined}
  552. onChange={this.followUp.bind(this)}
  553. filterOption={true}
  554. onSelect={this.selectF.bind(this)}
  555. >
  556. <Input />
  557. </AutoComplete>
  558. {newChannel == 1 &&
  559. <Select
  560. mode="multiple"
  561. placeholder={"请选择渠道类别"}
  562. style={{ width: 200 }}
  563. value={searchInfor.channelType ? searchInfor.channelType.split(",") : undefined}
  564. onChange={(e) => {
  565. this.setState({
  566. searchInfor: Object.assign(searchInfor, {
  567. channelType: e.toString(),
  568. }),
  569. });
  570. }}
  571. >
  572. {[
  573. { name: "民主党派", val: 2 },
  574. { name: "园区", val: 3 },
  575. { name: "民间组织", val: 4 },
  576. { name: "战略合作单位", val: 5 },
  577. { name: "其他", val: 1 },].map((it, ins) => (
  578. <Option key={it.val}>{it.name}</Option>
  579. ))}
  580. </Select>}
  581. {newChannel == 0 && <Input
  582. placeholder="产品关键字"
  583. value={searchInfor.businessScope || undefined}
  584. style={{ width: 150, marginRight: 10 }}
  585. onChange={e => {
  586. this.setState({
  587. searchInfor: Object.assign(searchInfor, {
  588. businessScope: e.target.value,
  589. }),
  590. });
  591. }}
  592. />}
  593. {newChannel == 0 &&
  594. <Select
  595. mode="multiple"
  596. placeholder={"请选择行业"}
  597. style={{ width: 150 }}
  598. value={searchInfor.industry ? searchInfor.industry.split(",") : undefined}
  599. onChange={(e) => {
  600. this.setState({
  601. searchInfor: Object.assign(searchInfor, {
  602. industry: e.toString(),
  603. }),
  604. });
  605. }}
  606. >
  607. {industry.map((it, ins) => (
  608. <Option key={it.value}>{it.key}</Option>
  609. ))}
  610. </Select>}
  611. <Select
  612. placeholder={"请选择客户类型"}
  613. style={{ width: 150 }}
  614. value={searchInfor.shareType}
  615. onChange={(e) => {
  616. this.setState({
  617. searchInfor: Object.assign(searchInfor, {
  618. shareType: e,
  619. }),
  620. });
  621. }}
  622. >
  623. <Option value="">全部客户</Option>
  624. <Option value="0">私有客户</Option>
  625. <Option value="1">公共客户</Option>
  626. <Option value="2">签单客户</Option>
  627. <Option value="3">外联客户</Option>
  628. <Option value="4">私有&签单</Option>
  629. </Select>
  630. <Select
  631. placeholder={"是否签单"}
  632. style={{ width: 100 }}
  633. value={searchInfor.signBills}
  634. onChange={(e) => {
  635. this.setState({
  636. searchInfor: Object.assign(searchInfor, {
  637. signBills: e,
  638. }),
  639. });
  640. }}
  641. >
  642. <Option value="0">否</Option>
  643. <Option value="1">是</Option>
  644. </Select>
  645. <span>更新时间: </span>
  646. <RangePicker
  647. style={{ width: 300 }}
  648. value={[
  649. searchInfor.startTime ? moment(searchInfor.startTime) : null,
  650. searchInfor.endTime ? moment(searchInfor.endTime) : null,
  651. ]}
  652. onChange={(data, dataString) => {
  653. this.setState({
  654. searchInfor: Object.assign(searchInfor, {
  655. startTime: dataString[0],
  656. endTime: dataString[1],
  657. }),
  658. });
  659. }}
  660. />
  661. <Button type="primary" onClick={this.search} style={{ marginRight: 10 }}>
  662. 搜索
  663. </Button>
  664. <Button onClick={this.reset}>重置</Button>
  665. </TabPane>
  666. <TabPane tab="更改表格显示数据" key="2">
  667. <div style={{ marginLeft: 10 }}>
  668. <ChooseList
  669. columns={newChannel == 1 ? this.state.columnsX : this.state.columns}
  670. changeFn={this.changeList}
  671. changeList={this.state.changeList}
  672. top={55}
  673. margin={11}
  674. />
  675. </div>
  676. </TabPane>
  677. <TabPane tab="导出EXCEL" key="3">
  678. <Button
  679. type="primary"
  680. loading={this.state.exportPendingLoading}
  681. onClick={this.exportAll}
  682. style={{ margin: 10 }}
  683. >
  684. 导出excel
  685. </Button>
  686. </TabPane>
  687. </Tabs>
  688. </div>
  689. <div className="patent-table">
  690. <Spin spinning={this.state.loading}>
  691. <Table
  692. columns={this.state.changeList
  693. ? this.state.changeList
  694. : newChannel == 1
  695. ? this.state.columnsX
  696. : this.state.columns}
  697. dataSource={this.state.dataSource}
  698. pagination={this.state.pagination}
  699. bordered
  700. scroll={{ x: newChannel == 0 ? "140%" : "130%" }}
  701. />
  702. </Spin>
  703. </div>
  704. {this.state.visible &&
  705. <MainBusinessLog
  706. visible={this.state.visible}
  707. uid={this.state.uid}
  708. onCancel={() => {
  709. this.setState({
  710. visible: false,
  711. uid: ''
  712. })
  713. }}
  714. />}
  715. { this.state.receiveVisible && (
  716. <ReceiveLog
  717. visible={this.state.receiveVisible}
  718. uid={this.state.uid}
  719. onCancel={() => {
  720. this.setState({
  721. receiveVisible: false,
  722. uid: ''
  723. })
  724. }}
  725. />
  726. ) }
  727. </div>
  728. );
  729. }
  730. }));
  731. export default IntentionCustomer;