Jelajahi Sumber

更新代码

sunxiao 2 bulan lalu
induk
melakukan
b582913225

+ 6 - 6
html/ie.html

@@ -112,6 +112,12 @@
           <p class="sub-title">请下载或使用一下任意浏览器的最新版本:</p>
         </div>
         <ul class="list">
+          <li>
+            <a href="http://se.360.cn/" target="_blank">
+              <img src="./img/icon-360.svg" alt="">
+              <span>360安全浏览器</span>
+            </a>
+          </li>
           <li>
             <a href="https://www.google.cn/chrome/browser/desktop/index.html?hl=zh-CN&standalone=1" target="_blank">
               <img src="./img/icon-chrome.svg" alt="">
@@ -124,12 +130,6 @@
               <span>火狐浏览器</span>
             </a>
           </li>
-          <li>
-            <a href="http://se.360.cn/" target="_blank">
-              <img src="./img/icon-360.svg" alt="">
-              <span>360安全浏览器</span>
-            </a>
-          </li>
         </ul>
       </div>
     </div>

+ 2 - 1
src/components/CallView/index.vue

@@ -10,6 +10,7 @@ import VoiceToText from '@/components/VoiceToText';
 import { watch, watchEffect } from 'vue';
 
 const emit = defineEmits(['onEnd'])
