customerProfile.jsx 20 KB

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