index.jsx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  1. import React, { Component } from "react";
  2. import { Table, Spin, Button, message, Select, Modal, Icon } from "antd";
  3. import $ from "jquery/src/ajax";
  4. import moment from 'moment';
  5. import "./index.less";
  6. class Outbound extends Component {
  7. constructor(props) {
  8. super(props);
  9. this.state = {
  10. loading: false,
  11. pVisible: false,
  12. rVisible: false,
  13. tVisible: false,
  14. status: false,
  15. id: null,
  16. uList: [],
  17. tList: [],
  18. transAgent: "",
  19. mobile: '',
  20. info: {},
  21. dataSource: [],
  22. pagination: {
  23. defaultCurrent: 1,
  24. defaultPageSize: 10,
  25. showQuickJumper: true,
  26. pageSize: 10,
  27. onChange: function (page) {
  28. this.userCallList(page);
  29. }.bind(this),
  30. showTotal: function (total) {
  31. return '共' + total + '条数据';
  32. }
  33. },
  34. columns: [
  35. {
  36. title: '通话人',
  37. dataIndex: 'adminName',
  38. key: 'adminName',
  39. },
  40. {
  41. title: '联系人',
  42. dataIndex: 'contacts',
  43. key: 'contacts',
  44. },
  45. {
  46. title: '电话(尾号)',
  47. dataIndex: 'mobileLastDigits',
  48. key: 'mobileLastDigits',
  49. width: 100,
  50. },
  51. {
  52. title: '时长',
  53. dataIndex: 'duration',
  54. key: 'duration',
  55. render: (text) => {
  56. return this.isTime(text)
  57. }
  58. },
  59. {
  60. title: '时间',
  61. dataIndex: 'createTime',
  62. key: 'createTime',
  63. },
  64. ],
  65. };
  66. this.onOk = this.onOk.bind(this);
  67. this.blindTransferByAgent = this.blindTransferByAgent.bind(this);
  68. this.webSocket = null;
  69. }
  70. componentDidMount() {
  71. }
  72. componentWillUnmount() {
  73. }
  74. isTime(second) {
  75. let time = "0秒"
  76. if (second > 3600) {
  77. time = moment.utc(second * 1000).format('h小时m分s秒')
  78. } else if (second > 60) {
  79. time = moment.utc(second * 1000).format('m分s秒')
  80. } else {
  81. time = moment.utc(second * 1000).format('s秒')
  82. }
  83. return time
  84. }
  85. getWebSocket() {
  86. const _this = this
  87. if (typeof (WebSocket) == "undefined") {
  88. console.log('\x1b[31m您的浏览器不支持WebSocket\x1b[0m')
  89. } else {
  90. console.log('\x1b[32m您的浏览器支持WebSocket\x1b[0m')
  91. }
  92. // 测试
  93. // this.webSocket = new WebSocket('ws://uat.jishutao.com/webSocketServer');
  94. // 生产
  95. this.webSocket = new WebSocket('wss://bm.jishutao.com/webSocketServer');
  96. // 处理WebSocket打开事件
  97. this.webSocket.onopen = () => {
  98. console.log('WebSocke已打开');
  99. };
  100. // 处理收到消息的事件
  101. this.webSocket.onmessage = (event) => {
  102. const newMessage = event.data;
  103. console.log('WebSocke已连接', newMessage);
  104. _this.setState({
  105. status: false
  106. })
  107. // const newMessage = event.data;
  108. // this.setState((prevState) => ({
  109. // messages: [...prevState.messages, newMessage],
  110. // }));
  111. if (this.webSocket) {
  112. console.log("关闭WebSocket连接")
  113. this.webSocket.close();
  114. }
  115. };
  116. // 处理WebSocket关闭事件
  117. this.webSocket.onclose = () => {
  118. console.log('WebSocket已关闭');
  119. _this.setState({
  120. status: false
  121. })
  122. };
  123. // 处理WebSocket错误事件
  124. this.webSocket.onerror = (error) => {
  125. console.error('WebSocket出错了', error);
  126. _this.setState({
  127. status: false
  128. })
  129. };
  130. }
  131. onOk() {
  132. const { uid } = this.props
  133. this.setState({
  134. status: true,
  135. id: uid,
  136. })
  137. this.callNumber()
  138. }
  139. // 公共库-默认联系人
  140. getDefaultMobile() {
  141. const { uid } = this.props
  142. $.ajax({
  143. method: "get",
  144. dataType: "json",
  145. crossDomain: false,
  146. url: globalConfig.context + "/api/admin/userOutbound/getDefaultMobile",
  147. data: {
  148. uid,
  149. }
  150. }).done(function (data) {
  151. if (!data.error.length) {
  152. if (data.data) {
  153. let mobile = data.data.mobile
  154. this.setState({
  155. pVisible: true,
  156. mobile,
  157. })
  158. } else {
  159. message.warning("暂无查询到联系人号码~")
  160. }
  161. } else {
  162. message.warning(data.error[0].message);
  163. };
  164. }.bind(this));
  165. }
  166. // 私有-客户联系方式列表
  167. findCustomerContacts() {
  168. const { uid, isOwn = 0 } = this.props
  169. // isOwn
  170. $.ajax({
  171. method: "get",
  172. dataType: "json",
  173. crossDomain: false,
  174. url: globalConfig.context + "/api/admin/customer/findCustomerContacts",
  175. data: {
  176. uid,
  177. type: isOwn,
  178. }
  179. }).done(function (data) {
  180. if (!data.error.length) {
  181. let list = data.data || [];
  182. let mobile = "";
  183. if (list && list.length > 0) {
  184. for (var i = 0; i < list.length; i++) {
  185. if (list[i].major == 1) {
  186. mobile = list[i].mobile
  187. }
  188. }
  189. }
  190. this.setState({
  191. pVisible: true,
  192. mobile: mobile,
  193. uList: list,
  194. })
  195. } else {
  196. message.warning(data.error[0].message);
  197. };
  198. }.bind(this));
  199. }
  200. // 转移列表
  201. agentList() {
  202. $.ajax({
  203. method: "get",
  204. dataType: "json",
  205. crossDomain: false,
  206. url: globalConfig.context + "/api/admin/userOutbound/agentList",
  207. data: {}
  208. }).done(function (data) {
  209. if (!data.error.length) {
  210. let newList = data.data || []
  211. this.setState({
  212. transAgent: newList[0].callNo,
  213. tList: newList
  214. })
  215. } else {
  216. message.warning(data.error[0].message);
  217. };
  218. }.bind(this));
  219. }
  220. // 呼叫
  221. callNumber() {
  222. const { uid } = this.props
  223. const { mobile } = this.state
  224. $.ajax({
  225. method: "post",
  226. dataType: "json",
  227. crossDomain: false,
  228. url: globalConfig.context + "/api/admin/userOutbound/callNumber",
  229. data: {
  230. uid,
  231. callee: mobile,
  232. }
  233. }).done(function (data) {
  234. if (!data.error.length) {
  235. this.setState({
  236. pVisible: false
  237. })
  238. message.success(data.data)
  239. } else {
  240. this.setState({
  241. status: false,
  242. id: null,
  243. })
  244. this.webSocket.close();
  245. message.warning(data.error[0].message);
  246. };
  247. }.bind(this));
  248. }
  249. // 呼叫转移
  250. blindTransferByAgent() {
  251. const { transAgent } = this.state
  252. const _this = this
  253. $.ajax({
  254. method: "post",
  255. dataType: "json",
  256. crossDomain: false,
  257. url: globalConfig.context + "/api/admin/userOutbound/blindTransferByAgent",
  258. data: {
  259. transAgent,
  260. }
  261. }).done(function (data) {
  262. if (!data.error.length) {
  263. _this.setState({
  264. tVisible: false
  265. })
  266. message.success(data.data)
  267. } else {
  268. message.warning(data.error[0].message);
  269. };
  270. }.bind(this));
  271. }
  272. // 通话记录
  273. userCallList(pageNo) {
  274. const { pagination } = this.state;
  275. const { uid } = this.props
  276. this.setState({
  277. loading: true,
  278. });
  279. $.ajax({
  280. method: "get",
  281. dataType: "json",
  282. crossDomain: false,
  283. url: globalConfig.context + "/api/admin/userOutbound/userCallList",
  284. data: {
  285. uid,
  286. pageNo: pageNo || 1,
  287. pageSize: pagination.pageSize,
  288. },
  289. success: function (data) {
  290. this.setState({
  291. loading: false,
  292. });
  293. if (data.error && data.error.length === 0) {
  294. if (data.data.page.list) {
  295. pagination.current = data.data.page.pageNo;
  296. pagination.total = data.data.page.totalCount;
  297. if (data.data.page && data.data.page.list && !data.data.page.list.length) {
  298. pagination.current = 0;
  299. pagination.total = 0;
  300. }
  301. this.setState({
  302. dataSource: data.data.page.list,
  303. pagination: this.state.pagination,
  304. pageNo: data.data.pageNo,
  305. info: data.data.sum
  306. });
  307. } else {
  308. this.setState({
  309. dataSource: data.data,
  310. pagination: false,
  311. });
  312. }
  313. } else {
  314. message.warning(data.error[0].message);
  315. }
  316. }.bind(this),
  317. }).always(
  318. function () {
  319. this.setState({
  320. loading: false,
  321. });
  322. }.bind(this)
  323. );
  324. }
  325. render() {
  326. const { id, status, pVisible, rVisible, tVisible, transAgent, tList, mobile, uList } = this.state
  327. const { type, uid, noTransfer = false } = this.props
  328. //noTransfer
  329. //type= history 只查看呼叫记录
  330. //type= private 私有呼叫
  331. //type= public 公共库呼叫
  332. return (
  333. <span>
  334. {type != "history" &&
  335. <Button
  336. style={{ background: ((id == uid) && status) ? "red" : "green", border: 0 }}
  337. type="primary"
  338. loading={pVisible}
  339. onClick={() => {
  340. if (status) {
  341. return
  342. }
  343. this.getWebSocket();
  344. type == "public"
  345. ? this.getDefaultMobile()
  346. : this.findCustomerContacts()
  347. }}
  348. >{!pVisible && <Icon type="phone" />} {((id == uid) && status) ? '正在通话中' : '呼叫'}</Button>}
  349. {type == "private" && status && (id == uid) && !noTransfer &&
  350. <Button
  351. style={{ background: "green", border: 0, marginLeft: 20 }}
  352. type="primary"
  353. onClick={() => {
  354. this.agentList();
  355. this.setState({ tVisible: true })
  356. }}
  357. ><Icon type="phone" /> 呼叫转移</Button>}
  358. <Button
  359. style={{ background: "green", border: 0, marginLeft: 20 }}
  360. type="primary"
  361. onClick={() => {
  362. this.userCallList();
  363. this.setState({ rVisible: true })
  364. }}
  365. ><Icon type="phone" /> 历史记录</Button>
  366. <Modal
  367. title="联系人电话"
  368. width={420}
  369. visible={pVisible}
  370. maskClosable={false}
  371. okText="呼叫"
  372. onOk={this.onOk}
  373. onCancel={() => {
  374. this.setState({
  375. pVisible: false
  376. })
  377. }}
  378. >
  379. <div className="contacts" style={{ position: "relative" }}>
  380. <Select
  381. style={{ width: 200 }}
  382. value={mobile}
  383. onChange={e => {
  384. this.setState({
  385. mobile: e
  386. })
  387. }}
  388. >
  389. {
  390. uList.map(item =>
  391. <Select.Option value={item.mobile} key={item.id}>{item.mobile}</Select.Option>
  392. )
  393. }
  394. </Select>
  395. {uList.length > 1 && <span style={{ color: 'red', position: "absolute", right: 0, top: 4 }}>有多电话可选!</span>}
  396. </div>
  397. </Modal>
  398. <Modal
  399. title="呼叫转移"
  400. width={420}
  401. visible={tVisible}
  402. maskClosable={false}
  403. okText="呼叫转移"
  404. onOk={this.blindTransferByAgent}
  405. onCancel={() => {
  406. this.setState({
  407. tVisible: false
  408. })
  409. }}
  410. >
  411. <div className="contacts">
  412. <Select
  413. style={{ width: 200 }}
  414. value={transAgent}
  415. onChange={(e) => {
  416. this.setState({
  417. transAgent: e
  418. })
  419. }}
  420. >
  421. {
  422. tList.map(item =>
  423. <Select.Option value={item.callNo} key={item.id}>{item.name}</Select.Option>
  424. )
  425. }
  426. </Select>
  427. </div>
  428. </Modal>
  429. <Modal
  430. title="历史记录"
  431. width={600}
  432. visible={rVisible}
  433. maskClosable={false}
  434. onCancel={() => {
  435. this.setState({
  436. rVisible: false
  437. })
  438. }}
  439. footer={null}
  440. >
  441. <div>
  442. <div style={{ marginBottom: 5 }}>公司名称:{this.state.info.name}</div>
  443. <div style={{ marginBottom: 10 }}>累计通话次数:{this.state.info.callCount}次&nbsp;&nbsp;&nbsp;&nbsp;通话时长:{this.isTime(this.state.info.callDuration)}</div>
  444. <Spin spinning={this.state.loading}>
  445. <Table
  446. size="middle"
  447. columns={this.state.columns}
  448. dataSource={this.state.dataSource}
  449. pagination={this.state.pagination}
  450. />
  451. </Spin>
  452. </div>
  453. </Modal>
  454. </span>
  455. );
  456. }
  457. }
  458. export default Outbound;