足力健前端,vue版本

index.vue 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544
  1. <template>
  2. <div class="dialplate">
  3. <div class="plate">
  4. <!-- 拨号盘 -->
  5. <el-input
  6. v-model="telNumber"
  7. class="tel_input"
  8. autofocus
  9. maxlength="12"
  10. @keyup.native="callOutInput"
  11. @keyup.enter.native="callOut"
  12. />
  13. <i v-show="isShowDelNum" class="del_num" @click="delNum" />
  14. <el-row v-for="(item, index) in dialNums" :gutter="20" :key="index">
  15. <el-col v-for="(tnum, index) in item" :span="8" :key="index">
  16. <el-button class="btn_nums" type="info" circle @click="dialNumHandler(tnum)">{{ tnum }}</el-button>
  17. </el-col>
  18. </el-row>
  19. <el-button v-waves class="btn_call" type="success" round @click="callOut">拨打</el-button>
  20. <!-- 右侧 通话记录和通讯录 -->
  21. <svg-icon v-popover:popover class="btn_yonghu" icon-class="yonghu" />
  22. <el-popover
  23. ref="popover"
  24. :value="telIsVisCallout"
  25. visible-arrow
  26. popper-class="phone_lists"
  27. placement="right-end"
  28. width="396"
  29. trigger="click"
  30. transition="fade-in-linear"
  31. >
  32. <!-- @show="getTelHisList" -->
  33. <el-tabs v-model="tabActiveName" stretch class="phnoe_tabs" @tab-click="handleClick">
  34. <el-input v-model="s_keywords" size="mini" placeholder="搜索" prefix-icon="el-icon-search" />
  35. <el-tab-pane label="历史记录" name="first">
  36. <div class="h_list_title">
  37. <span>最近通话</span>
  38. <el-tooltip effect="dark" content="点击查看是否有工单" placement="right">
  39. <svg-icon icon-class="eye" @click.native="showOrderIcon" />
  40. </el-tooltip>
  41. </div>
  42. <el-scrollbar
  43. v-loading="loading1"
  44. element-loading-background="transparent"
  45. style="height: 300px;"
  46. >
  47. <ul v-if="recentCalls.length" class="recent_calls_lists">
  48. <li v-for="item in recentCalls" :key="item.id" class="recent_calls_item clearfix">
  49. <div class="recent_calls_item_left" @click="recentCallOut(item.tel)">
  50. <svg-icon v-show="item.isCallOut" icon-class="huchu" />
  51. <p :class="{ name_state: !item.isConect }" class="recent_calls_item_name">
  52. <span>{{ item.name }}</span>
  53. <span v-if="item.isConect">| {{ item.callTimes | secondToDuring }}</span>
  54. </p>
  55. <p class="recent_calls_item_tel">{{ item.tel | telFilter }}</p>
  56. </div>
  57. <div class="recent_calls_item_right">
  58. <span class="recent_calls_item_time">{{ item.time | timesAgo }}</span>
  59. <el-tooltip
  60. v-show="isShowOrderIcon"
  61. v-if="item.isOrder"
  62. effect="dark"
  63. content="点击查看工单"
  64. placement="right"
  65. >
  66. <svg-icon icon-class="xiangmu1" @click.native="goOrderList(item.tel)" />
  67. </el-tooltip>
  68. </div>
  69. </li>
  70. </ul>
  71. <p v-else class="text_center">没有找到数据···</p>
  72. </el-scrollbar>
  73. </el-tab-pane>
  74. <el-tab-pane label="通讯录" name="second">
  75. <el-scrollbar
  76. v-loading="loading2"
  77. element-loading-background="transparent"
  78. style="height: 320px;"
  79. >
  80. <ul v-if="phoneLists.length" class="recent_calls_lists">
  81. <li
  82. v-for="(item, index) in phoneLists"
  83. :key="index"
  84. class="recent_calls_item clearfix"
  85. >
  86. <div class="recent_calls_item_left" @click="recentCallOut(item.tel)">
  87. <p class="recent_calls_item_name">{{ item.name }}</p>
  88. <p class="recent_calls_item_tel">{{ item.tel | telFilter }}</p>
  89. </div>
  90. </li>
  91. </ul>
  92. <p v-else class="text_center">没有找到数据···</p>
  93. </el-scrollbar>
  94. </el-tab-pane>
  95. </el-tabs>
  96. </el-popover>
  97. </div>
  98. </div>
  99. </template>
  100. <script>
  101. import store from '@/store'
  102. import router from '@/router'
  103. import { mapGetters } from 'vuex'
  104. import { Send } from '@/utils/telWebsocket'
  105. import { getCallOutprefix } from '@/api/teloperation'
  106. // import { getOrderLists } from '@/api/memberManagement/memberList'
  107. import { getOrderLists } from '@/api/memberManagement/memberList'
  108. import { getCurentCallRecords } from '@/api/teloperation'
  109. import { secondToDuring, timesAgo } from '@/filters'
  110. import { getNowDate, getPreDate } from '@/utils'
  111. export default {
  112. name: 'Dialplate',
  113. filters: {
  114. telFilter (val) {
  115. if (!val.includes('-')) {
  116. if (val.length === 12) {
  117. val = val.substring(1, 4) + '-' + val.substring(4, 8) + '-' + val.substring(8, 12)
  118. } else if (val.length === 11) {
  119. val = val.substring(0, 3) + '-' + val.substring(3, 7) + '-' + val.substring(7, 11)
  120. }
  121. }
  122. return val
  123. }
  124. },
  125. data () {
  126. return {
  127. loading1: false,
  128. loading2: false,
  129. telNumber: '',
  130. scoketDatas: '',
  131. isShowDelNum: false,
  132. dialNums: [
  133. ['1', '2', '3'],
  134. ['4', '5', '6'],
  135. ['7', '8', '9'],
  136. ['*', '0', '#']
  137. ],
  138. tabActiveName: 'second',
  139. s_keywords: '',
  140. pageParams: {
  141. pageindex: 1, // 当前第几页
  142. pagesize: Number(this.$store.getters.serverConfig.PAGESIZE), // 每页几条数据
  143. total: 0 // 总共多少数据
  144. },
  145. isShowOrderIcon: false,
  146. phoneLists: [],
  147. recentCalls: []
  148. }
  149. },
  150. computed: {
  151. ...mapGetters([
  152. 'usercode', // 工号
  153. 'extension', // 分机号
  154. 'sidebar',
  155. 'avatar',
  156. 'telCallType', // 通话类型
  157. 'telIsVisCallout' // 外呼面板是否显示
  158. ])
  159. },
  160. watch: {
  161. telIsVisCallout: function (newVal, oldVal) {
  162. if (newVal) {
  163. this.tabActiveName = 'first'
  164. }
  165. }
  166. },
  167. created () {
  168. document.onkeyup = (e) => {
  169. if (e.keyCode === 13) {
  170. if (this.tabActiveName === 'first') {
  171. // this.getTelHisList()
  172. } else if (this.tabActiveName === 'second') {
  173. this.getMailList()
  174. }
  175. }
  176. }
  177. },
  178. methods: {
  179. // 获取通话历史记录
  180. getTelHisList () {
  181. this.loading1 = true
  182. const stime = getPreDate(3600 * 1000 * 24 * 7) // 不传参数是30天前
  183. const etime = getNowDate()
  184. const params = {
  185. stime, // 开始时间
  186. etime, // 结束时间
  187. keyword: this.s_keywords // 否 string 模糊查询(呼叫号码)
  188. }
  189. getCurentCallRecords(params).then(res => {
  190. this.loading1 = false
  191. this.recentCalls = []
  192. if (res.state.toLowerCase() === 'success') {
  193. const resItems = res.data.rows
  194. if (resItems && resItems.length) {
  195. resItems.forEach(element => {
  196. this.recentCalls.push({
  197. id: element.id,
  198. name: element.name || '未知', // 姓名 默认 未知
  199. tel: element.callnumber, // '15235457489' 呼叫号码
  200. time: element.endtime, // '16:00' 挂机时间
  201. isCallOut: element.calltype === 1, // 是否是呼出 "calltype": 1,//呼叫类型:0呼入,1呼出
  202. isOrder: element.existorder !== '无', // 是否有工单
  203. isConect: element.callstate === 1, // 是否正常接通 //呼叫状态:0未接通,1已接通
  204. callTimes: element.longs_talk// 通话时长
  205. })
  206. })
  207. }
  208. }
  209. })
  210. },
  211. // 获取通讯录
  212. getMailList () {
  213. this.loading2 = true
  214. const params = {
  215. pageindex: this.pageParams.pageindex, // 第几页
  216. pagesize: this.pageParams.pagesize, // 每页几条信息
  217. keyword: this.s_keywords // 否 string 模糊查询(姓名,手机号码,固话)
  218. }
  219. getOrderLists(params).then(res => {
  220. this.loading2 = false
  221. this.phoneLists = []
  222. if (res.state.toLowerCase() === 'success') {
  223. if (res.rows) {
  224. this.pageParams.total = res.rows.Totals
  225. if (res.rows.Rows && res.rows.Rows) {
  226. res.rows.Rows.forEach(val => {
  227. this.phoneLists.push({
  228. name: val.F_Name,
  229. tel: val.F_Phone
  230. })
  231. })
  232. }
  233. }
  234. }
  235. })
  236. },
  237. // 点击拨号键
  238. dialNumHandler (tnum) {
  239. this.isShowDelNum = true
  240. if (this.telNumber.length === 12) {
  241. this.$message({
  242. message: '电话号码不能超过12位!',
  243. type: 'warning'
  244. })
  245. return
  246. }
  247. this.telNumber += tnum
  248. // store.dispatch('ChangeCallNum', this.telNumber);
  249. },
  250. callOutInput () {
  251. this.isShowDelNum = true
  252. if (this.telNumber.length === 0) {
  253. this.isShowDelNum = false
  254. }
  255. if (this.telNumber.length === 12) {
  256. this.$message({
  257. message: '电话号码不能超过12位!',
  258. type: 'warning'
  259. })
  260. return
  261. }
  262. // store.dispatch('ChangeCallNum', this.telNumber);
  263. },
  264. // 删除电话号码
  265. delNum () {
  266. this.telNumber = this.telNumber.substr(0, this.telNumber.length - 1)
  267. if (this.telNumber.length === 0) {
  268. this.isShowDelNum = false
  269. }
  270. // store.dispatch('ChangeCallNum', this.telNumber);
  271. },
  272. // 外呼
  273. callOut () {
  274. if (this.telNumber) {
  275. getCallOutprefix(this.telNumber).then(response => {
  276. if (response.state.toLowerCase() === 'success') {
  277. const res = response.data
  278. switch (this.telCallType) {
  279. case 'MakeCall':
  280. this.scoketDatas = {
  281. 'Type': this.telCallType,
  282. 'AgentID': this.usercode,
  283. 'AgentExten': this.extension,
  284. 'Header': res.fix, // 号码前缀 用于截断前缀得到真实号码
  285. 'DestinationNumber': res.phone //
  286. }
  287. break
  288. case 'Meeting':
  289. this.scoketDatas = {
  290. 'Type': this.telCallType,
  291. 'AgentID': this.usercode,
  292. 'AgentExten': this.extension,
  293. 'DestinationNumber': res.phone // 会议目标号码
  294. }
  295. break
  296. case 'Transfer':
  297. this.scoketDatas = {
  298. 'Type': this.telCallType,
  299. 'AgentID': this.usercode,
  300. 'AgentExten': this.extension,
  301. 'DestinationNumber': res.phone // 转移目标号码
  302. }
  303. break
  304. // case 'Consult': // 协商呼叫
  305. // this.scoketDatas = {
  306. // 'Type': this.telCallType,
  307. // 'AgentID': this.usercode,
  308. // 'AgentExten': this.extension,
  309. // 'Callee': res.phone, // 对方号码
  310. // 'Caller': this.extension // 自己的号码(分机号)
  311. // }
  312. // break
  313. default:
  314. break
  315. }
  316. store.dispatch('ChangeCallNum', this.telNumber)
  317. Send(this.scoketDatas)
  318. store.dispatch('UpdateCalloutScreen', !this.telIsVisCallout)// 关闭外呼面板
  319. this.telNumber=''
  320. }
  321. })
  322. } else {
  323. this.$message({
  324. message: '请先输入电话号码!',
  325. type: 'warning'
  326. })
  327. }
  328. },
  329. // tab切换
  330. handleClick (tab, event) {
  331. if (tab.name === 'first') {
  332. // this.getTelHisList()
  333. } else if (tab.name === 'second') {
  334. this.getMailList()
  335. }
  336. },
  337. // 点击历史记录通讯录中的号码 外呼
  338. recentCallOut (tel) {
  339. if (tel.length === 12) {
  340. tel = tel.substring(1)
  341. }
  342. this.telNumber = tel
  343. this.callOut()
  344. },
  345. // 展示隐藏工单图标
  346. showOrderIcon () {
  347. this.isShowOrderIcon = !this.isShowOrderIcon
  348. },
  349. // 点击工单图标去 该工单详情页面
  350. goOrderList (tel) {
  351. store.dispatch('UpdateCalloutScreen', !this.telIsVisCallout)// 关闭外呼面板
  352. // 带查询参数,变成 /order/orderSearchHY?tel=xxx
  353. router.push({ path: '/order/orderSearchHY', query: { tel } })// 工单列表
  354. }
  355. }
  356. }
  357. </script>
  358. <style rel="stylesheet/scss" lang="scss">
  359. .plate {
  360. div.tel_input {
  361. font-size: 26px;
  362. margin-bottom: 22px;
  363. width: 186px;
  364. .el-input__inner {
  365. background-color: #42484d;
  366. color: #ffffff;
  367. font-size: 26px;
  368. border-color: transparent;
  369. width: 100%;
  370. }
  371. }
  372. .btn_nums {
  373. background-color: #1f2129;
  374. width: 63px;
  375. height: 63px;
  376. font-size: 28px;
  377. border-color: transparent;
  378. margin-bottom: 8px;
  379. }
  380. .btn_nums:hover {
  381. box-shadow: 0px 0px 20px #7e7e7e;
  382. }
  383. .btn_nums:active {
  384. background-color: #409eff;
  385. }
  386. .btn_yonghu {
  387. position: absolute;
  388. right: 12px;
  389. bottom: 12px;
  390. color: #ffffff;
  391. cursor: pointer;
  392. }
  393. }
  394. .phone_lists {
  395. background-color: #5b6369;
  396. padding: 0;
  397. top: 50px !important;
  398. z-index: 2001 !important;
  399. box-shadow: none !important;
  400. border-bottom-right-radius: 10px;
  401. border-bottom-left-radius: 0;
  402. border-top-left-radius: 0;
  403. border-top-right-radius: 0;
  404. border-color: #5b6369;
  405. color: #ffffff;
  406. }
  407. .phnoe_tabs {
  408. width: 100%;
  409. height: 454px;
  410. border-bottom-right-radius: 10px;
  411. background-color: #5b6369;
  412. padding: 15px;
  413. color: #fff;
  414. .el-tabs__header {
  415. .el-tabs__active-bar {
  416. background-color: #ffffff;
  417. }
  418. .el-tabs__nav-wrap::after {
  419. background-color: #5b6369;
  420. }
  421. .el-tabs__item,
  422. .el-tabs__item.is-active {
  423. color: #ffffff;
  424. }
  425. }
  426. .el-tabs__content {
  427. .el-input {
  428. margin-top: 0px;
  429. margin-bottom: 20px;
  430. }
  431. .el-input__inner {
  432. border-radius: 14px;
  433. }
  434. }
  435. .el-scrollbar__wrap {
  436. overflow-x: hidden;
  437. }
  438. }
  439. </style>
  440. <style rel="stylesheet/scss" lang="scss" scoped>
  441. .dialplate {
  442. .plate {
  443. width: 100%;
  444. height: 454px;
  445. position: relative;
  446. background-color: #42484d;
  447. border-bottom-left-radius: 10px;
  448. padding: 24px 30px;
  449. text-align: center;
  450. .del_num {
  451. position: absolute;
  452. right: 12px;
  453. top: 32px;
  454. width: 31px;
  455. height: 16px;
  456. display: inline-block;
  457. cursor: pointer;
  458. background: url(../../assets/imgs/del_num.png) left center no-repeat;
  459. }
  460. .btn_call {
  461. margin-top: 22px;
  462. width: 142px;
  463. height: 46px;
  464. background-color: #1bce7d;
  465. border-radius: 23px;
  466. }
  467. .btn_call:hover {
  468. background-color: #4be59f;
  469. border-color: #4be59f;
  470. }
  471. }
  472. }
  473. .phnoe_tabs {
  474. .h_list_title {
  475. position: relative;
  476. font-size: 14px;
  477. padding-bottom: 10px;
  478. width: 100%;
  479. border-bottom: 1px solid #4b5155;
  480. .svg-icon {
  481. position: absolute;
  482. vertical-align: middle;
  483. cursor: pointer;
  484. font-size: 18px;
  485. right: 7px;
  486. top: 5px;
  487. }
  488. }
  489. .recent_calls_lists {
  490. width: 100%;
  491. padding-left: 30px;
  492. .recent_calls_item {
  493. list-style: none;
  494. border-bottom: 1px solid #4b5155;
  495. height: 56px;
  496. line-height: 56px;
  497. .recent_calls_item_left {
  498. position: relative;
  499. float: left;
  500. font-size: 14px;
  501. cursor: pointer;
  502. .svg-icon {
  503. position: absolute;
  504. left: -24px;
  505. top: 19px;
  506. font-size: 18px;
  507. }
  508. .recent_calls_item_name {
  509. line-height: 18px;
  510. margin: 6px 0 0 0;
  511. }
  512. .recent_calls_item_tel {
  513. line-height: 18px;
  514. margin: 4px 0 0 0;
  515. }
  516. }
  517. .recent_calls_item_right {
  518. float: right;
  519. position: relative;
  520. .recent_calls_item_time {
  521. color: #999999;
  522. padding-right: 42px;
  523. }
  524. .svg-icon {
  525. position: absolute;
  526. right: 7px;
  527. top: 17px;
  528. cursor: pointer;
  529. font-size: 20px;
  530. }
  531. }
  532. .name_state {
  533. color: #fa7171;
  534. }
  535. }
  536. }
  537. }
  538. </style>