1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230 |
- <template>
- <div class="phoneControls">
- <el-popover :width="240" trigger="hover" v-model:visible="showPop">
- <template #reference>
- <div class="mr20 status-box">
- <span class="color-primary">{{ currentStatusText }}</span>
- <el-text tag="b" v-if="['301', '303'].includes(m_strTelState)" type="danger">{{ formatDuration(talkTime) }}</el-text>
- <el-text tag="b" v-else-if="m_strTelState === '200'">{{ formatDuration(idleTime) }}</el-text>
- <el-text tag="b" v-else-if="m_strTelState === '201'">{{ formatDuration(busyTime) }}</el-text>
- <el-text tag="b" v-else-if="m_strTelState === '320'">{{ formatDuration(conferenceTime) }}</el-text>
- <el-text tag="b" v-else-if="m_strTelState === '900'">{{ formatDuration(arrangeTime) }}</el-text>
- <SvgIcon name="ele-CaretBottom" class="arrow" :class="showPop ? 'is-reverse' : ''" />
- </div>
- </template>
- <template #default>
- <template v-if="m_bLogin">
- <div class="flex-center-between" v-if="m_strUserNo">
- <span class="ml10">分机号</span>
- <el-text tag="b" type="danger">{{ m_strUserNo }}</el-text>
- </div>
- <div class="flex-center-between mt10" v-if="signTime">
- <span class="ml10">签入时长</span>
- <el-text tag="b" type="primary">{{ formatDuration(signTime) }}</el-text>
- </div>
- <div class="flex-center-between mt10" v-if="talkTime && ['301', '303', '310'].includes(m_strTelState)">
- <span class="ml10">通话时长</span>
- <el-text tag="b" type="danger">{{ formatDuration(talkTime) }}</el-text>
- </div>
- <div class="flex-center-between mt10" v-if="idleTime && ['0'].includes(m_strTelState)">
- <span class="ml10">空闲时长</span>
- <el-text tag="b">{{ formatDuration(idleTime) }}</el-text>
- </div>
- <div class="flex-center-between mt10" v-if="busyTime && ['201'].includes(m_strTelState)">
- <span class="ml10">示忙时长</span>
- <el-text tag="b">{{ formatDuration(busyTime) }}</el-text>
- </div>
- </template>
- <template v-else> <span class="color-info flex flex-center-center">请签入</span> </template>
- </template>
- </el-popover>
- <div class="btn-container">
- <!-- 签入 -->
- <template v-if="m_bLogin">
- <!-- 签出可用 -->
- <div class="item active" @click="onEvent('signOut')" v-if="activeArr.includes('dutyOff')" title="签出">
- <SvgIcon name="iconfont icon-dutyOff" class="icon mr3" size="18px" />签出
- </div>
- <!-- 签出不可用 -->
- <div class="item disabled" v-else title="签出"><SvgIcon name="iconfont icon-dutyOff" class="icon mr3" size="18px" />签出</div>
- </template>
- <!-- 灰色签入不可用 -->
- <template v-else>
- <div class="item active" @click="onEvent('signIn')" title="签入">
- <SvgIcon name="iconfont icon-dutyOn" class="icon mr3" size="18px" />签入
- </div>
- </template>
- <!-- 呼叫 可用-->
- <template v-if="m_bLogin && activeArr.includes('outbound')">
- <div class="item active" title="呼叫" @click="onEvent('callOut')">
- <SvgIcon name="iconfont icon-outbound" class="icon mr3" size="18px" />
- <span>呼叫</span>
- </div>
- </template>
- <!-- 呼叫 不可用 -->
- <template v-else>
- <div class="item disabled" title="呼叫">
- <SvgIcon name="iconfont icon-outbound" class="icon mr3" size="18px" />
- <span>呼叫</span>
- </div>
- </template>
- <!-- 可用挂断 -->
- <template v-if="m_bLogin && activeArr.includes('hangup')">
- <div class="item active" @click="onEvent('hangup')" title="挂断">
- <SvgIcon name="iconfont icon-hangup" class="icon mr3" size="16px" />挂断
- </div>
- </template>
- <!-- 灰色挂断 不可用 -->
- <template v-else>
- <div class="item disabled" title="挂断"><SvgIcon name="iconfont icon-hangup" class="icon mr3" size="16px" />挂断</div>
- </template>
- <!-- 小休和结束休息 可用 -->
- <template v-if="m_bLogin && activeArr.includes('rest')">
- <div class="item active" :title="m_bTelBusy ? '示闲' : '示忙'" @click="onEvent(m_bTelBusy ? 'idle' : 'busy')">
- <SvgIcon name="iconfont icon-rest" class="icon mr3" size="16px" />
- {{ m_bTelBusy ? '示闲' : '示忙' }}
- </div>
- </template>
- <!-- 灰色小休不可用 -->
- <template v-else>
- <div class="item disabled" title="示忙"><SvgIcon name="iconfont icon-rest" class="icon mr3" size="18px" />示忙</div>
- </template>
- <!-- 保持和取消保持 可用 -->
- <template v-if="m_bLogin && activeArr.includes('hold')">
- <div class="item active" :title="m_IsHold ? '恢复' : '保持'" @click="onEvent(m_IsHold ? 'reHold' : 'hold')">
- <SvgIcon name="iconfont icon-hold" class="icon mr3" size="16px" />
- {{ m_IsHold ? '恢复' : '保持' }}
- </div>
- </template>
- <!-- 灰色保持不可用 -->
- <template v-else>
- <div class="item disabled" title="保持"><SvgIcon name="iconfont icon-hold" class="icon mr3" size="16px" />保持</div>
- </template>
- <!-- 咨询 可用 -->
- <template v-if="m_bLogin && activeArr.includes('consult')">
- <div class="item active" title="咨询" @click="onEvent('consult')">
- <SvgIcon name="iconfont icon-transfer" class="icon mr3" size="16px" />
- 咨询
- </div>
- </template>
- <!-- 灰色咨询不可用 -->
- <template v-else>
- <div class="item disabled" title="咨询"><SvgIcon name="iconfont icon-transfer" class="icon mr3" size="16px" />咨询</div>
- </template>
- <!-- 盲转可用 -->
- <template v-if="m_bLogin && activeArr.includes('transferMz')">
- <div class="item active" title="盲转" @click="onEvent('transferMz')">
- <SvgIcon name="iconfont icon-transfer" class="icon mr3" size="16px" />
- 盲转
- </div>
- </template>
- <!-- 灰色盲转不可用 -->
- <template v-else>
- <div class="item disabled" title="盲转"><SvgIcon name="iconfont icon-transfer" class="icon mr3" size="16px" />盲转</div>
- </template>
- <!-- 转接可用 -->
- <template v-if="m_bLogin && activeArr.includes('transfer')">
- <div class="item active" title="转接" @click="onEvent('transfer')">
- <SvgIcon name="iconfont icon-transfer" class="icon mr3" size="16px" />
- 转接
- </div>
- </template>
- <!-- 灰色转接不可用 -->
- <template v-else>
- <div class="item disabled" title="转接"><SvgIcon name="iconfont icon-transfer" class="icon mr3" size="16px" />转接</div>
- </template>
- <!-- 三方会议可用 -->
- <template v-if="m_bLogin && activeArr.includes('conference')">
- <div class="item active" title="三方会议" @click="onEvent('conference')">
- <SvgIcon name="iconfont icon-conference" class="icon mr3" size="16px" />
- 三方会议
- </div>
- </template>
- <!-- 三方会议不可用 -->
- <template v-else>
- <div class="item disabled" title="三方会议"><SvgIcon name="iconfont icon-conference" class="icon mr3" size="16px" />三方会议</div>
- </template>
- <!-- 整理和取消整理 可用 -->
- <!-- <template v-if="m_bLogin && activeArr.includes('talkingDeal')">
- <div class="item active" :title="m_IsTalkingDeal ? '取消整理' : '话后整理'" @click="onEvent(m_IsTalkingDeal ? 'idle' : '')">
- <SvgIcon name="iconfont icon-talkingDeal" class="icon mr3" size="16px" />
- {{ m_IsTalkingDeal ? '取消整理' : '话后整理' }}
- </div>
- </template>
- <!– 灰色整理不可用 –>
- <template v-else>
- <div class="item disabled" title="话后整理"><SvgIcon name="iconfont icon-talkingDeal" class="icon mr3" size="16px" />话后整理</div>
- </template>-->
- <!-- 评价可用 登录并且是呼入 -->
- <template v-if="m_bLogin && m_IsCallIn && activeArr.includes('evaluate')">
- <div class="item active" title="评价" @click="onEvent('evaluate')">
- <SvgIcon name="ele-Flag" class="icon mr3" size="16px" />
- 评价
- </div>
- </template>
- <!-- 评价不可用 -->
- <template v-else>
- <div class="item disabled" title="评价"><SvgIcon name="ele-Flag" class="icon mr3" size="16px" />评价</div>
- </template>
- </div>
- </div>
- <!-- 签入弹窗 -->
- <el-dialog v-model="state.dutyDialogVisible" draggable title="签入" width="500px" :show-close="false">
- <el-form :model="state.dutyForm" label-width="80px" ref="dutyFormRef" @submit.native.prevent>
- <el-form-item label="分机号" prop="telNo" :rules="[{ required: true, message: '请选择分机号', trigger: 'change' }]">
- <!-- <el-select-v2
- v-model="state.dutyForm.telNo"
- :options="telsList"
- placeholder="请选择分机号"
- filterable
- class="w100"
- :props="{
- label: 'no',
- value: 'no',
- }"
- clearable
- />-->
- <el-input v-model="state.dutyForm.telNo"></el-input>
- </el-form-item>
- <el-form-item label="技能组" prop="skillId" :rules="[{ required: true, message: '请选择技能组', trigger: 'change' }]">
- <!-- <el-select-v2
- v-model="state.dutyForm.skillId"
- :options="telsListGroup"
- placeholder="请选择技能组"
- filterable
- class="w100"
- :props="{
- label: 'no',
- value: 'no',
- }"
- clearable
- >
- </el-select-v2>-->
- <el-input v-model="state.dutyForm.skillId"></el-input>
- </el-form-item>
- </el-form>
- <template #footer>
- <span class="dialog-footer">
- <el-button @click="state.dutyDialogVisible = false" class="default-button" :loading="state.loading">取 消</el-button>
- <el-button type="primary" @click="clickOnDuty(dutyFormRef)" :loading="state.loading">确 定</el-button>
- </span>
- </template>
- </el-dialog>
- <!-- 呼出弹窗 -->
- <el-dialog v-model="state.outboundDialogVisible" draggable title="呼出" width="450px">
- <el-form :model="state.outboundForm" label-width="80px" ref="outboundFormRef" @submit.native.prevent>
- <el-form-item label="呼出号码" prop="telNo" :rules="[{ required: true, message: '请填写呼出号码', trigger: 'blur' }]">
- <el-input v-model="state.outboundForm.telNo" placeholder="呼出号码" @keyup.enter="clickOnOutbound(outboundFormRef)" clearable />
- </el-form-item>
- </el-form>
- <template #footer>
- <span class="dialog-footer">
- <el-button @click="state.outboundDialogVisible = false" class="default-button" :loading="state.loading">取 消</el-button>
- <el-button type="primary" @click="clickOnOutbound(outboundFormRef)" :loading="state.loading">确 定</el-button>
- </span>
- </template>
- </el-dialog>
- <!-- 咨询弹窗 -->
- <el-dialog v-model="state.consultDialogVisible" draggable title="咨询" width="450px">
- <el-form :model="state.consultForm" label-width="80px" ref="consultFormRef" @submit.native.prevent>
- <el-form-item label="咨询类型" prop="strType" :rules="[{ required: false, message: '请选择咨询类型', trigger: 'blur' }]">
- <el-radio-group v-model="state.consultForm.strType">
- <el-radio value="0">内线</el-radio>
- <el-radio value="1">外线</el-radio>
- <el-radio value="2">群组</el-radio>
- </el-radio-group>
- </el-form-item>
- <el-form-item label="咨询" prop="telNo" :rules="[{ required: true, message: '请填写咨询号码', trigger: 'blur' }]">
- <el-input v-model="state.consultForm.telNo" placeholder="咨询号码" @keyup.enter="clickOnConsult(consultFormRef)" clearable />
- </el-form-item>
- </el-form>
- <template #footer>
- <span class="dialog-footer">
- <el-button @click="state.consultDialogVisible = false" class="default-button" :loading="state.loading">取 消</el-button>
- <el-button type="primary" @click="clickOnConsult(consultFormRef)" :loading="state.loading">确 定</el-button>
- </span>
- </template>
- </el-dialog>
- <!-- 盲转 -->
- <el-dialog v-model="state.blindDialogVisible" draggable title="盲转" width="450px">
- <el-form :model="state.blindForm" label-width="80px" ref="blindFormRef" @submit.native.prevent>
- <el-form-item label="盲转" prop="telNo" :rules="[{ required: true, message: '请填写盲转号码', trigger: 'blur' }]">
- <el-input v-model="state.blindForm.telNo" placeholder="盲转号码" @keyup.enter="clickOnBlind(blindFormRef)" clearable />
- </el-form-item>
- </el-form>
- <template #footer>
- <span class="dialog-footer">
- <el-button @click="state.blindDialogVisible = false" class="default-button" :loading="state.loading">取 消</el-button>
- <el-button type="primary" @click="clickOnBlind(blindFormRef)" :loading="state.loading">确 定</el-button>
- </span>
- </template>
- </el-dialog>
- <!-- 占位标签 -->
- <div class="seizeSeat-box"></div>
- </template>
- <script setup lang="ts" name="zgTelControl">
- import { computed, onMounted, reactive, ref } from 'vue';
- import { getNowDateTime } from '@/utils/constants';
- import { ElMessage, ElMessageBox, FormInstance } from 'element-plus';
- import { useRouter } from 'vue-router';
- import { useWebSocket } from '@/hooks/useWebsocket';
- import { useIntervalFn } from '@vueuse/shared';
- import { formatDuration } from '@/utils/formatTime';
- import { Local } from '@/utils/storage';
- import { useAppConfig } from '@/stores/appConfig';
- import { storeToRefs } from 'pinia';
- import { useUserInfo } from '@/stores/userInfo';
- import { callCenterIsOnThePhone, callCenterIsSignIn, callCenterWs, currentTel } from '@/utils/callCenter';
- import mittBus from '@/utils/mitt';
- import { callCenterSignIn, callCenterSignOut, getCallCenterGroupList, getCallCenterList } from '@/api/callCenter';
- import { getCurrentCityConfig } from '@/utils/appConfig';
- import { useTimeoutFn } from '@vueuse/shared/index';
- const state = reactive({
- dutyDialogVisible: false,
- loading: false,
- dutyForm: {
- telNo: null,
- skillId: null,
- },
- outboundDialogVisible: false,
- outboundForm: {
- telNo: '',
- },
- consultDialogVisible: false,
- consultForm: {
- telNo: '',
- strType: '0',
- },
- blindDialogVisible: false,
- blindForm: {
- telNo: '',
- },
- });
- /*
- * @description: 置当前可用的按钮
- * 电话控件在头部展示时切换;
- * 状态改变
- * 0-未登录;100-登录成功;
- * 200-空闲;201-繁忙;
- * 300-呼入振铃;301-呼入通话;302-呼出振铃;303-呼出通话;310-保持通话;320-会议;330-咨询;333-转接接通
- * 510-监听;520-插话;
- */
- const activeArr = computed(() => {
- const switchCases: any = {
- '0': ['dutyOn'], // 签出状态
- '100': [], // 登录成功
- '200': ['dutyOff', 'rest', 'outbound'], // 空闲
- '201': ['rest'], // 示忙
- '300': ['hangup'], // 呼入振铃
- '301': ['hangup', 'hold', 'consult', 'transferMz', 'evaluate'], // 呼入通话
- '302': ['hangup'], // 呼出振铃
- '303': ['hangup', 'hold', 'consult', 'transferMz', 'evaluate'], // 呼出通话
- '310': ['hangup', 'hold'], // 通话保持
- '320': ['hangup', 'evaluate'], // 三方会议中
- '330': ['hangup', 'hold', 'transfer', 'conference', 'evaluate'], // 转接 咨询
- '331': ['hangup', 'hold', 'evaluate'], // 咨询 转接
- '900': ['dutyOff', 'talkingDeal'], // 整理
- };
- let arr = <EmptyArrayType>[];
- if (m_strTelState.value in switchCases) {
- arr = switchCases[m_strTelState.value];
- }
- return arr;
- });
- // 当前对应code展示的中文
- const currentStatusText = computed(() => {
- const statusMap: any = {
- '0': '签出',
- '100': '登录成功',
- '200': '空闲',
- '201': '示忙',
- '300': '呼入振铃',
- '301': '呼入通话',
- '302': '呼出振铃',
- '303': '呼出通话',
- '310': '通话保持',
- '320': '三方会议',
- '330': '转接',
- '331': '转接',
- '900': '整理',
- };
- return statusMap[m_strTelState.value] || '';
- });
- // ws实例对象
- const wsRef = ref();
- const { callCenterSocketUrl } = getCurrentCityConfig();
- const initWs = () => {
- wsRef.value = useWebSocket(callCenterSocketUrl, {
- /* heartbeat: {
- message: 'ping',
- interval: 5000,
- pongTimeout: 5000,
- },*/
- autoReconnect: true, // 自动重连
- immediate: false, // 是否立即链接
- onMessage: e_TelMsgReceive, // 消息接收
- onError: e_websocketError, // 错误
- onDisconnected: e_websocketClose, // 断开
- onConnected: e_websocketOpen, // 链接成功
- });
- };
- // 发送消息
- const e_TelSendMsg = (strObj: Object) => {
- // 客户端当前时间
- const strMsg = JSON.stringify(strObj);
- console.log(`${getNowDateTime()} 发送消息:`, strMsg, wsRef.value.status);
- if (wsRef.value.ws?.readyState === 1) {
- // 已经链接并且可以通讯,则发放文本消息
- wsRef.value.send(strMsg);
- } else {
- ElMessage.error('请先签入');
- state.loading = false;
- }
- };
- const m_strUserNo = ref(''); // 分机号码
- const m_strJobNum = ref(''); // 坐席工号
- const m_strSkillId = ref(''); // 技能组
- const m_strLevel = ref('1'); // 优先级别
- const m_strGroup = ref('1'); // 分组ID
- const m_strCompanyId = ref(''); // 企业编码
- const m_bLogin = ref(false); // 登录状态
- const m_bTelBusy = ref(false); // 是否示忙中
- const m_strIsMonitor = ref('0'); // 是否监控分机 1-是监控分机
- const callId = ref(''); // 通话ID
- const m_IsCallOut = ref(false); // 是否呼出
- const m_IsCallIn = ref(false); // 是否是呼入
- const m_strOpenFlag = ref('2'); // 来电弹屏方式 1-接通弹屏;2-振铃弹屏
- const m_CallOutOpen = ref(false); // 呼出是否弹屏(用于未接统计“回拨”业务处理)
- const m_bIsOpen = ref(false); // 是否已经弹屏
- const m_bCallConnect = ref(false); // 是否在通话状态
- const m_IsConsult = ref(false); // 是否咨询
- const m_strConsultType = ref('-1'); // 咨询类型
- const m_IsHangup = ref(false); // 是否挂机
- const m_IsHold = ref(false); // 是否保持
- const m_IsTalkingDeal = ref(false); // 是否通话整理
- const m_IsMonListen = ref('0'); // 监控状态 0-未监听;1-监控成功;2-监控失败;
- const m_strTelState = ref('0'); // 当前状态
- const showPop = ref(false);
- // 点击事件
- const onEvent = (event: string) => {
- switch (event) {
- case 'signIn': // 签入
- onSignIn();
- break;
- case 'signOut': // 签出
- onSignOut();
- break;
- case 'busy': // 示忙
- onBusy();
- break;
- case 'idle': // 示闲
- onIdle();
- break;
- case 'answer': // 应答
- break;
- case 'hangup': // 挂机
- onHangup();
- break;
- case 'callOut': // 外呼
- onCallOut();
- break;
- case 'hold': // 保持
- onHold();
- break;
- case 'reHold': // 恢复
- onReHold();
- break;
- // 咨询
- case 'consult':
- e_TopStateChange('331');
- onConsultOpen();
- break;
- // 转接
- case 'transfer':
- onTransfer();
- break;
- // 盲转
- case 'transferMz':
- onTransferMzOpen();
- break;
- case 'conference': // 三方会议
- onConference();
- break;
- case 'DTMF': // 拨号盘
- break;
- // 评价
- case 'evaluate':
- i_evaluate();
- break;
- }
- };
- /*
- * 事件响应状态
- */
- const arrangeTime = ref(0);
- const arrangeTimer = useIntervalFn(
- () => {
- arrangeTime.value += 1;
- },
- 1000,
- { immediate: false }
- );
- // 整理时长开始
- const startArrangeTime = () => {
- arrangeTimer.resume();
- };
- // 整理时长开始结束
- const stopArrangeTime = () => {
- arrangeTime.value = 0;
- arrangeTimer.pause();
- };
- const evtSeatState = (data: any) => {
- if (m_strIsMonitor.value == '1') {
- // 推送分机信息
- const pushExt = data.Param.Extension || '';
- if (pushExt !== m_strUserNo.value) {
- // 如果分机实时推送的分机信息和当前登录分机不一致,则表明当前登录分机为监控分机,开启了状态监控功能
- // 1.不属于当前分机的状态,则不改变当前分机电话条状态
- // 2.调整其他分机大屏监控状态
- const pushState = GetTelState(data.Param.State);
- if (pushState) {
- // 修改后台数据
- console.log(pushExt, pushState);
- // SetMonitorState(pushExt, pushState);
- }
- return;
- }
- }
- if (m_IsHold.value) {
- // 正在保持通话状态下
- return;
- }
- // 状态 0:闲 1:忙 2:会议 3:登出 4:呼入 5:呼出 6:咨询 7:其他 8:通话
- const strState = data.Param.State;
- switch (strState) {
- // 空闲
- case '0':
- m_bIsOpen.value = false;
- m_IsHangup.value = false;
- m_strTelState.value = '200';
- m_bTelBusy.value = false;
- e_TopStateChange(m_strTelState.value);
- startIdleTime(); // 空闲计时器开始
- stopTalkTimer(); // 停止通话时长
- stopConferenceTime(); // 三方会议时长结束
- // m_IsTalkingDeal.value = false;
- break;
- // 示忙
- case '1':
- m_strTelState.value = '201';
- m_bTelBusy.value = true;
- e_TopStateChange(m_strTelState.value);
- startBusyTime(); // 示忙计时器开始
- stopIdleTime(); // 停止空闲时长
- break;
- case '2':
- stopIdleTime();
- break;
- // 登出
- case '3':
- // 附加签出方法(用户分机分离调用业务系统签出)
- m_strTelState.value = '0';
- e_TopStateChange(m_strTelState.value);
- break;
- // 通话振铃
- case '4':
- if (false === m_IsHangup.value) {
- if (m_IsCallOut.value == true) {
- // 呼出振铃
- m_strTelState.value = '302';
- } else {
- // 呼入振铃
- m_strTelState.value = '300';
- }
- e_TopStateChange(m_strTelState.value);
- }
- stopIdleTime();
- break;
- // 通话振铃
- case '5':
- if (!m_IsHangup.value) {
- m_strTelState.value = '302';
- e_TopStateChange(m_strTelState.value);
- }
- stopIdleTime();
- break;
- // 咨询
- case '6':
- break;
- // 其他
- case '7':
- break;
- // 接通
- case '8':
- if (!m_IsHangup.value) {
- if (m_IsCallOut.value) {
- // 呼出接通
- m_strTelState.value = '303';
- } else {
- // 呼入接通
- m_strTelState.value = '301';
- // 是否是保持通话
- }
- e_TopStateChange(m_strTelState.value);
- }
- stopIdleTime();
- break;
- case '9': // 工单整理
- m_strTelState.value = '900';
- startArrangeTime(); // 开始整理时长
- e_TopStateChange(m_strTelState.value);
- // m_IsTalkingDeal.value = true;
- break;
- }
- };
- // 获取分机状态
- const GetTelState = (strState: any) => {
- let strResult = '';
- switch (strState) {
- // 空闲
- case '0':
- strResult = '200';
- break;
- // 示忙
- case '1':
- strResult = '201';
- break;
- case '2':
- break;
- // 登出
- case '3':
- strResult = '0';
- break;
- // 通话振铃
- case '4':
- strResult = '302'; // 默认呼入振铃
- break;
- // 通话振铃
- case '5':
- strResult = '302'; // 默认呼出振铃
- break;
- // 咨询
- case '6':
- break;
- // 其他
- case '7':
- break;
- // 接通
- case '8':
- strResult = '301';
- break;
- case '9': // 工单整理
- strResult = '900';
- break;
- }
- return strResult;
- };
- /**
- * 状态初始化请求
- * */
- const ReqAgentMonitor = () => {
- // 开始坐席状态监控
- // SkillId 技能组为0则监控所有分机
- const msgObj = {
- Action: 'ReqAgentMonitor',
- Param: {
- Extension: m_strUserNo.value,
- CompanyId: m_strCompanyId.value,
- SkillId: '0',
- },
- };
- // 发送请求
- e_TelSendMsg(msgObj);
- };
- /**
- * {“Action”:”ResAgentMonitor”,”Param”:[{“Extension”:,”JobNumber”:,”SkillId”:,”Name”:,”Caller”:,”Called”:,”State”}]}
- * State:0:闲 1:忙 2:会议 3:登出 4:呼入 5:呼出 6:咨询 7:其他 8:通话 9:工单整理
- * 监控状态初始化返回状态
- * @param {any} data
- */
- const ResAgentMonitor = (data) => {
- if (null != data && null != data.Param && data.Param.length > 0) {
- // 监控分机集合
- const strMonitorInfo = JSON.stringify(data.Param);
- console.log(`${getNowDateTime()} 监控分机集合:`, strMonitorInfo);
- }
- };
- /*
- * 登录
- * ReqAgentLogin - 登录方法名
- * JobNum - 工号
- * Name - 姓名
- * Extension - 分机号
- * SkillId - 技能组
- * Level - 为要设置的级别,分为9个级别,从高到低分别为0-8;同一技能组中级别越高的坐席优先被分配
- * Role - 角色,保留,不做设置
- * GroupName - 技能组名称
- * OrgId - 组织ID
- * 返回内容:
- {“Action”:”ResAgentLogin”,”Param”:{“Result”:}}
- Result: 3:分机错误 7:已登录 0:登录成功
- */
- const sendSignIn = () => {
- callCenterWs.value = wsRef.value;
- const sendObj = {
- Action: 'ReqAgentLogin',
- Param: {
- ExtNum: m_strUserNo.value,
- JobNum: m_strJobNum.value,
- Name: m_strUserNo.value,
- Extension: m_strUserNo.value,
- SkillId: m_strSkillId.value,
- Level: m_strLevel.value,
- Role: '',
- GroupName: m_strGroup.value,
- OrgId: m_strCompanyId.value,
- },
- };
- // 发送请求
- e_TelSendMsg(sendObj);
- console.log(`${getNowDateTime()} 呼叫中心发起签入`);
- };
- const signTime = ref(0); //签入时长
- // 使用 useInterval 创建定时器
- const signInTimer = useIntervalFn(
- () => {
- signTime.value += 1;
- },
- 1000,
- { immediate: false }
- );
- // 签入时长及时开始
- const startSignTime = (second?: number) => {
- if (second) {
- // 从后台获取签入时长
- if (second < 0) second = 0; // 防止后台返回的签入时间大于当前时间
- signTime.value = second;
- signInTimer.resume();
- } else {
- signInTimer.resume();
- }
- };
- // 签入时长计时结束
- const stopSignTime = () => {
- signTime.value = 0;
- signInTimer.pause();
- };
- // 空闲时长
- const idleTime = ref(0);
- const idleTimer = useIntervalFn(
- () => {
- idleTime.value += 1;
- },
- 1000,
- { immediate: false }
- );
- // 空闲时长开始
- const startIdleTime = () => {
- idleTimer.resume();
- stopBusyTime(); // 结束示忙时长
- stopArrangeTime(); // 结束整理时长
- };
- // 空闲时长计时结束
- const stopIdleTime = () => {
- idleTime.value = 0;
- idleTimer.pause();
- };
- const appConfigStore = useAppConfig();
- const { AppConfigInfo } = storeToRefs(appConfigStore); // 系统配置信息
- const storesUserInfo = useUserInfo();
- const { userInfos } = storeToRefs(storesUserInfo); // 用户信息
- const onSignIn = () => {
- if (AppConfigInfo.value.isNeedTelNo) {
- // 需要填写分机号
- state.dutyDialogVisible = true;
- } else {
- if (!userInfos.value.defaultTelNo) {
- ElMessage.error('请先配置用户默认分机');
- return;
- }
- if (!userInfos.value.defaultTelGroup) {
- ElMessage.error('请先配置用户技能组');
- return;
- }
- state.loading = true;
- m_strUserNo.value = userInfos.value.defaultTelNo; // 默认分机
- m_strJobNum.value = <string>userInfos.value.staffNo; // 工号
- m_strSkillId.value = userInfos.value.defaultTelGroup; // 技能组
- currentTel.value = {
- telNo: userInfos.value.defaultTelNo,
- telGroup: userInfos.value.defaultTelGroup,
- jobNum: <string>userInfos.value.staffNo,
- };
- wsRef.value.open();
- }
- };
- const dutyFormRef = ref();
- const clickOnDuty = (formEl: FormInstance | undefined) => {
- if (!formEl) return;
- formEl.validate((valid: boolean) => {
- if (!valid) return;
- state.loading = true;
- m_strUserNo.value = <string>state.dutyForm.telNo;
- m_strJobNum.value = <string>state.dutyForm.telNo;
- m_strSkillId.value = <string>state.dutyForm.skillId;
- currentTel.value = {
- telNo: state.dutyForm.telNo,
- telGroup: state.dutyForm.skillId,
- jobNum: state.dutyForm.telNo,
- };
- wsRef.value.open();
- state.dutyDialogVisible = false;
- state.loading = false;
- });
- };
- // 签入消息回调
- const retSignIn = (data: any) => {
- state.loading = false;
- if (data.Param.Result === '0') {
- // 登录成功
- m_bLogin.value = true;
- m_strTelState.value = '100';
- e_TopStateChange(m_strTelState.value);
- // 刷新页面自动签出不需要调用业务系统签入
- // 附加签入方法(用户分机分离) 调用业务系统登录
- e_TelSignIn(m_strUserNo.value, m_strSkillId.value);
- // 登录成功
- startSignTime(); // 签入计时器
- callCenterIsSignIn.value = true; // 签入状态
- if (m_strIsMonitor.value === '1') {
- // 监控初始化状态
- ReqAgentMonitor();
- }
- console.log(`${getNowDateTime()} 呼叫中心签入成功回调`);
- } else if (data.Param.Result === '3') {
- // 登录不成功 调用业务系统
- e_TelSignOut(m_strUserNo.value, m_strSkillId.value);
- wsRef.value.close();
- // 分机错误
- ElMessage.error('分机错误');
- // 分机错误
- } else if (data.Param.Result === '7') {
- // 先签出再签入
- sendSignOut();
- }
- };
- // ws链接开启成功
- const e_websocketOpen = () => {
- sendSignIn();
- };
- // 链接关闭
- const e_websocketClose = () => {
- callCenterIsSignIn.value = false; // 签出状态
- console.log(`${getNowDateTime()} 呼叫中心链接关闭`);
- };
- // 链接错误
- const e_websocketError = () => {
- callCenterWs.value = null;
- callCenterIsSignIn.value = false; // 签出状态
- console.log(`${getNowDateTime()} 呼叫中心链接错误`);
- };
- // 消息接收
- const e_TelMsgReceive = (ws: any, restMsg: any) => {
- console.log(`${getNowDateTime()} 接收消息:${restMsg.data}`);
- if (restMsg.data) {
- const data = eval('(' + restMsg.data + ')');
- if (data) {
- // 方法
- const strAction = data.Action;
- switch (strAction) {
- // 登录返回值
- case 'ResAgentLogin':
- retSignIn(data);
- break;
- // 示闲
- case 'ResAgentIdle':
- retIdle(data);
- break;
- // 示忙
- case 'ResAgentBusy':
- retBusy(data);
- break;
- // 外呼状态
- case 'ResMakeCall':
- retCallOut(data);
- break;
- // 保持
- case 'ResHoldCall':
- retHold(data);
- break;
- // 取消保持
- case 'ResRetrieve':
- retRehold(data);
- break;
- // 咨询内线
- case 'ResConsultInline':
- retConsult(data, '0');
- break;
- // 咨询外线
- case 'ResConsultOutline':
- retConsult(data, '1');
- break;
- // 咨询群组
- case 'ResConsultSkillGroup':
- retConsult(data, '2');
- break;
- // 咨询转移
- case 'ResTransfer':
- retResTransfer(data);
- break;
- // 三方会议
- case 'ResConference':
- retResConference(data);
- break;
- // 三方会议
- case 'ResMonConf':
- retResConference(data);
- break;
- // 坐席实时状态
- case 'ResAgentMinitor':
- ResAgentMonitor(data);
- break;
- // 监听
- case 'ResMonListen':
- retResMonListen(data);
- break;
- // 取消监听返回
- case 'ResStopListen':
- retResStopListen(data);
- break;
- }
- // 事件
- const strEvent = data.Event;
- switch (strEvent) {
- // 签出事件
- case 'EvtLogout':
- retSignOut();
- break;
- // 呼入振铃事件
- case 'EvtCallAlerting':
- evtCallAlerting(data);
- break;
- // 应答事件
- case 'EvtCallAnswer':
- evtEvtCallAnswer(data);
- break;
- // 挂机事件
- case 'EvtHangup':
- retHangup(data);
- break;
- // 状态
- case 'EvtSeatState':
- evtSeatState(data);
- break;
- // 队列等待
- case 'EvtAcdInfo':
- i_QueueNum(data);
- break;
- // 语音识别结果通知事件
- case 'EvtRecognize':
- e_EvtRecognize(data.Param);
- break;
- // 转三方接通状态
- case 'EvtDispatchState':
- e_EvtDispatchState(data.Param);
- break;
- // 签出事件
- case 'ResStopMonitor':
- retSignOut();
- break;
- case 'ResError': // 异常
- retHangup(data); // 挂机
- // 异常处理
- retResError(data);
- break;
- // 呼出接通事件
- case 'EvtOutCalling':
- evtEvtCalling(data); // 呼出振铃事件
- break;
- // 签出事件
- case 'EvtQuit':
- retSignOut();
- break;
- }
- }
- }
- };
- /*
- * 签出
- * ReqAgentLogout - 签出方法名称
- * Extension - 分机号码
- */
- const sendSignOut = () => {
- const objMsg = {
- Action: 'ReqAgentLogout',
- Param: {
- Extension: m_strUserNo.value,
- },
- };
- // 发送请求
- e_TelSendMsg(objMsg);
- };
- const onSignOut = () => {
- ElMessageBox.confirm(`确定要签出,是否继续?`, '提示', {
- confirmButtonText: '确认',
- cancelButtonText: '取消',
- type: 'warning',
- draggable: true,
- cancelButtonClass: 'default-button',
- autofocus: false,
- })
- .then(() => {
- sendSignOut();
- })
- .catch(() => {
- state.loading = false;
- });
- };
- /*
- * 签出事件
- */
- const retSignOut = () => {
- // 刷新页面自动签出不需要调用业务系统签入
- // 附加签出方法(用户分机分离 调用业务系统等处)
- e_TelSignOut(m_strUserNo.value, m_strSkillId.value);
- state.loading = false;
- // 登出成功
- m_strTelState.value = '0';
- e_TopStateChange(m_strTelState.value);
- // 签出
- e_ActionUpdate('1'); // 更新话机动作
- m_bLogin.value = false;
- callCenterIsSignIn.value = false; // 签出状态
- stopSignTime(); // 停止签入计时器
- stopBusyTime(); // 停止示忙计时器
- stopIdleTime(); // 停止空闲计时器
- stopTalkTimer(); // 停止通话计时器
- stopArrangeTime(); // 停止整理时长
- // 关闭ws
- wsRef.value.close();
- console.log(`${getNowDateTime()} 呼叫中心签出回调`);
- };
- /*
- * 示忙
- * ReqAgentBusy - 方法名
- * Extension:分机号
- */
- // 示忙时长
- const busyTime = ref(0);
- const busyTimer = useIntervalFn(
- () => {
- busyTime.value += 1;
- },
- 1000,
- { immediate: false }
- );
- // 示忙时长开始
- const startBusyTime = () => {
- busyTimer.resume();
- };
- // 示忙时长计时结束
- const stopBusyTime = () => {
- busyTime.value = 0;
- busyTimer.pause();
- };
- const onBusy = () => {
- ElMessageBox.confirm(`确定要示忙,是否继续?`, '提示', {
- confirmButtonText: '确认',
- cancelButtonText: '取消',
- type: 'warning',
- draggable: true,
- cancelButtonClass: 'default-button',
- autofocus: false,
- })
- .then(() => {
- const objMsg = {
- Action: 'ReqAgentBusy',
- Param: {
- Extension: m_strUserNo.value,
- },
- };
- // 发送请求
- e_TelSendMsg(objMsg);
- })
- .catch(() => {
- state.loading = false;
- });
- };
- /*
- * 示忙返回值
- {“Action”:”ResAgentBusy”,”Param”:{“Result”:}}
- Result:0-1
- 0:成功 1:失败
- */
- const retBusy = (data) => {
- if (data.Param.Result === '0') {
- m_bTelBusy.value = true;
- m_strTelState.value = '201';
- e_TopStateChange(m_strTelState.value);
- } else {
- ElMessage.error('示忙失败');
- }
- };
- /*
- * 示闲
- * ReqAgentIdle - 方法名
- * Extension:分机号
- */
- const onIdle = () => {
- ElMessageBox.confirm(`确定要示闲,是否继续?`, '提示', {
- confirmButtonText: '确认',
- cancelButtonText: '取消',
- type: 'warning',
- draggable: true,
- cancelButtonClass: 'default-button',
- autofocus: false,
- })
- .then(() => {
- const objMsg = {
- Action: 'ReqAgentIdle',
- Param: {
- Extension: m_strUserNo.value,
- },
- };
- // 发送请求
- e_TelSendMsg(objMsg);
- })
- .catch(() => {
- state.loading = false;
- });
- };
- /*
- * 示闲返回值
- * {“Action”:”ResAgentIdle”,”Param”:{“Result”:}}
- Result:0-1
- 0:成功 1:失败
- */
- const retIdle = (data) => {
- if (data.Param.Result == '0') {
- m_bTelBusy.value = false;
- m_strTelState.value = '200';
- e_TopStateChange(m_strTelState.value);
- // m_IsTalkingDeal.value = false;
- } else {
- ElMessage.error('示闲失败');
- }
- };
- /*
- * 保持
- */
- const onHold = () => {
- ElMessageBox.confirm(`确定要保持,是否继续?`, '提示', {
- confirmButtonText: '确认',
- cancelButtonText: '取消',
- type: 'warning',
- draggable: true,
- cancelButtonClass: 'default-button',
- autofocus: false,
- })
- .then(() => {
- const objMsg = {
- Action: 'ReqHoldCall',
- Param: {
- Extension: m_strUserNo.value,
- },
- };
- // 发送请求
- e_TelSendMsg(objMsg);
- })
- .catch(() => {
- state.loading = false;
- });
- };
- /*
- * 保持返回
- */
- const retHold = (data) => {
- if (data.Param.Result == '0') {
- m_IsHold.value = true;
- m_strTelState.value = '310';
- e_TopStateChange(m_strTelState.value);
- } else {
- ElMessage.error('保持操作失败');
- }
- };
- /*
- * 取消保持
- */
- const onReHold = () => {
- ElMessageBox.confirm(`确定要恢复,是否继续?`, '提示', {
- confirmButtonText: '确认',
- cancelButtonText: '取消',
- type: 'warning',
- draggable: true,
- cancelButtonClass: 'default-button',
- autofocus: false,
- })
- .then(() => {
- const objMsg = {
- Action: 'ReqRetrieve',
- Param: {
- Extension: m_strUserNo.value,
- },
- };
- // 发送请求
- e_TelSendMsg(objMsg);
- })
- .catch(() => {
- state.loading = false;
- });
- };
- /*
- * 取消保持返回状态
- */
- const retRehold = (data) => {
- if (data.Param.Result == '0') {
- // 是否是保持通话
- m_IsHold.value = false;
- if (m_IsCallIn.value) {
- m_strTelState.value = '301';
- } else {
- m_strTelState.value = '303';
- }
- e_TopStateChange(m_strTelState.value);
- } else {
- ElMessage.error('取消保持操作失败');
- }
- };
- // 外呼
- const onCallOut = () => {
- state.loading = false;
- state.outboundDialogVisible = true;
- };
- const outboundFormRef = ref<RefType>();
- const clickOnOutbound = (formEl: FormInstance | undefined) => {
- if (!formEl) return;
- formEl.validate((valid: boolean) => {
- if (!valid) return;
- state.loading = true;
- callout(state.outboundForm.telNo);
- state.outboundDialogVisible = false;
- });
- };
- /*
- * 外呼
- * ReqMakeCall - 方法名
- * Extension:分机号
- * Called:被叫
- * CustomerId:客户ID
- */
- const callout = (strCallNumber) => {
- if (!strCallNumber) {
- ElMessage.error('电话号码不能为空');
- return;
- }
- const obkMsg = {
- Action: 'ReqMakeCall',
- Param: {
- Extension: m_strUserNo.value,
- Called: strCallNumber,
- CustomerId: '',
- },
- };
- // 是否外呼
- m_IsCallOut.value = true;
- // 发送请求
- e_TelSendMsg(obkMsg);
- };
- /*
- * 外呼返回事件
- {“Action”:”ResMakeCall”,”Param”:{“Result”:}}
- Result:0-1
- 0:成功 1:失败
- */
- const retCallOut = (data) => {
- state.loading = false;
- if (data.Param.Result == '0') {
- // 是否外呼
- m_IsCallOut.value = true; // 呼出
- m_strTelState.value = '302';
- e_TopStateChange(m_strTelState.value);
- } else {
- ElMessage.error('呼叫失败');
- }
- };
- /*
- * 咨询
- */
- const onConsultOpen = () => {
- m_strTelState.value = '331';
- // 保持状态
- m_IsHold.value = true;
- state.loading = false;
- state.consultDialogVisible = true;
- };
- const consultFormRef = ref<RefType>();
- const clickOnConsult = (formEl: FormInstance | undefined) => {
- if (!formEl) return;
- formEl.validate((valid: boolean) => {
- if (!valid) return;
- state.loading = true;
- onConsult(state.consultForm.telNo, state.consultForm.strType);
- state.consultDialogVisible = false;
- });
- };
- const onConsult = (strCallNumber: string, strType: string) => {
- let strObj;
- switch (strType) {
- // 内线
- case '0':
- strObj = {
- Action: 'ReqConsultInline',
- Param: {
- Extension: m_strUserNo.value,
- TargetExtension: strCallNumber,
- },
- };
- break;
- // 外线
- case '1':
- strObj = {
- Action: 'ReqConsultOutline',
- Param: {
- Extension: m_strUserNo.value,
- TargetCalled: strCallNumber,
- },
- };
- break;
- // 群组
- case '2':
- strObj = {
- Action: 'ReqConsultSkillGroup',
- Param: {
- Extension: m_strUserNo.value,
- TargetSkillGroup: strCallNumber,
- },
- };
- break;
- }
- // 转接类型
- m_strConsultType.value = strType;
- // 外呼
- m_IsCallOut.value = true;
- // 咨询状态
- m_IsConsult.value = true;
- // 发送请求
- e_TelSendMsg(strObj);
- };
- /*
- * 转接返回
- * data
- * {“Action”:”ResConsultSkillGroup”,”Param”:{“Result”:}}Result:0-1
- * 0:成功 1:失败
- * strType:0-转内线;1-转外线;2-转群组
- */
- const retConsult = (data: any, strType: string) => {
- state.loading = false;
- if (data.Param.Result == '0') {
- // 咨询成功
- // m_IsConsult = true;
- //m_strTelState = "330";
- // e_TopStateChange(m_strTelState);
- } else {
- //alert("转接失败");
- if (!m_IsHangup.value) {
- if (m_IsCallOut.value) {
- // 呼出接通
- m_strTelState.value = '303';
- } else {
- // 呼入接通
- m_strTelState.value = '301';
- }
- e_TopStateChange(m_strTelState.value);
- }
- let strMsg = '咨询失败';
- if (strType == '0') {
- strMsg = '咨询内线失败';
- } else if (strType == '1') {
- strMsg = '咨询外线失败';
- } else if (strType == '2') {
- strMsg = '咨询技能组失败';
- }
- ElMessage.error(strMsg);
- }
- };
- /*
- * 转接
- */
- const onTransfer = () => {
- const objMsg = {
- Action: 'ReqTransfer',
- Param: {
- Extension: m_strUserNo.value,
- },
- };
- // 发送请求
- e_TelSendMsg(objMsg);
- };
- /*
- * 转接返回
- */
- const retResTransfer = (data: any) => {
- if (data.Param.Result == '0') {
- // 咨询成功
- m_IsConsult.value = true;
- m_strTelState.value = '320';
- e_TopStateChange(m_strTelState.value);
- } else {
- ElMessage.error('转接失败');
- }
- };
- /*
- * 盲转
- */
- const onTransferMzOpen = () => {
- state.loading = false;
- state.blindDialogVisible = true;
- };
- const blindFormRef = ref<RefType>();
- const clickOnBlind = (formEl: FormInstance | undefined) => {
- if (!formEl) return;
- formEl.validate((valid: boolean) => {
- if (!valid) return;
- state.loading = true;
- onTransferMz(state.blindForm.telNo);
- state.blindDialogVisible = false;
- });
- };
- const onTransferMz = (strCallNumber) => {
- const objMsg = {
- Action: 'ReqBlindTransfer',
- Param: {
- Extension: m_strUserNo.value,
- TargetCalled: strCallNumber,
- },
- };
- // 发送请求
- e_TelSendMsg(objMsg);
- state.loading = false;
- console.log(`${getNowDateTime()}盲转消息:${JSON.stringify(objMsg)}`);
- // 结束挂机
- useTimeoutFn(() => {
- sendHangup();
- }, 300);
- };
- /*
- * 三方会议
- */
- const onConference = () => {
- ElMessageBox.confirm(`确定要发起三方会议,是否继续?`, '提示', {
- confirmButtonText: '确认',
- cancelButtonText: '取消',
- type: 'warning',
- draggable: true,
- cancelButtonClass: 'default-button',
- autofocus: false,
- })
- .then(() => {
- state.loading = true;
- const objMsg = {
- Action: 'ReqConference',
- Param: {
- Extension: m_strUserNo.value,
- },
- };
- // 发送请求
- e_TelSendMsg(objMsg);
- })
- .catch(() => {
- state.loading = false;
- });
- };
- // 会议时长
- const conferenceTime = ref(0);
- const conferenceTimer = useIntervalFn(
- () => {
- conferenceTime.value += 1;
- },
- 1000,
- { immediate: false }
- );
- // 三方会议开始
- const startConferenceTime = () => {
- conferenceTimer.resume();
- };
- // 三方会议时长计时结束
- const stopConferenceTime = () => {
- conferenceTime.value = 0;
- conferenceTimer.pause();
- };
- /*
- * 三方会议返回
- * { "Action": "ReqConference", "Param": {"Extension": "1002"} }
- */
- const retResConference = (data) => {
- state.loading = false;
- if (data.Param.Result == '0') {
- // 咨询成功
- m_IsConsult.value = true;
- m_strTelState.value = '320';
- e_TopStateChange(m_strTelState.value);
- } else {
- ElMessage.error('三方会议失败');
- }
- };
- /*
- * 挂机
- * ReqHangup - 方法名
- * Extension:分机号
- {“Event”: “EvtHangup”}
- */
- const sendHangup = () => {
- const objMsg = {
- Action: 'ReqHangup',
- Param: {
- Extension: m_strUserNo.value,
- },
- };
- // 发送请求
- e_TelSendMsg(objMsg);
- };
- const onHangup = () => {
- ElMessageBox.confirm(`确定要挂机,是否继续?`, '提示', {
- confirmButtonText: '确认',
- cancelButtonText: '取消',
- type: 'warning',
- draggable: true,
- cancelButtonClass: 'default-button',
- autofocus: false,
- })
- .then(() => {
- sendHangup();
- })
- .catch(() => {
- state.loading = false;
- });
- };
- /*
- * 挂机事件
- * {“Event”: “EvtHangup”}
- */
- const retHangup = (data?: any) => {
- // 挂机后该状态为 false
- console.log(`${getNowDateTime()}:接收消息:呼叫中心挂机回调`, data);
- // 挂机后该状态为 false
- // 挂机
- m_IsHangup.value = true;
- m_IsCallIn.value = false;
- m_IsCallOut.value = false;
- m_bCallConnect.value = false;
- callCenterIsOnThePhone.value = false;
- m_IsConsult.value = false;
- m_IsHold.value = false;
- // 是否弹屏
- m_bIsOpen.value = false;
- m_strConsultType.value = '-1';
- /* if(!m_IsTalkingDeal.value){ // 如果不当前状态不是话后整理状态
- m_strTelState.value = '200';
- e_TopStateChange(m_strTelState.value);
- }*/
- m_strTelState.value = '200';
- e_TopStateChange(m_strTelState.value);
- // 未监听
- m_IsMonListen.value = '0';
- // 呼出是否弹屏(用于未接统计“回拨”业务处理)
- m_CallOutOpen.value = false;
- // 清除呼叫ID
- callId.value = '';
- };
- /*
- * 评价
- */
- const i_evaluate = () => {
- ElMessageBox.confirm(`确定要开启评价,评价后将直接挂机,是否继续?`, '提示', {
- confirmButtonText: '确认',
- cancelButtonText: '取消',
- type: 'warning',
- draggable: true,
- cancelButtonClass: 'default-button',
- autofocus: false,
- })
- .then(() => {
- const objMsg = {
- Action: 'ReqSatisfaction',
- Param: {
- Extension: m_strUserNo.value,
- },
- };
- // 发送请求
- e_TelSendMsg(objMsg);
- state.loading = false;
- console.log(`${getNowDateTime()}评价消息:${JSON.stringify(objMsg)}`);
- // 结束挂机
- useTimeoutFn(() => {
- sendHangup();
- }, 300);
- })
- .catch(() => {
- state.loading = false;
- });
- };
- /*
- * 监听
- */
- const reqMonListen = (strTargetNum) => {
- const objMsg = {
- Action: 'ReqMonListen',
- Param: {
- Extension: m_strUserNo.value,
- TargetExtension: strTargetNum,
- },
- };
- // 发送请求
- e_TelSendMsg(objMsg);
- };
- /*
- * 监听返回
- */
- const retResMonListen = (data) => {
- if (data.Param.Result == '0') {
- m_IsMonListen.value = '1';
- // 成功
- } else {
- m_IsMonListen.value = '2';
- }
- };
- /*
- * 取消监听
- */
- const reqStopListen = (strTargetNum) => {
- const objMsg = {
- Action: 'ReqStopListen',
- Param: {
- Extension: m_strUserNo.value,
- TargetExtension: strTargetNum,
- },
- };
- // 发送请求
- e_TelSendMsg(objMsg);
- };
- /*
- * 取消监听返回
- */
- const retResStopListen = (data) => {
- if (data.Param.Result == '0') {
- m_IsMonListen.value = '1';
- // 成功
- } else {
- m_IsMonListen.value = '2';
- }
- };
- /*
- * 呼入(振铃)事件
- * EvtCallAlerting - 事件名称
- * Caller:主叫
- * Called:被叫
- * Customerid:客户ID
- * Callid:呼叫ID
- {“Event”:”EvtCallAlerting”,”Param”:{“Caller”:”123”,”Called”:”456”,”Customerid”:”675”,”Callid”:”94593939”}}
- */
- const router = useRouter();
- const evtCallAlerting = (data) => {
- let strCalledNum;
- let strTelNumber;
- console.log(
- `开始振铃,是否呼出:${m_IsCallOut.value},是否呼出弹屏:${m_CallOutOpen.value},是否弹屏:${m_bIsOpen.value},弹屏方式:${
- m_strOpenFlag.value === '1' ? '接通弹屏' : '振铃弹屏'
- }`
- );
- if (m_IsCallOut.value) {
- // 呼出
- // 呼出振铃
- m_strTelState.value = '302';
- e_TopStateChange(m_strTelState.value);
- if (m_CallOutOpen.value) {
- // 呼出是否弹屏(用于未接统计“回拨”业务处理)
- // 主叫号码
- strTelNumber = data.Param.Caller;
- // 被叫号码
- strCalledNum = data.Param.Called;
- // 呼叫ID
- callId.value = data.Param.Callid;
- if (!m_bIsOpen.value && m_strOpenFlag.value == '2') {
- // 振铃呼出弹屏
- console.log(
- '呼出是否弹屏[' +
- m_bIsOpen.value +
- '];弹屏方式[' +
- m_strOpenFlag.value +
- '];记录ID[' +
- callId.value +
- '];主叫号码[' +
- strTelNumber +
- '];被叫号码[' +
- strCalledNum +
- ']'
- );
- m_bIsOpen.value = true;
- // 呼出不再弹单
- m_CallOutOpen.value = false;
- // 去电弹屏
- router.push({
- name: 'orderAccept',
- query: {
- createBy: 'tel',
- fromTel: strTelNumber, // 来电号码
- callId: callId.value, // 通话ID
- transfer: strCalledNum, // 转接来源(如12345,12333)
- telArea: '',
- identityType: '', // 按键接收(1:市民 2:企业 3:智能应答)
- },
- });
- }
- }
- } else {
- // 呼入振铃该状态为呼入
- m_IsCallIn.value = true;
- // 呼入振铃
- m_strTelState.value = '300';
- e_TopStateChange(m_strTelState.value);
- // 主叫号码
- strTelNumber = data.Param.Caller;
- // 被叫号码
- strCalledNum = data.Param.Called;
- // 呼叫ID
- callId.value = data.Param.Callid;
- if (strTelNumber.length == strCalledNum.length && strTelNumber.length == 4) {
- // 如果主叫号码、被叫号码都是分机号码,则不弹屏
- m_bIsOpen.value = true;
- }
- if (!m_bIsOpen.value && m_strOpenFlag.value === '2') {
- m_bIsOpen.value = true;
- // 用户按键
- const strDigit = data.Param.Digit;
- console.log(
- '用户按键[' + strDigit + '];记录ID[' + callId.value + '];主叫号码[' + strTelNumber + '];被叫号码[' + strCalledNum + ']',
- '来电弹屏'
- );
- router.push({
- name: 'orderAccept',
- query: {
- createBy: 'tel',
- fromTel: strTelNumber, // 来电号码
- callId: callId.value, // 通话ID
- transfer: strCalledNum, // 转接来源(如12345,12333)
- telArea: '',
- identityType: strDigit, // 按键接收(1:市民 2:企业 3:智能应答)
- },
- });
- }
- }
- };
- /*
- * 应答事件
- * Caller:主叫
- * Called:被叫
- * Callid:呼叫ID
- {“Event”:”EvtCallAnswer”,”Param”:{“Caller”:”123”,”Called”:”456”,”Callid”:”94593939”}}
- */
- const talkTime = ref(0); // 通话时长
- const talkTimer = useIntervalFn(
- () => {
- talkTime.value += 1;
- Local.set('talkTime', String(talkTime.value));
- },
- 1000,
- { immediate: false }
- );
- // 开始通话计时
- const startTalkTimer = () => {
- let localTalkTime = Local.get('talkTime');
- if (talkTime.value) {
- talkTime.value = Number(localTalkTime);
- }
- talkTimer.resume();
- stopIdleTime();
- };
- // 结束通话计时
- const stopTalkTimer = () => {
- talkTimer.pause();
- talkTime.value = 0;
- Local.remove('talkTime');
- };
- const evtEvtCallAnswer = (data) => {
- let strCalledNum;
- let strTelNumber;
- // 通话接通
- m_bCallConnect.value = true;
- callCenterIsOnThePhone.value = true;
- console.log(
- `接通电话,是否呼出:${m_IsCallOut.value},是否咨询:${m_IsConsult.value},是否呼出弹屏:${m_CallOutOpen.value},是否弹屏:${
- m_bIsOpen.value
- },弹屏方式:${m_strOpenFlag.value === '1' ? '接通弹屏' : '振铃弹屏'}`
- );
- if (m_IsCallOut.value) {
- // 呼出
- if (!m_IsConsult.value) {
- // 不是转接、三方会议呼出
- // 呼出应答
- m_strTelState.value = '303';
- e_TopStateChange(m_strTelState.value);
- if (m_CallOutOpen.value) {
- // 呼出是否弹屏(用于未接统计“回拨”业务处理)
- // 主叫号码
- strTelNumber = data.Param.Caller;
- // 被叫号码
- strCalledNum = data.Param.Called;
- // 呼叫ID
- callId.value = data.Param.Callid;
- mittBus.emit('outboundConnect', {
- callNumber: strCalledNum, // 被叫号码
- callId: callId.value, //呼叫ID
- }); // 外呼接通之后收到的消息
- if (!m_bIsOpen.value && m_strOpenFlag.value === '1') {
- console.log(
- '呼出是否弹屏[' +
- m_bIsOpen.value +
- '];弹屏方式[' +
- m_strOpenFlag.value +
- '];记录ID[' +
- callId.value +
- '];主叫号码[' +
- strTelNumber +
- '];被叫号码[' +
- strCalledNum +
- ']'
- );
- m_bIsOpen.value = true;
- // 呼出不再弹单
- m_CallOutOpen.value = false;
- router.push({
- name: 'orderAccept',
- query: {
- createBy: 'tel',
- fromTel: strTelNumber, // 来电号码
- callId: callId.value, // 通话ID
- transfer: strCalledNum, // 转接来源(如12345,12333)
- telArea: '',
- identityType: '', // 按键接收(1:市民 2:企业 3:智能应答)
- },
- });
- }
- }
- }
- } else {
- // 呼入应答
- m_strTelState.value = '301';
- e_TopStateChange(m_strTelState.value);
- // 呼入应答
- // 主叫号码
- strTelNumber = data.Param.Caller;
- // 被叫号码
- strCalledNum = data.Param.Called;
- // 呼叫ID
- callId.value = data.Param.Callid;
- console.log(
- '是否弹屏[' +
- m_bIsOpen.value +
- '];弹屏方式[' +
- m_strOpenFlag.value +
- '];记录ID[' +
- callId.value +
- '];主叫号码[' +
- strTelNumber +
- '];被叫号码[' +
- strCalledNum +
- ']'
- );
- if (strTelNumber.length == strCalledNum.length && strTelNumber.length == 4) {
- // 如果主叫号码、被叫号码都是分机号码,则不弹屏
- m_bIsOpen.value = true;
- }
- if (!m_bIsOpen.value && m_strOpenFlag.value === '1') {
- m_bIsOpen.value = true;
- // 用户按键
- const strDigit = data.Param.Digit;
- console.log(
- '用户按键' +
- strDigit +
- '是否弹屏[' +
- m_bIsOpen.value +
- '];弹屏方式[' +
- m_strOpenFlag.value +
- '];记录ID[' +
- callId.value +
- '];主叫号码[' +
- strTelNumber +
- '];被叫号码[' +
- strCalledNum +
- ']'
- );
- router.push({
- name: 'orderAccept',
- query: {
- createBy: 'tel',
- fromTel: strTelNumber, // 来电号码
- callId: callId.value, // 通话ID
- transfer: strCalledNum, // 转接来源(如12345,12333)
- telArea: '',
- identityType: strDigit, // 按键接收(1:市民 2:企业 3:智能应答)
- },
- });
- }
- }
- if (!m_IsConsult.value) {
- // 如果不是咨询,则启动通话时间计时器
- startTalkTimer(); // 通话计时器开始
- }
- };
- /*
- * 39.外呼振铃事件
- * Caller:主叫
- * Called:被叫
- * Callid:呼叫ID
- {“Event”:”EvtOutCalling”,”Param”:{“Caller”:”123”,”Called”:”456”,”Customerid”:”675”,”Callid”:”94593939”}}
- */
- const evtEvtCalling = (data) => {
- let strCalledNum;
- let strTelNumber;
- m_IsCallOut.value = true; // 呼出
- console.log(
- `开始振铃,是否呼出:${m_IsCallOut.value},是否呼出弹屏:${m_CallOutOpen.value},是否弹屏:${m_bIsOpen.value},弹屏方式:${
- m_strOpenFlag.value === '1' ? '接通弹屏' : '振铃弹屏'
- }`
- );
- if (m_CallOutOpen.value) {
- // 主叫号码
- strTelNumber = data.Param.Caller;
- // 被叫号码
- strCalledNum = data.Param.Called;
- // 呼叫ID
- callId.value = data.Param.Callid;
- if (!m_bIsOpen.value && m_strOpenFlag.value === '2') {
- //振铃弹屏
- m_bIsOpen.value = true;
- console.log(
- '呼出是否弹屏[' +
- m_bIsOpen.value +
- '];弹屏方式[' +
- m_strOpenFlag.value +
- '];记录ID[' +
- callId.value +
- '];主叫号码[' +
- strTelNumber +
- '];被叫号码[' +
- strCalledNum +
- ']'
- );
- router.push({
- name: 'orderAccept',
- query: {
- createBy: 'tel',
- fromTel: strTelNumber, // 来电号码
- callId: callId.value, // 通话ID
- transfer: strCalledNum, // 转接来源(如12345,12333)
- telArea: '',
- identityType: '', // 按键接收(1:市民 2:企业 3:智能应答)
- },
- });
- }
- }
- };
- /*
- * 计算接通时长
- */
- // 是否在队列状态
- const m_bIsQueue = ref(false);
- /*
- * 队列等待
- */
- const i_QueueNum = (data) => {
- // 40,87098300,85961020,1,80|40,87098300,85961020,1,80|40,87098300,85961020,1,80
- // 处于队列状态
- m_bIsQueue.value = true;
- // 队列信息
- const strInfo = data.Param.Info;
- if (undefined != strInfo && '' != strInfo) {
- const arrFirst = strInfo.split('|');
- if (null != arrFirst && 0 < arrFirst.length) {
- // 设置队列等待数量
- console.log(arrFirst.length - 1);
- e_SetQueryWait(arrFirst.length - 1, strInfo);
- }
- }
- console.log(`${getNowDateTime()}:队列消息:`, data.Param, strInfo);
- };
- /*
- 语音识别结果保存
- */
- const e_EvtRecognize = (data) => {
- console.log('EvtRecognize' + JSON.stringify(data));
- const strDirection = data.Direciton || '';
- const strResult = data.Result || '';
- console.log(`${getNowDateTime()}:识别结果`, strResult, strDirection);
- };
- /*
- 转三方接通状态
- */
- const e_EvtDispatchState = (data: any) => {
- const strState = data.State || '';
- console.log(`${getNowDateTime()}:转接三方状态-EvtDispatchState:`, data, `是否咨询状态:${m_IsConsult.value},当前str:${strState}`);
- if (strState === '2') {
- if (m_IsConsult.value) {
- // 咨询成功
- m_strTelState.value = '330';
- e_TopStateChange(m_strTelState.value);
- }
- } else if (strState === '3') {
- if (m_IsConsult.value) {
- m_strTelState.value = '301';
- m_IsHold.value = false; // 三方有一方挂断 取消保持
- e_TopStateChange(m_strTelState.value);
- }
- } else {
- //alert("转接失败");
- }
- };
- /**
- * 异常处理
- * @param {any} data
- */
- const retResError = (data: any) => {
- if (data.Param.Result == '99') {
- // 掉线
- m_strTelState.value = '0';
- e_TopStateChange(m_strTelState.value);
- ElMessage.error('连接已断开');
- // 自动签入
- onSignIn();
- }
- };
- // 改变状态方法
- const e_TopStateChange = (state: string) => {
- console.log(`${getNowDateTime()}:状态改变:`, state);
- switch (state) {
- case '0': // 签出
- break;
- case '100': // 登录成功
- break;
- case '200': // 空闲
- break;
- case '201': // 示忙
- break;
- case '300': //呼入振铃
- break;
- case '301': // 呼入通话
- stopConferenceTime();
- break;
- case '302': // 呼出振铃
- break;
- case '303': // 呼出通话
- stopConferenceTime();
- break;
- case '310': // 通话保持
- break;
- case '320': // 三方会议
- startConferenceTime(); // 三方会议时长开始
- break;
- case '330': // 转接
- break;
- case '331': // 转接
- break;
- case '900': // 整理
- break;
- }
- // console.log(state);
- };
- /**
- * 更新话机动作
- * 1:登录登出;2:示忙示闲;3:摘机
- */
- const e_ActionUpdate = (strActionType: string) => {
- const data = {
- Action: 'ActionUpdate',
- ActType: strActionType,
- };
- };
- /*
- * 用户分机签入签出(用户分机分离业务)
- * 业务改造,先签入我方业务系统,再签入呼叫中心
- *
- */
- const e_TelSignIn = async (telNo: string, groupId: string) => {
- const data = {
- telNo,
- groupId,
- telModelState: 1,
- };
- try {
- const { result } = await callCenterSignIn(data);
- console.log(`${getNowDateTime()}:业务系统:签入成功`, result);
- } catch (e) {
- console.log(e);
- sendSignOut(); // 签出
- }
- };
- /*
- * 用户分机签出(用户分机分离业务)
- */
- const e_TelSignOut = async (telNo: string, groupId: string) => {
- const data = {
- telNo,
- groupId,
- telModelState: 1,
- };
- try {
- await callCenterSignOut(data);
- console.log(`${getNowDateTime()}:业务系统:签出成功`);
- } catch (e) {
- console.log(e);
- }
- };
- /**
- * 保存队列信息
- * @param {any} strUserNum
- * @param strQueueInfo
- */
- const e_SetQueryWait = (strUserNum, strQueueInfo) => {
- const data = {
- Action: 'SaveQueueNumNew',
- QueueNum: strUserNum,
- QueueInfo: strQueueInfo,
- };
- };
- // 获取基础信息
- const telsList = ref([]);
- const telsListGroup = ref([]);
- const getBaseInfo = async () => {
- try {
- const [tels, telGroup] = await Promise.all([getCallCenterList(), getCallCenterGroupList()]);
- telsList.value = tels?.result ?? [];
- telsListGroup.value = telGroup?.result ?? [];
- } catch (e) {
- console.log(e);
- }
- };
- // 检查用户状态
- onMounted(async () => {
- await getBaseInfo();
- initWs();
- // 是否在通话中
- window.onbeforeunload = function (e) {
- if (m_bCallConnect.value) {
- const dialogText = '正在通话中,您确定要刷新吗?';
- e.returnValue = dialogText;
- return dialogText;
- }
- };
- });
- </script>
- <style scoped lang="scss">
- .seizeSeat-box {
- display: none;
- }
- .phoneControls {
- display: flex;
- flex: 1;
- background-color: var(--el-color-white) !important;
- padding: 0 10px;
- color: var(--hotline-color-text-main);
- height: 100%;
- align-items: center;
- .status-box {
- width: 240px;
- display: flex;
- align-items: center;
- justify-content: space-between;
- background: var(--el-color-info-light-7);
- position: relative;
- box-sizing: border-box;
- cursor: pointer;
- text-align: left;
- font-size: 14px;
- padding: 4px 26px 4px 12px;
- gap: 6px;
- min-height: 32px;
- line-height: 24px;
- border-radius: var(--el-border-radius-round);
- background-color: var(--el-color-info-light-8);
- transition: var(--el-transition-duration);
- .arrow {
- position: absolute;
- right: 10px;
- transition: transform var(--el-transition-duration);
- }
- .is-reverse {
- transform: rotate(180deg);
- }
- }
- // 按钮列表
- .btn-container {
- display: flex;
- justify-content: space-between;
- width: calc(100% - 100px);
- height: 100%;
- border-right: 1px solid var(--el-border-color);
- border-left: 1px solid var(--el-border-color);
- overflow: hidden;
- .item {
- text-align: center;
- cursor: pointer;
- width: 100%;
- user-select: none;
- display: flex;
- align-items: center;
- justify-content: center;
- //border-right: 1px solid var(--el-border-color);
- .icon {
- color: var(--el-color-primary);
- }
- &.disabled {
- cursor: not-allowed;
- overflow: hidden;
- .icon {
- color: #cccccc;
- }
- }
- }
- .active {
- &:hover {
- color: var(--hotline-color-white);
- background-color: var(--el-color-primary);
- .icon {
- color: var(--hotline-color-white);
- }
- }
- }
- }
- }
- </style>
|