123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545 |
- <!--
- * @Author: zc
- * @Description: 电话控件
- * @version:
- * @Date: 2022-11-08 14:16:48
- * @LastEditors: Please set LastEditors
- * @LastEditTime: 2022-11-18 16:04:53
- -->
- <template>
- <div class="phoneControls">
- <div class="infos">
- <div><span>分机号:</span>{{ telStatus.telNo }}</div>
- <div class="bottom_line"><span>状态:</span><b class="qianru_status">{{ telStatus.isOnDuty ? '签入' : '签出' }}</b>
- </div>
- </div>
- <div class="btns">
- <!-- 签入签出 -->
- <div class="item" :class="active.includes('qianchu') ? 'active' : ''" @click="onControlClick('qianchu')" v-if="telStatus.isOnDuty">
- <img :src="getImageUrl('phoneControls/qianchu_blue.png')" alt="">
- <span>签出</span>
- </div>
- <div class="item" @click="onControlClick('qianru')" v-else>
- <img :src="getImageUrl('phoneControls/qinaru_grey.png')" alt="">
- <!-- <img:src="getImageUrl('phoneControls/qianru_grey.png')" alt=""/> -->
- <span>签入</span>
- </div>
- <!-- 挂断 -->
- <el-popover :width="130*hangupList.length" v-model:visible="showHangupList" :show-arrow="false" trigger="hover" popper-class="hangup-popover" v-if="hangupList.length > 1">
- <template #reference>
- <div class="item" :class="active.includes('guaduan') ? 'active' : ''"
- @click="onControlClick('guaduan')">
- <img v-if="active.includes('guaduan')" :src="getImageUrl('phoneControls/guaduan_white.png')"
- alt="">
- <img v-else
- :src="telStatus.isOnDuty ? getImageUrl('phoneControls/guaduan_blue.png') : getImageUrl('phoneControls/guaduan_grey.png')"
- alt="">
- <span>挂断({{ hangupList.length }})</span>
- </div>
- </template>
- <div class="hangup-container">
- <div class="hangup-item" v-for="(item, index) in hangupList" :key="index">
- <p class="hangup-item-name">{{ item.name }}</p>
- <p class="hangup-item-phoneNumber">{{ item.tel }}</p>
- <button class="hangup-item-button" @click="hanup(item.tel)">挂断</button>
- </div>
- </div>
- </el-popover>
- <div class="item" :class="active.includes('guaduan') ? 'active' : ''" @click="onControlClick('guaduan')"
- v-else>
- <img v-if="active.includes('guaduan')" :src="getImageUrl('phoneControls/guaduan_white.png')" alt="">
- <img v-else
- :src="telStatus.isOnDuty ? getImageUrl('phoneControls/guaduan_blue.png') : getImageUrl('phoneControls/guaduan_grey.png')"
- alt="">
- <span>挂断</span>
- </div>
- <!-- 小休和结束休息 -->
- <div class="item"
- :class="active.includes('xiaoxiu') ? 'active' : '', userInfos.authBtnList.includes('999104') ? '' : 'disabled'"
- @click="onControlClick('xiaoxiuEnd')" v-if="telStatus.isResting">
- <img v-if="active.includes('xiaoxiu')" :src="getImageUrl('phoneControls/xiaoxiu_white.png')" alt="">
- <img v-else
- :src="telStatus.isOnDuty ? getImageUrl('phoneControls/xiaoxiu_blue.png') : getImageUrl('phoneControls/xiaoxiu_grey.png')"
- alt="">
- <span>结束小休</span>
- </div>
- <div class="item"
- :class="active.includes('xiaoxiu') ? 'active' : '', userInfos.authBtnList.includes('999103') ? '' : 'disabled'"
- @click="telStatus.isOnDuty ? onControlClick('xiaoxiu') : ''" v-else>
- <img v-if="active.includes('xiaoxiu')" :src="getImageUrl('phoneControls/xiaoxiu_white.png')" alt="">
- <img v-else
- :src="telStatus.isOnDuty ? getImageUrl('phoneControls/xiaoxiu_blue.png') : getImageUrl('phoneControls/xiaoxiu_grey.png')"
- alt="">
- <span>小休</span>
- </div>
- <!-- 保持和取消保持 -->
- <el-popover :width="130*holdList.length" v-model:visible="showHoldList" :show-arrow="false" trigger="hover" popper-class="hangup-popover" v-if="hangupList.length > 1">
- <template #reference>
- <div class="item" :class="active.includes('baochi') ? 'active' : ''"
- @click="onControlClick('baochi')">
- <img v-if="active.includes('baochi')" :src="getImageUrl('phoneControls/baochi_white.png')"
- alt="">
- <img v-else
- :src="telStatus.isOnDuty ? getImageUrl('phoneControls/baochi_blue.png') : getImageUrl('phoneControls/baochi_grey.png')"
- alt="">
- <span>保持({{ holdList.length }})</span>
- </div>
- </template>
- <div class="hangup-container">
- <div class="hangup-item" v-for="(item, index) in holdList" :key="index">
- <p class="hangup-item-name">{{ item.name }}</p>
- <p class="hangup-item-phoneNumber">{{ item.tel }}</p>
- <button class="hangup-item-button" @click="hold(item.hold)">{{item.hold?'保持':'取消保持'}}</button>
- </div>
- </div>
- </el-popover>
- <div class="item" :class="active.includes('baochi') ? 'active' : ''" @click="onControlClick('baochi')" v-else>
- <img v-if="active.includes('baochi')" :src="getImageUrl('phoneControls/baochi_white.png')" alt="">
- <img v-else
- :src="telStatus.isOnDuty ? getImageUrl('phoneControls/baochi_blue.png') : getImageUrl('phoneControls/baochi_grey.png')"
- alt="">
- <span>保持</span>
- </div>
- <div class="item" :class="active.includes('jingyin') ? 'active' : ''" @click="onControlClick('jingyin')">
- <img v-if="active.includes('jingyin')" :src="getImageUrl('phoneControls/jingyin_white.png')" alt="">
- <img v-else
- :src="telStatus.isOnDuty ? getImageUrl('phoneControls/jingyin_blue.png') : getImageUrl('phoneControls/jingyin_grey.png')"
- alt="">
- <span>静音</span>
- </div>
- <div class="item" :class="active.includes('zhuanjie') ? 'active' : ''" @click="onControlClick('zhuanjie')">
- <img v-if="active.includes('zhuanjie')" :src="getImageUrl('phoneControls/zhuanjie_white.png')" alt="">
- <img v-else
- :src="telStatus.isOnDuty ? getImageUrl('phoneControls/zhuanjie_blue.png') : getImageUrl('phoneControls/zhuanjie_grey.png')"
- alt="">
- <span>转接</span>
- </div>
- <div class="item" :class="active.includes('sanfang') ? 'active' : ''" @click="onControlClick('sanfang')">
- <img v-if="active.includes('sanfang')" :src="getImageUrl('phoneControls/sanfang_white.png')" alt="">
- <img v-else
- :src="telStatus.isOnDuty ? getImageUrl('phoneControls/sanfang_blue.png') : getImageUrl('phoneControls/sanfang_grey.png')"
- alt="">
- <span>三方会议</span>
- </div>
- <div class="item" :class="active.includes('waihu') ? 'active' : ''" @click="onControlClick('waihu')">
- <img v-if="active.includes('waihu')" :src="getImageUrl('phoneControls/waihu_white.png')" alt="">
- <img v-else
- :src="telStatus.isOnDuty ? getImageUrl('phoneControls/waihu_blue.png') : getImageUrl('phoneControls/waihu_grey.png')"
- alt="">
- <span>外呼</span>
- </div>
- <div class="item" :class="active.includes('hujiaozhuanyi') ? 'active' : ''"
- @click="onControlClick('zhuanyi')">
- <img v-if="active.includes('hujiaozhuanyi')" :src="getImageUrl('phoneControls/hujiaozhuanyi_white.png')"
- alt="">
- <img v-else
- :src="telStatus.isOnDuty ? getImageUrl('phoneControls/hujiaozhuanyi_blue.png') : getImageUrl('phoneControls/hujiaozhuanyi_grey.png')"
- alt="">
- <span>呼叫转移</span>
- </div>
- <div class="item" :class="active.includes('pingjia') ? 'active' : ''" @click="onControlClick('pingjia')">
- <img v-if="active.includes('pingjia')" :src="getImageUrl('phoneControls/pingjia_white.png')" alt="">
- <img v-else
- :src="telStatus.isOnDuty ? getImageUrl('phoneControls/pingjia_blue.png') : getImageUrl('phoneControls/pingjia_grey.png')"
- alt="">
- <span>评价</span>
- </div>
- </div>
- </div>
- <!-- 占位标签 -->
- <div class="seizeSeat-box"></div>
- <!-- 功能 -->
- <!-- 签入 -->
- <el-dialog v-model="showDutyDialog" draggable title="签入" width="400px">
- <el-form :model="dutyForm" label-width="80px" ref="dutyFormRef">
- <el-form-item label="分机" prop="telNo"
- :rules="[{ required: true, message: '请选择需要签入的分机', trigger: 'change' }]">
- <el-select v-model="dutyForm.telNo" placeholder="请选择需要签入的分机" class="w100">
- <el-option v-for="item in telsList" :key="item.id" :label="item.no" :value="item.no" />
- </el-select>
- </el-form-item>
- </el-form>
- <template #footer>
- <span class="dialog-footer">
- <el-button @click="showDutyDialog = false">取 消</el-button>
- <el-button type="primary" @click="clickOnDuty" :loading="loading">确 定</el-button>
- </span>
- </template>
- </el-dialog>
- </template>
- <script setup lang="ts" name="telControl">
- import { reactive, toRefs, ref, nextTick } from "vue";
- import { ElMessageBox, ElNotification } from 'element-plus';
- import { storeToRefs } from 'pinia';
- import { useUserInfo } from '/@/stores/userInfo';
- import { useTelStatus } from '/@/stores/telStatus';
- import { getImageUrl } from "/@/utils/tools";
- import { getTelsList } from '/@/api/login/user';
- import { onDuty, offDuty, telRest, telUnrest } from '/@/api/login/user';
- // import signalR from '/@/utils/signalR';
- const state = reactive({
- active: <any>[], // 当前选中
- showDutyDialog: false, //签入选分机弹窗
- dutyForm: {
- telNo: '' //分机号
- },
- telsList: <any>[],// 分机列表
- loading: false,
- showHangupList:false, //是否展示挂断列表
- hangupList: [
- {
- name: '市民',
- tel: 13412341234
- },
- {
- name: '坐席',
- tel: 123456
- },
- ], //挂断列表
- holdList: [
- {
- name: '市民',
- tel: 13412341234,
- hold:true
- },
- {
- name: '坐席',
- tel: 123456,
- hold:false
- },{
- name: '坐席',
- tel: 123456,
- hold:false
- },{
- name: '坐席',
- tel: 123456,
- hold:false
- },{
- name: '坐席',
- tel: 123456,
- hold:false
- },{
- name: '坐席',
- tel: 123456,
- hold:false
- },
- ], // 保持列表
- showHoldList:false, // 是否展示保持列表
- })
- const { active, showDutyDialog, dutyForm, loading, telsList,showHangupList, hangupList, holdList,showHoldList } = toRefs(state);
- const useTelStatusStore = useTelStatus();
- const { telStatus } = storeToRefs(useTelStatusStore);
- const storesUserInfo = useUserInfo();
- const { userInfos } = storeToRefs(storesUserInfo);
- nextTick(() => {
- useTelStatusStore.getTelStatusAction(); // 查询当前用户签入状态
- });
- const getTelsLists = () => {// 查询所有分机
- getTelsList().then((res: any) => {
- state.telsList = res?.result ?? [];
- })
- }
- // 点击事件
- const onControlClick = (val: string) => {
- switch (val) {
- case 'qianru': //签入
- if (userInfos.value.authBtnList.includes('999101')) { // 签入权限
- onDutyFn();
- } else {
- console.warn('您没有签入权限')
- }
- break;
- case 'qianchu': //签出
- if (userInfos.value.authBtnList.includes('999102')) { // 签出权限
- offDutyFn();
- } else {
- console.warn('您没有签出权限')
- }
- break;
- case 'guaduan': //挂断
- hangupFn();
- break;
- case 'xiaoxiu': //小休
- if (userInfos.value.authBtnList.includes('999103')) { // 小休权限
- xiaoxiuFn();
- } else {
- console.warn('您没有小休权限')
- }
- break;
- case 'xiaoxiuEnd': //结束小休
- if (userInfos.value.authBtnList.includes('999104')) { // 结束小休权限
- xiaoxiuEndFn();
- } else {
- console.warn('您没有结束小休权限')
- }
- break;
- default:
- break;
- }
- }
- const dutyFormRef = ref();
- const onDutyFn = () => { //签入
- getTelsLists();
- // 重置表单
- if (dutyFormRef.value) {
- dutyFormRef.value.resetFields();
- }
- state.showDutyDialog = true;
- }
- const clickOnDuty = () => {// 确认签入
- dutyFormRef.value.validate((valid: boolean) => {
- if (valid) {
- state.showDutyDialog = true;
- onDuty(state.dutyForm.telNo).then(() => {
- // 开启 signalr 链接
- // if (Session.get('token')) {
- // signalR.start();
- // signalR.SR.on("Ring", (data:any) =>{// 接收消息
- // console.log(data)
- // })
- // }
- ElNotification({
- title: '成功',
- message: '签入成功',
- type: 'success',
- })
- state.showDutyDialog = false;
- state.loading = false;
- useTelStatusStore.getTelStatusAction(); // 查询当前用户签入状态
- }).catch(() => {
- state.showDutyDialog = false;
- state.loading = false;
- })
- } else {
- return false;
- }
- });
- }
- // 签出
- const offDutyFn = () => {
- ElMessageBox.confirm(`确定要签出,是否继续?`, '提示', {
- confirmButtonText: '确认',
- cancelButtonText: '取消',
- type: 'warning',
- }).then(() => {
- offDuty().then(() => {
- ElNotification({
- title: '成功',
- message: '签出成功',
- type: 'success',
- })
- useTelStatusStore.getTelStatusAction(); // 查询当前用户签入状态
- })
- }).catch(() => { });
- }
- // 挂断
- const hangupFn = () => {
- }
- // 挂断其中一个
- const hanup = (tel: any) => {
- state.showHangupList = false;
- }
- // 小休
- const xiaoxiuFn = () => {
- ElMessageBox.confirm(`确定要开始小休,是否继续?`, '提示', {
- confirmButtonText: '确认',
- cancelButtonText: '取消',
- type: 'warning',
- }).then(() => {
- telRest().then(() => {
- ElNotification({
- title: '成功',
- message: '小休开始',
- type: 'success',
- })
- useTelStatusStore.getTelStatusAction(); // 查询当前用户签入状态
- })
- }).catch(() => { });
- }
- const holdFn = ()=>{ // 单个保持
- }
- const hold = ()=>{ //保持一个
- state.showHoldList = false;
- }
- // 小休结束
- const xiaoxiuEndFn = () => {
- ElMessageBox.confirm(`确定要结束小休,是否继续?`, '提示', {
- confirmButtonText: '确认',
- cancelButtonText: '取消',
- type: 'warning',
- }).then(() => {
- telUnrest().then(() => {
- ElNotification({
- title: '成功',
- message: '小休结束',
- type: 'success',
- })
- useTelStatusStore.getTelStatusAction(); // 查询当前用户签入状态
- })
- }).catch(() => { });
- }
- </script>
- <style scoped lang="scss">
- .seizeSeat-box {
- display: none;
- }
- .phoneControls {
- display: flex;
- flex: 1;
- background: #FFFFFF;
- box-shadow: 0px 1px 8px 0px rgba(0, 15, 49, 0.1);
- border-bottom-left-radius: 90px;
- border-bottom-right-radius: 90px;
- padding: 0 52px;
- color: #333;
- height: 100%;
- .infos {
- margin: 20px 0;
- text-align: left;
- width: 120px;
- .bottom_line {
- padding-top: 5px;
- }
- .qianru_status {
- color: var(--el-color-primary);
- font-weight: normal;
- }
- span {
- display: inline-block;
- width: 60px;
- text-align: right;
- }
- }
- // 按钮列表
- .btns {
- display: flex;
- width: calc(100% - 120px);
- justify-content: space-between;
- .item {
- text-align: center;
- cursor: pointer;
- width: 100%;
- height: 100%;
- &:hover {
- color: #fff;
- background-image: url('../../../assets/images/phoneControls/active.png');
- background-repeat: no-repeat;
- background-size: 100% 100%;
- // height: calc(100% + 20px);
- }
- img {
- display: block;
- margin: 0 auto;
- padding-top: 15px;
- }
- span {
- margin-top: 5px;
- display: inline-block;
- }
- &.disabled {
- cursor: not-allowed;
- }
- }
- .active {
- color: #fff;
- background-image: url('../../../assets/images/phoneControls/active.png');
- background-repeat: no-repeat;
- background-size: 100% 100%;
- height: calc(100% + 20px);
- background-color: var(--hotline-bg-main-color);
- img {
- display: block;
- margin: 0 auto;
- padding-top: 30px;
- }
- span {
- margin-top: 5px;
- display: inline-block;
- }
- &:hover {
- transition: inherit;
- color: var(--hotline-color-white) !important;
- background-color: var(--hotline-bg-main-color) !important;
- }
- }
- }
- }
- </style>
- <style lang="scss">
- .el-popover.hangup-popover {
- background: var(--el-color-primary);
- border-radius:16px;
- opacity: .9;
- box-shadow: 0px 1px 8px 0px rgba(0,15,49,0.1);
- border: 1px solid #667AED;
- padding:15px;
- .hangup-container{
- display: flex;
- flex-wrap: nowrap;
- color: #fff;
- font-size: var(--el-font-size-small);
- .hangup-item {
- text-align: center;
- width: 130px;
- border-right: 1px solid #aaa;
- &:last-child {
- border-right: 0;
- }
- // &-name {
- // // padding-top: 10px;
- // }
- &-phoneNumber {
- padding-top: 4px;
- }
- &-button {
- background: linear-gradient(0deg, #E3E3E3, #FFFFFF);
- border-radius: 8px;
- color:var(--el-color-primary);
- outline: none;
- padding:5px 15px;
- border: none;
- margin-top: 6px;
- font-weight: bold;
- cursor: pointer;
- }
- }
- }
- }
- </style>
|