index.jsx 13 KB

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