Smart-visit-Detail.vue 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. <template>
  2. <el-dialog v-model="state.dialogVisible" width="60%" draggable title="回访明细" append-to-body destroy-on-close @close="close">
  3. <el-form :model="state.queryParams" ref="queryParamsRef" inline @submit.native.prevent>
  4. <el-form-item label="关键词" prop="Keyword">
  5. <el-input v-model="state.queryParams.Keyword" placeholder="工单标题/工单编码" clearable @keyup.enter="handleQuery" />
  6. </el-form-item>
  7. <el-form-item label="任务状态" prop="AiOrderVisitState">
  8. <el-select v-model="state.queryParams.AiOrderVisitState" placeholder="请选择任务状态" @change="handleQuery" clearable>
  9. <el-option v-for="item in aiOrderVisitState" :value="item.key" :key="item.key" :label="item.value" />
  10. </el-select>
  11. </el-form-item>
  12. <el-form-item>
  13. <el-button type="primary" @click="handleQuery" :loading="state.loading"> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
  14. <el-button @click="resetQuery(queryParamsRef)" :loading="state.loading" class="default-button">
  15. <SvgIcon name="ele-Refresh" class="mr5" />重置
  16. </el-button>
  17. </el-form-item>
  18. </el-form>
  19. <ProTable
  20. ref="proTableRef"
  21. :columns="columns"
  22. :data="state.tableData"
  23. @updateTable="queryList"
  24. :loading="state.loading"
  25. :total="state.total"
  26. v-model:page-index="state.queryParams.PageIndex"
  27. v-model:page-size="state.queryParams.PageSize"
  28. :toolButton="['refresh', 'setting', 'exportCurrent', 'exportAll']"
  29. :exportMethod="getSmartVisitDetailExport"
  30. :exportParams="requestParams"
  31. >
  32. <template #operation="{ row }">
  33. <template>
  34. <el-button type="primary" @click="onPlaySoundRecording(row)" title="播放录音" link v-if="row.recordUrl">播放录音</el-button>
  35. <el-button link type="primary" @click="onDownload(row)" title="下载录音" v-if="row.recordUrl"> 下载录音 </el-button>
  36. </template>
  37. </template>
  38. <template #title="{ row }">
  39. <order-detail :order="row.order" @updateList="queryList">{{ row.order?.title }}</order-detail>
  40. </template>
  41. </ProTable>
  42. </el-dialog>
  43. </template>
  44. <script setup lang="tsx">
  45. import { formatDate } from '@/utils/formatTime';
  46. import {ElMessageBox, FormInstance} from 'element-plus';
  47. import { defineAsyncComponent, reactive, ref } from 'vue';
  48. import {getSmartVisitBaseData, getSmartVisitDetail, getSmartVisitDetailExport, getSmartVisitExport} from '@/api/smartVisit';
  49. import { downloadFileByStream } from '@/utils/tools';
  50. const OrderDetail = defineAsyncComponent(() => import('@/components/OrderDetail/index.vue')); // 工单详情
  51. const pagination = defineAsyncComponent(() => import('@/components/ProTable/components/Pagination.vue')); // 分页
  52. const PlayRecord = defineAsyncComponent(() => import('@/views/tels/callLog/component/Play-record.vue')); // 播放录音
  53. const state = reactive({
  54. queryParams: {
  55. // 查询条件
  56. PageIndex: 1,
  57. PageSize: 10,
  58. Keyword: null, // 关键字
  59. id: '',
  60. AiOrderVisitState: null,
  61. },
  62. tableData: [], //表格
  63. loading: false, // 加载
  64. total: 0, // 总数
  65. dialogVisible: false, // 弹窗
  66. });
  67. const columns = ref<any[]>([
  68. { prop: 'order.no', label: '工单编码', width: 150 },
  69. {
  70. label: '标题',
  71. prop: 'order.title',
  72. width: 300,
  73. },
  74. { prop: 'aiOrderVisitStateText', label: '外呼状态', width: 150 },
  75. {
  76. label: '是否成功',
  77. prop: 'isSuccessText',
  78. width: 80,
  79. },
  80. { prop: 'outerNo', label: '外呼电话', width: 150 },
  81. { prop: 'order.fromName', label: '姓名', width: 150 },
  82. { prop: 'order.fromGenderText', label: '性别', width: 150 },
  83. {
  84. label: '受理时间',
  85. prop: 'order.startTime',
  86. width: 170,
  87. render: (scope: any) => {
  88. return <span>{formatDate(scope.row.order?.startTime, 'YYYY-mm-dd HH:MM:SS')}</span>;
  89. },
  90. },
  91. {
  92. label: '办结时间',
  93. prop: 'order.filedTime',
  94. width: 170,
  95. render: (scope: any) => {
  96. return <span>{formatDate(scope.row.order?.filedTime, 'YYYY-mm-dd HH:MM:SS')}</span>;
  97. },
  98. },
  99. {
  100. label: '话务员评价',
  101. prop: 'seatEvaluateText',
  102. width: 120,
  103. },
  104. {
  105. label: '部门办件结果',
  106. prop: 'orgProcessingResults',
  107. width: 170,
  108. },
  109. {
  110. label: '部门是否联系',
  111. prop: 'isContact',
  112. width: 170,
  113. },
  114. {
  115. label: '处理结果',
  116. prop: 'volved',
  117. width: 170,
  118. },
  119. // { prop: 'operation', label: '操作', fixed: 'right', width: 160, align: 'center' },
  120. ]);
  121. // 页面基础数据
  122. const aiOrderVisitState = ref([]);
  123. const getBaseData = async () => {
  124. try {
  125. const { result } = await getSmartVisitBaseData();
  126. aiOrderVisitState.value = result.aiOrderVisitState;
  127. } catch (e) {
  128. console.log(e);
  129. }
  130. };
  131. // 打开弹窗
  132. const openDialog = (row?: any) => {
  133. if (row) {
  134. state.dialogVisible = true;
  135. getBaseData();
  136. state.queryParams.id = row.id;
  137. queryList();
  138. }
  139. };
  140. // 手动查询,将页码设置为1
  141. const handleQuery = () => {
  142. state.queryParams.PageIndex = 1;
  143. queryList();
  144. };
  145. // 查询智能回访明细表
  146. const requestParams = ref({})
  147. const queryList = async () => {
  148. state.loading = true;
  149. try {
  150. state.tableData = [];
  151. requestParams.value = state.queryParams;
  152. const res = await getSmartVisitDetail(state.queryParams);
  153. state.tableData = res.result.items ?? [];
  154. state.total = res.result.total ?? 0;
  155. state.loading = false;
  156. } catch (e) {
  157. console.log(e);
  158. state.loading = false;
  159. state.tableData = [];
  160. }
  161. };
  162. const close = () => {
  163. queryParamsRef.value?.resetFields();
  164. queryParamsRef.value?.resetFields();
  165. };
  166. // 播放录音
  167. const playRecordRef = ref<RefType>();
  168. const onPlaySoundRecording = (val: any) => {
  169. playRecordRef.value.openDialog(
  170. import.meta.env.VITE_RECORD_PREFIX + val.recordingAbsolutePath,
  171. val.recordingFileName,
  172. val.recordingAbsolutePath,
  173. val.cpn,
  174. val.createdTime
  175. );
  176. };
  177. // 下载录音
  178. const onDownload = (row: any) => {
  179. ElMessageBox.confirm(`您确定要下载此录音吗?`, '提示', {
  180. confirmButtonText: '确认',
  181. cancelButtonText: '取消',
  182. type: 'warning',
  183. draggable: true,
  184. cancelButtonClass: 'default-button',
  185. autofocus: false,
  186. })
  187. .then(() => {
  188. fileDownload({ path: import.meta.env.VITE_RECORD_DOWNLOAD_PREFIX + row.recordingAbsolutePath }).then((res: any) => {
  189. downloadFileByStream(res, row.recordingFileName);
  190. });
  191. })
  192. .catch(() => {});
  193. };
  194. // 重置所有工单列表
  195. const queryParamsRef = ref<RefType>();
  196. const resetQuery = (formEl: FormInstance | undefined) => {
  197. if (!formEl) return;
  198. formEl.resetFields();
  199. queryList();
  200. };
  201. defineExpose({
  202. openDialog,
  203. });
  204. </script>