123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222 |
- <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';
- const router = useRouter();
- const { proxy } = getCurrentInstance();
- const { tableContainer, tableMaxHeight } = useTableHeight();
- const dataPickerValue = ref([]);
- const loading = ref(false);
- const tableData = ref([]);
- const total = ref(0);
- const agentList = ref([]);
- const queryParams = ref({
- pageNum: 1,
- pageSize: 10,
- userId: '',
- status: '',
- category: '',
- phone: '',
- })
- // 清除检索条件
- const handleCleanOptions = () => {
- queryParams.value = {
- pageNum: 1,
- pageSize: 10,
- userId: '',
- status: '',
- category: '',
- phone: '',
- };
- dataPickerValue.value = [];
- getList();
- }
- const jumpDetails = ({ id }) => {
- router.push({
- path: '/voice/call/details',
- query: { id }
- })
- }
- // 音频加载完成
- const onAudioLoadDone = ({ durationTime, id }) => {
- tableData.value.map(item => {
- if (item.id == id) {
- item.times = durationTime || ''
- }
- })
- }
- // 批量下载
- const handleBatchDownload = () => {
- const [timeBegin, timeEnd] = dataPickerValue.value;
- proxy.getDownload("/business/record/downloadBatchByCondition", {
- ...queryParams.value, timeBegin, timeEnd
- }, `${new Date().getTime()}.zip`);
- }
- // 单独下载
- const handleDownload = ({ id }) => {
- proxy.getDownload("/business/record/downloadById", { id }, `${new Date().getTime()}.wav`);
- }
- const getList = () => {
- const [timeBegin, timeEnd] = dataPickerValue.value || [];
- loading.value = true;
- workbenchApi.getCallRecordList({...queryParams.value, timeBegin, timeEnd}).then(({ rows, total:t }) => {
- const typeEnum = { 0: '白名单', 1: 'AI客服', 2: '传统服务' };
- const statusEnum = { 0: '未接听', 1: '已接通' };
- const serviceCategoryEnum = { 0: '人工坐席', 1: '机器人坐席', 2: '机器人转人工' };
- tableData.value = rows.map(item => ({
- ...item,
- url: item.url ? item.url + '?timstamp=' + new Date().getTime() : '',
- typeText: typeEnum[item.type],
- statusText: statusEnum[item.status],
- serviceCategoryText: serviceCategoryEnum[item.serviceCategory]
- }));
- loading.value = false;
- total.value = t;
- })
- };
- onMounted(() => {
- workbenchApi.getAgentList().then(({ data }) => {
- agentList.value = data;
- })
- getList();
- })
- </script>
- <template>
- <div class="call-viewprot">
- <div class="search-card">
- <el-row :gutter="24" class="mb-[24px]">
- <el-col :span="6">
- <SearchItemWrapper>
- <el-input class="search-input" placeholder="用户电话号码" v-model="queryParams.phone"></el-input>
- </SearchItemWrapper>
- </el-col>
- <el-col :span="6">
- <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" />
- </el-select>
- </SearchItemWrapper>
- </el-col>
- <el-col :span="6">
- <SearchItemWrapper label="通话状态">
- <el-select v-model="queryParams.status" placeholder="Select" size="large" :empty-values="[null, undefined]">
- <el-option label="全部" value="" />
- <el-option label="未接听" :value="0" />
- <el-option label="已接通" :value="1" />
- </el-select>
- </SearchItemWrapper>
- </el-col>
- <el-col :span="6">
- <SearchItemWrapper label="通话类型">
- <el-select v-model="queryParams.category" placeholder="全部" size="large" :empty-values="[null, undefined]">
- <el-option label="全部" value="" />
- <el-option label="呼入" :value="0" />
- <el-option label="呼出" :value="1" />
- </el-select>
- </SearchItemWrapper>
- </el-col>
- </el-row>
- <el-row :gutter="24">
- <el-col :span="6">
- <SearchItemWrapper label="通话发起时间">
- <el-date-picker v-model="dataPickerValue" type="daterange" range-separator="-" start-placeholder="起始日期"
- end-placeholder="结束日期" style="width: 100%;" :editable="false" value-format="YYYY-MM-DD"/>
- </SearchItemWrapper>
- </el-col>
- <el-col :span="18">
- <div class="flex items-center justify-start space-x-[30px]">
- <div class="custom-btn custom-btn_primary" @click="getList">搜索</div>
- <div class="custom-btn custom-btn_default" @click="handleBatchDownload">
- 批量下载语音
- </div>
- <div class="custom-btn custom-btn_text space-x-[2px]" @click="handleCleanOptions">
- <img src="@/assets/images/workbench/icon-clean.svg" alt="">
- <span>清除条件</span>
- </div>
- </div>
- </el-col>
- </el-row>
- </div>
- <div class="table-card">
- <div style="height: 100%;" ref="tableContainer">
- <el-table :data="tableData" style="width: 100%" :max-height="tableMaxHeight" v-loading="loading">
- <el-table-column prop="phone" label="用户电话" align="center" width="130" fixed />
- <el-table-column prop="typeText" label="呼叫类型" align="center" width="100" />
- <el-table-column prop="statusText" label="通话状态" align="center" width="100">
- <template #default="scope">
- <div class="flex items-center justify-center space-x-[6px]">
- <span class="w-[6px] h-[6px] rounded-full" :class="[scope.row.status === 1 ? 'bg-[#65C734]': 'bg-[#c75134]']" ></span>
- <span>{{ scope.row.statusText }}</span>
- </div>
- </template>
- </el-table-column>
- <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" />
- <el-table-column prop="address" label="通话录音" align="center" width="350">
- <template #default="scope">
- <div class="flex justify-center" v-show="scope.row.url">
- <AudioPlayer :audioUrl="scope.row.url" @loadDone="onAudioLoadDone" :id="scope.row.id"></AudioPlayer>
- </div>
- </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="handle" label="操作" align="center" fixed="right" width="150">
- <template #default="scope">
- <div class="flex justify-center space-x-[20px]">
- <span class="text-[#165DFF] cursor-pointer" @click="jumpDetails(scope.row)">详情</span>
- <span class="text-[#165DFF] cursor-pointer" @click="handleDownload(scope.row)">语音下载</span>
- </div>
- </template>
- </el-table-column>
- </el-table>
- <pagination v-show="total >= 0" :total="total" v-model:page="queryParams.pageNum"
- v-model:limit="queryParams.pageSize" @pagination="getList" />
- </div>
- </div>
- </div>
- </template>
- <style lang="scss" scoped>
- .call-viewprot {
- display: flex;
- flex-flow: column;
- width: 100%;
- height: 100%;
- padding: 28px 24px 18px 24px;
- border-radius: 8px;
- background: #fff;
- .search-card {
- padding-bottom: 20px;
- margin-bottom: 20px;
- border-bottom: 1px dashed #E5E6EB;
- overflow: hidden;
- flex-shrink: 0;
- }
- .table-card {
- height: 100%;
- }
- }
- </style>
|