+const modelValue = defineModel('modelValue');
 
 const props = defineProps({
   noInit: {
@@ -158,7 +159,7 @@ const onVoiceParsed = ({ parsedVoiceContent, id }) => {
       </div>
     </custom-row-item>
     <custom-row-item label="通话录音" v-if="callDetails.url">
-      <VoiceToText @on-parsed="onVoiceParsed" :content="callDetails.parsedVoiceContent" :id="callDetails.id">
+      <VoiceToText @on-parsed="onVoiceParsed" :content="callDetails.parsedVoiceContent" :id="callDetails.id" v-model="modelValue">
         <AudioPlayer :audioUrl="callDetails.url" ref="audioPlayerRef"></AudioPlayer>
       </VoiceToText>
     </custom-row-item>

+ 14 - 7
src/components/VoiceToText/index.vue

@@ -4,6 +4,7 @@ import { workbenchApi } from '@/api/voice/workbench';
 import { watchEffect } from 'vue';
 
 const emit = defineEmits(['onParsed']);
+const modelValue = defineModel('modelValue')
 const props = defineProps({
   content: {
     type: String,
@@ -44,14 +45,20 @@ const handleTransformVoiceToText = async () => {
 
   if ( !props.content ) {
     try {
+      modelValue.value = true
       ElMessage.warning('语音开始转换中, 请耐心等待,切勿进行其他操作');
-      const { data } = await workbenchApi.getVoiceToText({ id });
-      if ( data ) {
-        if ( props.id === id ) {
-          parsedVoiceList.value = JSON.parse(data);
-          emit('onParsed', { parsedVoiceContent: data, id });
-          isExpandStatus.value['id' + id] = !isExpandStatus.value['id' + id];
-        }
+      try {
+        await workbenchApi.getVoiceToText({ id }).then(({ data }) => {
+          if ( data ) {
+            if ( props.id === id ) {
+              parsedVoiceList.value = JSON.parse(data);
+              emit('onParsed', { parsedVoiceContent: data, id });
+              isExpandStatus.value['id' + id] = !isExpandStatus.value['id' + id];
+            }
+          }
+        })
+      } catch (error) {
+        modelValue.value = false;
       }
     } catch (error) {}
   } else {

+ 5 - 0
src/layout/components/HeaderGroup/index.vue

@@ -34,6 +34,11 @@ const handlePopoverItem = async ({ state, label }) => {
   // if( voiceStore.HSCTIERRORCODE == 100002) {
   //   return alert("有问题");
   // }
+  await voiceStore.getAgentStatus();
+  
+  if ( voiceStore.AGENTSTATUS == 0 ) {
+    return proxy.$modal.msgError('当前当前坐席没有嵌入成功, 状态切换失败');
+  }
 
   state ? await voiceStore.setIdle() : await voiceStore.setBusy();
   proxy.$modal[state ? 'msgSuccess' : 'msgWarning']('当前坐席状态: ' + label);

+ 12 - 5
src/permission.js

@@ -1,3 +1,5 @@
+
+
 import router from './router'
 import { ElMessage } from 'element-plus'
 import NProgress from 'nprogress'
@@ -14,13 +16,13 @@ NProgress.configure({ showSpinner: false });
 const whiteList = ['/login', '/register'];
 
 router.beforeEach((to, from, next) => {
-  NProgress.start()
+  NProgress.start();
   if (getToken()) {
     to.meta.title && useSettingsStore().setTitle(to.meta.title)
     /* has token*/
     if (to.path === '/login') {
-      next({ path: '/' })
-      NProgress.done()
+      next();
+      NProgress.done();
     } else if (whiteList.indexOf(to.path) !== -1) {
       next()
     } else {
@@ -30,6 +32,10 @@ router.beforeEach((to, from, next) => {
         useUserStore().getInfo().then(() => {
           isRelogin.show = false
           usePermissionStore().generateRoutes().then(accessRoutes => {
+            if (accessRoutes.length == 0) {
+               next({ path: '/login' })
+               return
+            }
             // 根据roles权限生成可访问的路由表
             accessRoutes.forEach(route => {
               if (!isHttp(route.path)) {
@@ -54,7 +60,8 @@ router.beforeEach((to, from, next) => {
       // 在免登录白名单,直接进入
       next()
     } else {
-      next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页
+      // ?redirect=${to.fullPath}
+      next(`/login`) // 否则全部重定向到登录页
       NProgress.done()
     }
   }
@@ -62,4 +69,4 @@ router.beforeEach((to, from, next) => {
 
 router.afterEach(() => {
   NProgress.done()
-})
+})

+ 4 - 4
src/router/index.js

@@ -57,10 +57,10 @@ export const constantRoutes = [
     component: () => import('@/views/error/401'),
     hidden: true
   },
-  {
-    path: '',
+  // {
+    // path: '',
     // component: Layout,
-    redirect: '/voice/workbench',
+    // redirect: '/voice/workbench',
     // children: [
     //   {
     //     path: '/index',
@@ -69,7 +69,7 @@ export const constantRoutes = [
     //     meta: { title: '首页', icon: 'dashboard', affix: true }
     //   }
     // ]
-  },
+  // },
   {
     path: '/user',
     component: Layout,

+ 1 - 1
src/store/modules/user.js

@@ -44,7 +44,7 @@ const useUserStore = defineStore(
               this.roles = res.roles
               this.permissions = res.permissions
             } else {
-              this.roles = ['ROLE_DEFAULT']
+              this.roles = []
             }
             this.id = user.userId
             this.name = user.userName

+ 2 - 8
src/store/modules/voice.js

@@ -171,20 +171,14 @@ const useVoiceStore = defineStore('voice', () => {
   const listenScoketEvent = (CTIEvent) => {
     HS_CTI.on(CTIEvent.OnCtiError,(res)=>{
       HSCTIERRORCODE.value = res.code;
-      ElNotification({
-        title: '提示',
-        message: res.msg,
-        showClose: true,
-        type: 'warning',
-      })
-      return
       switch (res.code) {
         case '100002':
           ElNotification({
             title: '提示',
-            message: res.msg,
+            message: '请开启麦克风权限,才能正常使用系统',
             showClose: true,
             type: 'warning',
+            duration: 0
           })
           break;
       }

+ 4 - 3
src/views/error/404.vue

@@ -17,15 +17,16 @@
         <div class="bullshit__info">
           对不起,您正在寻找的页面不存在。尝试检查URL的错误,然后按浏览器上的刷新按钮或尝试在我们的应用程序中找到其他内容。
         </div>
-        <router-link to="/index" class="bullshit__return-home">
-          返回首页
-        </router-link>
+        <div class="bullshit__return-home" @click="router.back()">
+          返回
+        </div>
       </div>
     </div>
   </div>
 </template>
 
 <script setup>
+const router = useRouter();
 let message = computed(() => {
   return '找不到网页!'
 })

+ 23 - 15
src/views/login.vue

@@ -67,6 +67,7 @@ import Cookies from "js-cookie";
 import { encrypt, decrypt } from "@/utils/jsencrypt";
 import useUserStore from '@/store/modules/user'
 import usePermissionStore from '@/store/modules/permission' 
+import { removeToken } from '@/utils/auth'
 
 const userStore = useUserStore()
 const route = useRoute();
@@ -128,22 +129,29 @@ function handleLogin() {
 
     usePermissionStore().generateRoutes().then(accessRoutes => {
       if ( accessRoutes.length ) {
-        let isOff = false;
-        accessRoutes.forEach(({ children }) => {
-          children?.forEach(item => {
-            if ( item.path === 'voice/workbench' ) {
-              isOff = true;
-            }
-          })
-        });
+        const path = accessRoutes[0]?.children[0]?.path;
+        router.push({ path });
+        // let isOff = false;
+        // accessRoutes.forEach(({ children }) => {
+        //   children?.forEach(item => {
+        //     if ( item.path === 'voice/workbench' ) {
+        //       isOff = true;
+        //     }
+        //   })
+        // });
 
-        if ( isOff ) {
-          router.push({ path: "/voice/workbench", query: otherQueryParams });
-        } else {
-          const path = accessRoutes[0]?.children[0]?.path;
-          router.push({ path });
-        }
-      } 
+        // if ( isOff ) {
+        //   router.push({ path: "/voice/workbench", query: otherQueryParams });
+        // } else {
+        //   const path = accessRoutes[0]?.children[0]?.path;
+        //   router.push({ path });
+        // }
+      } else {
+        loading.value = false;
+        proxy.$modal.msgError("当前账号未分配权限");
+        removeToken();
+
+      }
     })
     
     // router.push({ path: "/voice/workbench", query: otherQueryParams });

+ 53 - 12
src/views/voice/call/index.vue

@@ -1,11 +1,10 @@
 <script setup>
-import { useRouter } from 'vue-router'
 import { workbenchApi } from '@/api/voice/workbench';
 import SearchItemWrapper from '@/components/SearchItemWrapper';
 import AudioPlayer from '@/components/AudioPlayer';
 import useTableHeight from '@/composables/useTableHeight';
+import CallView from '@/components/CallView';
 
-const router = useRouter();
 const { proxy } = getCurrentInstance();
 const { tableContainer, tableMaxHeight } = useTableHeight();
 
@@ -14,6 +13,10 @@ const loading = ref(false);
 const tableData = ref([]);
 const total = ref(0);
 const agentList = ref([]);
+const drawer = ref(false);
+const callDetails = ref({});
+
+const isTransitionVoiceStatus = ref(false);
 
 const queryParams = ref({
   pageNum: 1,
@@ -38,11 +41,15 @@ const handleCleanOptions = () => {
   getList();
 }
 
-const jumpDetails = ({ id }) => {
-  router.push({
-    path: '/voice/call/details',
-    query: { id }
-  })
+// 语音转化完成
+const handleVoiceParsed = (item) => {
+  const { parsedVoiceContent } = item;
+  callDetails.value.parsedVoiceContent = parsedVoiceContent;
+}
+
+const jumpDetails = (item) => {
+  callDetails.value = item;
+  drawer.value = true;
 }
 
 // 音频加载完成
@@ -54,11 +61,22 @@ const onAudioLoadDone = ({ durationTime, id }) => {
   })
 }
 
+const handleClose = (done) => {
+  if ( !isTransitionVoiceStatus.value ) {
+    done();
+  } else {
+    proxy.$modal.msgWarning("当前语音正在转换中,请稍后");
+  }
+}
+
 // 批量下载
 const handleBatchDownload = () => {
   const [timeBegin, timeEnd] = dataPickerValue.value;
+  if ( !timeBegin ) {
+    return proxy.$modal.msgError("请选择通话发起时间");
+  }
   proxy.getDownload("/business/record/downloadBatchByCondition", {
-    ...queryParams.value, timeBegin, timeEnd
+    ...queryParams.value, timeBeginReq: timeBegin, timeEndReq: timeEnd
   }, `${new Date().getTime()}.zip`);
 }
 
@@ -72,7 +90,7 @@ const getList = () => {
 
   loading.value = true;
 
-  workbenchApi.getCallRecordList({...queryParams.value, timeBegin, timeEnd}).then(({ rows, total:t }) => {
+  workbenchApi.getCallRecordList({...queryParams.value, timeBeginReq:timeBegin, timeEndReq: timeEnd}).then(({ rows, total:t }) => {
     const typeEnum = { 0: '白名单', 1: 'AI客服', 2: '传统服务' };
     const statusEnum = { 0: '未接听', 1: '已接通' };
     const serviceCategoryEnum = { 0: '人工坐席', 1: '机器人坐席', 2: '机器人转人工' };
@@ -108,7 +126,7 @@ onMounted(() => {
           </SearchItemWrapper>
         </el-col>
         <el-col :span="6">
-          <SearchItemWrapper label="客服">
+          <SearchItemWrapper label="客服名称">
             <el-select v-model="queryParams.userId" placeholder="请选择" size="large" :empty-values="[null, undefined]">
               <el-option label="全部" value="" />
               <el-option v-for="item in agentList" :key="item.id" :label="item.name" :value="item.id" />
@@ -173,6 +191,7 @@ onMounted(() => {
               </div>
             </template>
           </el-table-column>
+          <el-table-column prop="sessionId" label="通话ID" align="center" width="150" />
           <el-table-column prop="timeBegin" label="通话发起时间" align="center" width="180" />
           <el-table-column prop="timeEnd" label="通话结束时间" align="center" width="180" />
           <el-table-column prop="times" label="通话时长" align="center" />
@@ -184,7 +203,7 @@ onMounted(() => {
             </template>
           </el-table-column>
           <el-table-column prop="serviceCategoryText" label="服务类型" align="center" width="120"/>
-          <el-table-column prop="userName" label="客服" align="center" />
+          <el-table-column prop="userName" label="客服名称" align="center" />
           <el-table-column prop="handle" label="操作" align="center" fixed="right" width="150">
             <template #default="scope">
               <div class="flex justify-center space-x-[20px]">
@@ -197,8 +216,20 @@ onMounted(() => {
         <pagination v-show="total >= 0" :total="total" v-model:page="queryParams.pageNum"
           v-model:limit="queryParams.pageSize" @pagination="getList" />
       </div>
-
     </div>
+
+    <el-drawer
+      v-model="drawer"
+      title="通话详情"
+      direction="rtl"
+      :before-close="handleClose"
+      class="voice-drawer"
+      size="800"
+    >
+      <div>
+        <CallView :data="callDetails" noInit @on-end="handleVoiceParsed" v-model="isTransitionVoiceStatus"></CallView>
+      </div>
+    </el-drawer>
   </div>
 </template>
 
@@ -225,3 +256,13 @@ onMounted(() => {
   }
 }
 </style>
+
+<style lang="scss">
+.voice-drawer {
+  .el-drawer__header {
+    margin-bottom: 0;
+    color: #333;
+    font-weight: bold;
+  }
+}
+</style>

+ 0 - 393
src/views/voice/workbench/index copy.vue

@@ -1,393 +0,0 @@
-<script setup>
-import { ElMessage } from 'element-plus';
-import { workbenchApi } from '@/api/voice/workbench';
-import useVoiceStore from "@/store/modules/voice";
-
-import RecordCardItem from './components/RecordCardItem';
-import CustomRowItem from './components/CustomRowItem.vue';
-import AudioPlayer from '@/components/AudioPlayer';
-import CallView from '@/components/CallView';
-
-const queryParams = ref({
-  pageNum: 1,
-  pageSize: 10,
-  category: 0,
-  phone: ''
-});
-
-const voiceStore = useVoiceStore();
-
-const remark = ref('');
-const tabCallRecordList = ref([]);
-const tabCurrentActive = ref(null);
-const callDetails = ref({});
-
-const isExpand = ref(false);
-const dialogVisible = ref(false);
-
-const total = ref(0);
-const loading = ref(false);
-
-const tabEnum = ['通话呼入', '通话呼出'];
-const categoryTypeEnum = {
-  0: '人工客服',
-  1: '机器人',
-  2: '机器人转人工'
-}
-
-const typeEnum = {
-  0: '白名单',
-  1: 'AI客服',
-  2: '传统服务'
-}
-
-const disabled = computed(() => loading.value || total.value == tabCallRecordList.value.length);
-
-// 切换tabs
-const handleChangeTab = (index) => {
-  queryParams.value.pageNum = 1;
-  queryParams.value.category = index;
-  tabCallRecordList.value = [];
-  initTabsData();
-}
-
-// 选中通话记录
-const hanldeTabItem = (i) => {
-  tabCurrentActive.value = i;
-  callDetails.value = tabCallRecordList.value[i];
-}
-
-// 编辑
-const handleEdit = () => {
-  dialogVisible.value = true;
-  remark.value = callDetails.value.remark;
-}
-
-// 弹窗 - 确定
-const onDialogConfirm = () => {
-  const { id } = callDetails.value;
-  workbenchApi.putCallRecord({ id, remark: remark.value }).then(() => {
-    dialogVisible.value = false;
-    callDetails.value.remark = remark.value;
-    ElMessage({
-      message: '备注更改成功',
-      type: 'success',
-    })
-  })
-}
-
-// 弹窗 - 取消
-const onDialogCancel = () => {
-  dialogVisible.value = false;
-  remark.value = callDetails.value.remark;
-}
-
-// 搜索
-const onSearch = () => {
-  queryParams.value.pageNum = 1;
-  tabCallRecordList.value = [];
-  initTabsData();
-}
-
-// 拨打电话
-const onConfirm = () => {
-  voiceStore.onMakingCall("15810954324");
-}
-
-const initTabsData = async () => {
-  loading.value = true;
-  const { rows, total: t } = await workbenchApi.getCallRecordList(queryParams.value);
-
-  tabCallRecordList.value = [...tabCallRecordList.value, ...rows];
-  total.value = t;
-  loading.value = false;
-}
-
-onMounted(async () => {
-  initTabsData();
-});
-
-const loadMoreData = () => {
-  queryParams.value.pageNum += 1;
-  initTabsData();
-}
-</script>
-
-<template>
-  <div class="workbench-viewport space-x-[16px]">
-    <div class="record-section">
-      <ul class="tabs-nav space-x-[48px]">
-        <li v-for="item, index in tabEnum" :class="['tabs-nav-item', { active: queryParams.category === index }]"
-          :key="item" @click="handleChangeTab(index)">{{ item }}</li>
-      </ul>
-      <div class="tabs-content">
-        <div class="search-inp-wrapper">
-          <div class="search-inp">
-            <input type="text" class="inp" placeholder="请输入电话号码" v-model="queryParams.phone">
-            <div class="btn" @click="onSearch">搜索</div>
-          </div>
-        </div>
-        <div class="search-result-wrapper">
-          <el-scrollbar height="100%">
-            <div 
-              class="search-result-inner space-y-[8px]"
-              v-infinite-scroll="loadMoreData"
-              :infinite-scroll-disabled="disabled"
-              v-show="tabCallRecordList.length"
-            >
-              <RecordCardItem 
-                v-for="item, index in tabCallRecordList"
-                :data="item"
-                :index="index"
-                :active="tabCurrentActive === index"
-                :key="item.id"
-                @on-click="hanldeTabItem(index)"
-              ></RecordCardItem>
-              <div class="flex justify-center text-[#999] text-[12px]">
-                <p class="pb-[6px]" v-if="loading">Loading...</p>
-              </div>
-            </div>
-            
-            <div class="flex items-center justify-center pt-[100px]" v-show="!tabCallRecordList.length">
-              <span class="text-[#999] text-[14px]">暂无数据</span>
-            </div>
-          </el-scrollbar>
-        </div>
-      </div>
-    </div>
-    <div class="details-section">
-      <div class="empty-wrapper" v-show="!callDetails.id">
-        <img src="@/assets/images/workbench/img-empty.png" alt="">
-        <p class="empty-text">
-          <span>Hi, 下午好~</span>
-          <span>欢迎登录智能语音客服</span>
-        </p>
-      </div>
-      <div class="details-wrapper" v-show="callDetails.id">
-        <h4 class="title">通话详情</h4>
-        <el-scrollbar class="details-scrollbar">
-          <CallView></CallView>
-        </el-scrollbar>
-      </div>
-    </div>
-
-    <el-dialog v-model="dialogVisible" title="编辑备注" width="530" modal-class="custom-workbench-dialog" align-center>
-      <template #header>
-        <div class="dialog-header">
-          <h4>编辑备注</h4>
-        </div>
-      </template>
-      <div class="dialog-body">
-        <el-input type="textarea" :autosize="{ minRows: 6, maxRows: 6 }" resize="none" v-model="remark"></el-input>
-      </div>
-      <template #footer>
-        <div class="dialog-footer space-x-[14px]">
-          <div class="custom-btn custom-btn_primary" @click="onDialogConfirm">确定</div>
-          <div class="custom-btn custom-btn_default" @click="onDialogCancel">取消</div>
-        </div>
-      </template>
-    </el-dialog>
-
-  </div>
-</template>
-
-<style lang="scss" scoped>
-$primaryColor: #165DFF;
-
-.workbench-viewport {
-  display: flex;
-  height: 100%;
-  background: #eceff6;
-
-  .record-section {
-    flex-shrink: 0;
-    width: 292px;
-    height: 100%;
-    border-radius: 8px;
-    background: linear-gradient(180deg, #FFF 0%, #FFF 100%);
-
-    .tabs-nav {
-      display: flex;
-      align-items: center;
-      justify-content: center;
-      height: 46px;
-      padding-top: 15px;
-      border-bottom: 1px solid #E5E6EB;
-      font-size: 14px;
-      line-height: 20px;
-      color: #4E5969;
-
-      .tabs-nav-item {
-        position: relative;
-        cursor: pointer;
-
-        &.active {
-          color: $primaryColor;
-          font-weight: bold;
-
-          &::after {
-            position: absolute;
-            left: 0;
-            bottom: -6px;
-            content: ' ';
-            display: block;
-            width: 100%;
-            height: 2px;
-            background: $primaryColor;
-          }
-        }
-      }
-
-    }
-
-    .tabs-content {
-      height: calc(100% - 46px);
-
-      .search-inp-wrapper {
-        padding: 12px 22px;
-
-        .search-inp {
-          display: flex;
-          align-items: center;
-          height: 34px;
-          padding: 2px;
-          border-radius: 8px;
-          background: #F2F4F7;
-
-          .inp {
-            width: 100%;
-            padding: 0 10px;
-            background: transparent;
-            outline: none;
-            font-size: 13px;
-            color: #1D2129;
-          }
-
-          .btn {
-            flex-shrink: 0;
-            width: 52px;
-            height: 30px;
-            border-radius: 8px;
-            background: #165DFF;
-            color: #FFF;
-            font-size: 13px;
-            line-height: 30px;
-            text-align: center;
-            cursor: pointer;
-          }
-        }
-      }
-
-      .search-result-wrapper {
-        height: calc(100% - 58px);
-
-        .search-result-inner {
-          padding: 0 22px;
-        }
-      }
-    }
-  }
-
-  .details-section {
-    width: 100%;
-    min-width: 700px;
-    height: 100%;
-    border-radius: 8px;
-    overflow: hidden;
-    padding: 20px;
-    background: #fff;
-
-    .details-scrollbar {
-      height: calc(100% - 50px);
-    }
-
-    .empty-wrapper {
-      display: flex;
-      align-items: center;
-      justify-content: center;
-      flex-flow: column;
-      width: 100%;
-      height: 100%;
-
-      .empty-text {
-        span {
-          display: block;
-          text-align: center;
-          font-weight: bold;
-          font-size: 24px;
-          line-height: 32px;
-
-          &:nth-child(1) {
-            color: #165DFF;
-          }
-
-          &:nth-child(2) {
-            color: #1D2129;
-          }
-        }
-      }
-    }
-
-    .details-wrapper {
-      height: 100%;
-
-      .title {
-        margin-bottom: 24px;
-        color: #1D2129;
-        font-size: 18px;
-        font-weight: bold;
-        line-height: 26px;
-      }
-
-      .details-inner {
-        :deep(.custom-label) {
-          display: inline-block;
-          width: 84px;
-          color: #86909C;
-          box-sizing: border-box;
-          font-size: 14px;
-          font-weight: normal;
-          line-height: 23px;
-          text-align: left;
-        }
-
-        :deep(.custom-colums) {
-          font-size: 14px;
-          color: #1D2129;
-        }
-
-        .record-box {
-          width: 100%;
-          padding: 16px;
-          border-radius: 8px;
-          background: linear-gradient(90deg, #F6F5F8 0%, #FFF 100%);
-
-          .record-play-control {
-            display: flex;
-            align-items: center;
-            padding: 0;
-            font-size: 14px;
-          }
-
-          .record-play-content {
-            padding-top: 12px;
-            color: #4E5969;
-            font-family: "PingFang SC";
-            font-size: 13px;
-            line-height: 20px;
-          }
-        }
-      }
-    }
-  }
-}
-
-.dialog-footer {
-  display: flex;
-  justify-content: center;
-}
-
-:deep(.el-textarea__inner) {
-  background: #f2f4f7;
-}
-</style>

+ 12 - 5
src/views/voice/workbench/index.vue

@@ -11,10 +11,14 @@ const queryParams = ref({
   phone: ''
 });
 
+const { proxy } = getCurrentInstance();
+
 const tabCallRecordList = ref([]);
 const tabCurrentActive = ref(null);
 const callDetails = ref({});
 
+const isTransitionVoiceStatus = ref(false);
+
 const total = ref(0);
 const loading = ref(false);
 
@@ -50,12 +54,15 @@ const handleChangeTab = (index) => {
 
 // 选中通话记录
 const hanldeTabItem = async (id) => {
-  const { data } = await workbenchApi.getCallRecordDetails(id);
-  callDetails.value = data;
-  tabCurrentActive.value = id;
+  if ( !isTransitionVoiceStatus.value ) {
+    const { data } = await workbenchApi.getCallRecordDetails(id);
+    callDetails.value = data;
+    tabCurrentActive.value = id;
+  } else {
+    proxy.$modal.msgWarning("当前语音正在转换中,请稍后");
+  }
 }
 
-
 // 搜索
 const onSearch = ( type ) => {
   if ( type === 'refresh' ) {
@@ -152,7 +159,7 @@ const loadMoreData = () => {
       <div class="details-wrapper" v-show="callDetails.id && tabCurrentActive !== null">
         <h4 class="title">通话详情</h4>
         <el-scrollbar class="details-scrollbar">
-          <CallView :data="callDetails" noInit @on-end="handleVoiceParsed"></CallView>
+          <CallView :data="callDetails" noInit @on-end="handleVoiceParsed" v-model="isTransitionVoiceStatus"></CallView>
         </el-scrollbar>
       </div>
     </div>