足力健前端,vue版本

index.vue 16KB

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