Visit-detail.vue 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  1. <template>
  2. <el-dialog
  3. v-model="state.dialogVisible"
  4. draggable
  5. :title="dialogTitle"
  6. ref="dialogRef"
  7. width="50%"
  8. append-to-body
  9. @mouseup="mouseup"
  10. :style="'transform: ' + state.transform + ';'"
  11. @close="close"
  12. destroy-on-close
  13. >
  14. <el-collapse v-model="state.collapseArr" class="collapse-box" v-loading="state.loading">
  15. <!-- 工单信息 -->
  16. <el-collapse-item name="1">
  17. <template #title>
  18. <p class="pl20">
  19. <b class="font14">工单信息</b>
  20. </p>
  21. </template>
  22. <div class="collapse-container">
  23. <el-form label-width="100px" class="show-info-form">
  24. <el-row :gutter="10">
  25. <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
  26. <el-form-item label="工单编码" class="mb5"> {{ state.orderDetail.no }} </el-form-item>
  27. </el-col>
  28. <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
  29. <el-form-item label="受理时间" class="mb5">
  30. <span>{{ dayjs(state.orderDetail.startTime).format('YYYY-MM-DD HH:mm:ss') }}</span></el-form-item
  31. >
  32. </el-col>
  33. <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
  34. <el-form-item label="受理人" class="mb5">
  35. <span
  36. >{{ state.orderDetail?.acceptorName }}
  37. <span v-if="state.orderDetail?.acceptorStaffNo">[{{ state.orderDetail?.acceptorStaffNo }}]</span></span
  38. >
  39. </el-form-item>
  40. </el-col>
  41. <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
  42. <el-form-item label="来源方式" class="mb5"> {{ state.orderDetail.sourceChannel }} </el-form-item>
  43. </el-col>
  44. <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
  45. <el-form-item label="受理类型" class="mb5"> {{ state.orderDetail.acceptType }} </el-form-item>
  46. </el-col>
  47. <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
  48. <el-form-item label="热点分类" class="mb5"> {{ state.orderDetail.hotspotName }} </el-form-item>
  49. </el-col>
  50. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  51. <el-form-item label="工单标题" class="mb5"> {{ state.orderDetail.title }} </el-form-item>
  52. </el-col>
  53. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  54. <el-form-item label="工单内容" class="mb5"> {{ state.orderDetail.content }} </el-form-item>
  55. </el-col>
  56. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  57. <el-form-item label="办理结果" class="mb5"> {{ state.orderDetail.actualOpinion }} </el-form-item>
  58. </el-col>
  59. </el-row>
  60. </el-form>
  61. </div>
  62. </el-collapse-item>
  63. <el-collapse-item name="2">
  64. <template #title>
  65. <p class="pl20">
  66. <b class="font14">来电人信息</b>
  67. </p>
  68. </template>
  69. <div class="collapse-container">
  70. <el-form label-width="100px" class="show-info-form">
  71. <el-row :gutter="10">
  72. <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
  73. <el-form-item label="来电人姓名"> {{ state.orderDetail.fromName }} </el-form-item>
  74. </el-col>
  75. <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
  76. <el-form-item label="来电号码" class="mb5">
  77. {{ state.orderDetail.fromPhone }}
  78. <el-button
  79. plain
  80. title="人工回访录音"
  81. size="small"
  82. type="primary"
  83. class="ml8"
  84. @click="recordFile(state)"
  85. v-if="state.recordingAbsolutePath"
  86. >人工回访录音</el-button
  87. >
  88. </el-form-item>
  89. </el-col>
  90. <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
  91. <el-form-item label="来电人性别" class="mb5"> {{ state.orderDetail.fromGenderText }} </el-form-item>
  92. </el-col>
  93. <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
  94. <el-form-item label="联系电话">
  95. {{ state.orderDetail.contact }}
  96. <el-button plain title="呼叫" size="small" type="primary" class="ml8" @click="onCall(state.orderDetail.contact)">外呼</el-button>
  97. </el-form-item>
  98. </el-col>
  99. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  100. <el-form-item label="联系地址"> {{ state.orderDetail.address }} </el-form-item>
  101. </el-col>
  102. </el-row>
  103. </el-form>
  104. </div>
  105. </el-collapse-item>
  106. <el-collapse-item name="3">
  107. <template #title>
  108. <p class="pl20">
  109. <b class="font14">回访信息</b>
  110. </p>
  111. </template>
  112. <div class="collapse-container">
  113. <el-form label-width="120px" ref="ruleFormRef" :model="state.ruleForm" label-position="left">
  114. <el-row :gutter="10">
  115. <!-- 详情 -->
  116. <template v-if="disabled">
  117. <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
  118. <el-form-item label="当前回访人">
  119. {{ state.orderVisitModel.employeeName }}
  120. <el-button plain title="智能回访录音" size="small" type="primary" class="ml8" @click="onSmartRecord" v-if="state.smartRecord"
  121. >智能回访录音
  122. </el-button>
  123. <el-button
  124. plain
  125. title="人工回访录音"
  126. size="small"
  127. type="primary"
  128. class="ml8"
  129. @click="recordFile"
  130. v-if="state.recordingAbsolutePath"
  131. >人工回访录音</el-button
  132. >
  133. </el-form-item>
  134. </el-col>
  135. <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12" v-if="visitCount">
  136. <el-form-item label="当前工单已回访次数" label-width="140px"> {{ visitCount }}次 </el-form-item>
  137. </el-col>
  138. <!-- <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  139. <el-form-item label="回访标签">
  140. <span v-if="state.ruleForm.isPutThrough !== null">{{ state.ruleForm.isPutThrough ? '已接通' : '未接通' }}</span>
  141. </el-form-item>
  142. </el-col>-->
  143. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  144. <el-row v-for="item in state.ruleForm.visitDetails" :key="item.id" :gutter="10">
  145. <!-- 务员评价 -->
  146. <template v-if="item.visitTarget === 10">
  147. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  148. <el-form-item label="话务员评价">
  149. <el-radio-group v-model="item.seatEvaluate" disabled>
  150. <el-radio :label="item.key" v-for="item in seatEvaluate" :key="item.key">{{ item.value }}</el-radio>
  151. </el-radio-group>
  152. </el-form-item>
  153. </el-col>
  154. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  155. <el-form-item label="话务员回访内容">
  156. {{ item.visitContent }}
  157. </el-form-item>
  158. </el-col>
  159. </template>
  160. <!-- 部门评价 -->
  161. <template v-if="item.visitTarget === 20">
  162. <el-divider content-position="left">
  163. <el-text tag="b" size="large"> {{ item.visitOrgName }} </el-text>
  164. </el-divider>
  165. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  166. <el-form-item label="部门是否联系">
  167. {{ item.isContact === null ? '' : item.isContact === true ? '是' : '否' }}
  168. </el-form-item>
  169. </el-col>
  170. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  171. <el-form-item label="处理结果">
  172. {{ item.volved === null ? '' : item.volved === true ? '已得到解决' : '未得到解决' }}
  173. </el-form-item>
  174. </el-col>
  175. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" v-if="item.volveConent">
  176. <el-form-item label="备注">
  177. {{ item.volveConent }}
  178. </el-form-item>
  179. </el-col>
  180. <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12">
  181. <el-form-item label="部门办件结果">
  182. {{ item.orgProcessingResults?.dicDataName }}
  183. </el-form-item>
  184. </el-col>
  185. <!-- 不满意才会选择不满意原因 -->
  186. <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" v-if="item.orgNoSatisfiedReason && item.orgNoSatisfiedReason.length">
  187. <el-form-item label="不满意原因">
  188. {{ item.orgNoSatisfiedReason.map((item) => item.dicDataName).join(',') }}
  189. </el-form-item>
  190. </el-col>
  191. <!-- <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12">
  192. <el-form-item label="部门办件态度">
  193. {{ item.orgHandledAttitude?.dicDataName }}
  194. </el-form-item>
  195. </el-col>-->
  196. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  197. <el-form-item label="部门回访内容">
  198. {{ item.visitContent }}
  199. </el-form-item>
  200. </el-col>
  201. </template>
  202. </el-row>
  203. </el-col>
  204. </template>
  205. <!-- 编辑 -->
  206. <template v-else>
  207. <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
  208. <el-form-item label="当前回访人">
  209. {{ userInfos.name }}
  210. <el-button plain title="智能回访录音" size="small" type="primary" class="ml8" @click="onSmartRecord" v-if="state.smartRecord"
  211. >智能回访录音
  212. </el-button>
  213. <el-button
  214. plain
  215. title="人工回访录音"
  216. size="small"
  217. type="primary"
  218. class="ml8"
  219. @click="recordFile"
  220. v-if="state.recordingAbsolutePath"
  221. >人工回访录音</el-button
  222. >
  223. </el-form-item>
  224. </el-col>
  225. <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
  226. <el-form-item label="当前工单已回访次数" label-width="140px"> {{ visitCount }}次 </el-form-item>
  227. </el-col>
  228. <!-- <el-col :span="24">
  229. <el-form-item label="回访标签" prop="isPutThrough" :rules="[{ required: false, message: '请选择回访标签', trigger: 'change' }]">
  230. <el-checkbox v-model="state.ruleForm.isPutThrough">未接通</el-checkbox>
  231. </el-form-item>
  232. </el-col>-->
  233. <el-col :span="24">
  234. <el-row v-for="(item, index) in state.ruleForm.visitDetails" :key="item.id" :gutter="10">
  235. <!-- 务员评价 -->
  236. <template v-if="item.visitTarget === 10">
  237. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  238. <el-form-item
  239. label="话务员评价"
  240. :prop="`visitDetails.${index}.seatEvaluate`"
  241. :rules="[{ required: true, message: '请选择话务员评价', trigger: 'change' }]"
  242. >
  243. <el-radio-group v-model="item.seatEvaluate">
  244. <el-radio :label="item.key" v-for="item in seatEvaluate" :key="item.key">{{ item.value }}</el-radio>
  245. </el-radio-group>
  246. </el-form-item>
  247. </el-col>
  248. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  249. <el-form-item
  250. label="话务员回访内容"
  251. :prop="`visitDetails.${index}.visitContent`"
  252. :rules="[{ required: true, message: '请填写话务员回访内容', trigger: 'blur' }]"
  253. >
  254. <common-advice
  255. @chooseAdvice="chooseAdvice($event, index)"
  256. v-model="item.visitContent"
  257. placeholder="请填写话务员回访内容"
  258. :loading="state.loading"
  259. :commonEnum="commonEnum.Seat"
  260. :minRows="5"
  261. :maxRows="10"
  262. drawerWidth="40%"
  263. />
  264. </el-form-item>
  265. </el-col>
  266. </template>
  267. <!-- 部门评价 -->
  268. <template v-if="item.visitTarget === 20">
  269. <el-divider content-position="left">
  270. <el-text tag="b" size="large"> {{ item.visitOrgName }} </el-text>
  271. </el-divider>
  272. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  273. <el-form-item
  274. label="部门是否联系"
  275. :prop="`visitDetails.${index}.isContact`"
  276. :rules="[{ required: true, message: '请选择部门是否联系', trigger: 'change' }]"
  277. >
  278. <el-radio-group v-model="item.isContact">
  279. <el-radio :label="true">是</el-radio>
  280. <el-radio :label="false">否</el-radio>
  281. </el-radio-group>
  282. </el-form-item>
  283. </el-col>
  284. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  285. <el-form-item
  286. label="处理结果"
  287. :prop="`visitDetails.${index}.volved`"
  288. :rules="[{ required: true, message: '请选择处理结果', trigger: 'change' }]"
  289. >
  290. <el-radio-group v-model="item.volved">
  291. <el-radio :label="true">已得到解决</el-radio>
  292. <el-radio :label="false">未得到解决</el-radio>
  293. </el-radio-group>
  294. </el-form-item>
  295. </el-col>
  296. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" v-if="item.volved === false">
  297. <el-form-item
  298. label=""
  299. :prop="`visitDetails.${index}.volveConent`"
  300. :rules="[{ required: false, message: '请填写备注', trigger: 'blur' }]"
  301. >
  302. <common-advice
  303. @chooseAdvice="chooseAdvice($event, index)"
  304. v-model="item.volveConent"
  305. placeholder="请填写备注"
  306. :loading="state.loading"
  307. :commonEnum="commonEnum.Seat"
  308. :minRows="5"
  309. :maxRows="10"
  310. drawerWidth="40%"
  311. />
  312. </el-form-item>
  313. </el-col>
  314. <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12">
  315. <el-form-item
  316. label="部门办件结果"
  317. :prop="`visitDetails.${index}.orgProcessingResults`"
  318. :rules="[{ required: true, message: '请选择部门办件结果', trigger: 'change' }]"
  319. >
  320. <el-select
  321. v-model="item.orgProcessingResults"
  322. placeholder="请选择部门办件结果"
  323. class="w100"
  324. value-key="dicDataValue"
  325. @change="
  326. (val) => {
  327. item.orgProcessingResults.value = val.dicDataName;
  328. item.orgProcessingResults.key = val.dicDataValue;
  329. }
  330. "
  331. >
  332. <el-option v-for="items in visitManner" :key="items.dicDataValue" :label="items.dicDataName" :value="items" />
  333. </el-select>
  334. </el-form-item>
  335. </el-col>
  336. <!-- 不满意才会选择不满意原因 -->
  337. <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" v-if="['1', '2'].includes(item.orgProcessingResults?.key)">
  338. <el-form-item
  339. label="不满意原因"
  340. :prop="`visitDetails.${index}.orgNoSatisfiedReason`"
  341. :rules="[{ required: true, message: '请选择不满意原因', trigger: 'change' }]"
  342. >
  343. <el-select
  344. v-model="item.orgNoSatisfiedReason"
  345. placeholder="请选择不满意原因"
  346. class="w100"
  347. value-key="dicDataValue"
  348. multiple
  349. collapse-tags
  350. collapse-tags-tooltip
  351. @change="selectReason($event, index)"
  352. >
  353. <el-option v-for="items in dissatisfiedReason" :key="items.dicDataValue" :label="items.dicDataName" :value="items" />
  354. </el-select>
  355. </el-form-item>
  356. </el-col>
  357. <!-- <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12">
  358. <el-form-item
  359. label="部门办件态度"
  360. :prop="`visitDetails.${index}.orgHandledAttitude`"
  361. :rules="[{ required: true, message: '请选择部门办件态度', trigger: 'change' }]"
  362. >
  363. <el-select
  364. v-model="item.orgHandledAttitude"
  365. placeholder="请选择部门办件态度"
  366. class="w100"
  367. value-key="dicDataValue"
  368. @change="
  369. (val) => {
  370. item.orgHandledAttitude.value = val.dicDataName;
  371. item.orgHandledAttitude.key = val.dicDataValue;
  372. }
  373. "
  374. >
  375. <el-option v-for="items in visitSatisfaction" :key="items.dicDataValue" :label="items.dicDataName" :value="items" />
  376. </el-select>
  377. </el-form-item>
  378. </el-col>-->
  379. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  380. <el-form-item
  381. label="部门回访内容"
  382. :prop="`visitDetails.${index}.visitContent`"
  383. :rules="[{ required: true, message: '请填写部门回访内容', trigger: 'blur' }]"
  384. >
  385. <common-advice
  386. @chooseAdvice="chooseAdvice($event, index)"
  387. v-model="item.visitContent"
  388. d
  389. placeholder="请填写部门回访内容"
  390. :loading="state.loading"
  391. :commonEnum="commonEnum.Seat"
  392. :minRows="5"
  393. :maxRows="10"
  394. drawerWidth="40%"
  395. />
  396. </el-form-item>
  397. </el-col>
  398. </template>
  399. </el-row>
  400. </el-col>
  401. <!-- <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  402. <el-form-item label="扭转满意度" prop="isPutThrough" :rules="[{ required: false, message: '请选择扭转满意度', trigger: 'change' }]">
  403. <el-checkbox v-model="state.ruleForm.isPutThrough">扭转部门满意度</el-checkbox>
  404. <el-checkbox v-model="state.ruleForm.isPutThrough">扭转坐席满意度</el-checkbox>
  405. </el-form-item>
  406. </el-col>-->
  407. </template>
  408. </el-row>
  409. </el-form>
  410. </div>
  411. </el-collapse-item>
  412. </el-collapse>
  413. <template #footer v-if="disabled">
  414. <span class="dialog-footer">
  415. <el-button @click="closeDialog" class="default-button">关 闭</el-button>
  416. </span>
  417. </template>
  418. <template #footer v-else>
  419. <span class="dialog-footer">
  420. <el-button @click="closeDialog" class="default-button">取 消</el-button>
  421. <el-button type="primary" @click="onSubmit(ruleFormRef)" :loading="state.loading">保存</el-button>
  422. </span>
  423. </template>
  424. </el-dialog>
  425. <!-- 播放录音 -->
  426. <play-record ref="playRecordRef" />
  427. </template>
  428. <script setup lang="ts" name="orderFollowUpDetail">
  429. import { computed, defineAsyncComponent, onBeforeUnmount, onMounted, reactive, ref, watch } from 'vue';
  430. import { ElMessage, FormInstance } from 'element-plus';
  431. import { commonEnum } from '@/utils/constants';
  432. import { storeToRefs } from 'pinia';
  433. import { useUserInfo } from '@/stores/userInfo';
  434. import { ola } from '@/utils/ola_api';
  435. import dayjs from 'dayjs';
  436. import { visitDetailBaseData, visitOrder } from '@/api/business/visit';
  437. import mittBus from '@/utils/mitt';
  438. // 引入组件
  439. const CommonAdvice = defineAsyncComponent(() => import('@/components/CommonAdvice/index.vue')); // 常用意见
  440. const PlayRecord = defineAsyncComponent(() => import('@/views/tels/callLog/component/Play-record.vue')); // 播放录音
  441. // 定义子组件向父组件传值/事件
  442. const emit = defineEmits(['updateList']);
  443. // 定义变量内容
  444. const state = reactive<any>({
  445. collapseArr: ['1', '2', '3'], // 折叠面板
  446. dialogVisible: false, // 是否显示弹窗
  447. loading: false, // 是否显示加载
  448. transform: 'translate(0px, 0px)', // 附件弹窗位置
  449. smartRecord: null,
  450. ruleForm: {
  451. isPutThrough: false, //未接通
  452. visitDetails: {},
  453. },
  454. orderDetail: {}, // 工单详情
  455. orderVisitModel: {}, // 回访详情
  456. recordingAbsolutePath: '', // 录音文件
  457. });
  458. const ruleFormRef = ref<RefType>();
  459. const storesUserInfo = useUserInfo();
  460. const { userInfos } = storeToRefs(storesUserInfo); // 用户信息
  461. const visitCount = ref<number>(0); // 回访次数
  462. const seatEvaluate = ref<EmptyArrayType>(); // 话务员评价
  463. const viceEvaluate = ref<EmptyArrayType>(); // 语音评价
  464. const dissatisfiedReason = ref<EmptyArrayType>(); // 不满意原因
  465. const visitManner = ref<EmptyArrayType>(); // 部门办件结果
  466. const visitSatisfaction = ref<EmptyArrayType>(); // 部门办件态度
  467. const visitId = ref<string>(''); // 回访id
  468. const dialogTitle = ref<string>('回访'); // 弹窗标题
  469. const getBaseData = async (id: string) => {
  470. state.loading = true;
  471. try {
  472. const res = await visitDetailBaseData(id);
  473. visitCount.value = res.result?.visitCount ?? 0;
  474. seatEvaluate.value = res.result?.seatEvaluate ?? [];
  475. viceEvaluate.value = res.result?.viceEvaluate ?? [];
  476. dissatisfiedReason.value = res.result?.dissatisfiedReason ?? [];
  477. visitManner.value = res.result?.visitManner ?? [];
  478. visitSatisfaction.value = res.result?.visitSatisfaction ?? [];
  479. visitId.value = res.result?.orderVisitModel?.id ?? '';
  480. state.orderDetail = res.result?.orderVisitModel?.order ?? {};
  481. state.orderVisitModel = res.result?.orderVisitModel ?? {};
  482. state.recordingAbsolutePath = res.result?.recordingAbsolutePath ?? '';
  483. state.smartRecord = res.result?.orderVisitModel.recordUrl ?? '';
  484. if (res.result?.orderVisitModel?.isPutThrough !== null) {
  485. state.ruleForm.isPutThrough = !res.result?.orderVisitModel?.isPutThrough ?? false;
  486. } else {
  487. state.ruleForm.isPutThrough = false;
  488. }
  489. state.ruleForm.visitDetails = res.result?.orderVisitModel?.orderVisitDetails ?? {};
  490. for (let i of state.ruleForm.visitDetails) {
  491. if (i.visitTarget === 20) {
  492. if (i.orgProcessingResults) {
  493. i.orgProcessingResults = {
  494. ...i.orgProcessingResults,
  495. dicDataName: i.orgProcessingResults.value,
  496. dicDataValue: i.orgProcessingResults.key,
  497. };
  498. }
  499. if (i.orgNoSatisfiedReason) {
  500. i.orgNoSatisfiedReason = i.orgNoSatisfiedReason.map((item: any) => {
  501. return {
  502. ...item,
  503. dicDataName: item.value,
  504. dicDataValue: item.key,
  505. };
  506. });
  507. } else {
  508. i.orgNoSatisfiedReason = [];
  509. }
  510. if (i.orgHandledAttitude) {
  511. i.orgHandledAttitude = {
  512. ...i.orgHandledAttitude,
  513. dicDataName: i.orgHandledAttitude.value,
  514. dicDataValue: i.orgHandledAttitude.key,
  515. };
  516. }
  517. }
  518. }
  519. state.loading = false;
  520. } catch (error) {
  521. console.log(error);
  522. state.loading = false;
  523. }
  524. };
  525. const notGetThrough = ref(false);
  526. watch(
  527. () => state.ruleForm.isPutThrough,
  528. (val) => {
  529. notGetThrough.value = !val;
  530. },
  531. { immediate: true, deep: true }
  532. );
  533. // 打开弹窗
  534. const openDialog = (row: any, type: string = '回访') => {
  535. getBaseData(row.id);
  536. dialogTitle.value = type;
  537. state.dialogVisible = true;
  538. };
  539. const disabled = computed(() => {
  540. return dialogTitle.value === '回访详情';
  541. });
  542. // 设置抽屉
  543. const dialogRef = ref<RefType>(); // 弹窗ref
  544. const mouseup = () => {
  545. state.transform = dialogRef.value.dialogContentRef.$el.style.transform;
  546. };
  547. // 关闭弹窗
  548. const closeDialog = () => {
  549. state.dialogVisible = false;
  550. };
  551. // 查看人工回访录音文件
  552. const playRecordRef = ref<RefType>();
  553. const recordFile = (obj: any) => {
  554. const fileName = `工单编号-${obj.orderDetail?.no} 人工回访录音文件`;
  555. playRecordRef.value.openDialog(import.meta.env.VITE_RECORD_PREFIX + obj.recordingAbsolutePath, fileName, obj.recordingAbsolutePath);
  556. };
  557. // 查看智能回访录音
  558. const onSmartRecord = () => {
  559. const fileName = `工单编号-${state.orderDetail?.no} 智能回访录音文件`;
  560. playRecordRef.value.openDialog(state.smartRecord, fileName);
  561. };
  562. // 呼叫
  563. const onCall = (phoneNumber: string) => {
  564. ola.dial(phoneNumber);
  565. };
  566. // 选择不满意原因
  567. const selectReason = (val: any, index: number | string) => {
  568. state.ruleForm.visitDetails[index].orgNoSatisfiedReason = val.map((item: any) => {
  569. return {
  570. ...item,
  571. value: item.dicDataName,
  572. key: item.dicDataValue,
  573. };
  574. });
  575. };
  576. const close = () => {
  577. ruleFormRef.value?.clearValidate();
  578. ruleFormRef.value?.resetFields();
  579. };
  580. // 提交
  581. const onSubmit = (formEl: FormInstance | undefined) => {
  582. if (!formEl) return;
  583. formEl.validate((valid: boolean) => {
  584. if (!valid) return;
  585. state.loading = true;
  586. let request = {
  587. ...state.ruleForm,
  588. isPutThrough: !state.ruleForm.isPutThrough,
  589. ...state.visitDetails,
  590. id: visitId.value,
  591. };
  592. if (callId.value) {
  593. request.callId = callId.value;
  594. }
  595. visitOrder(request)
  596. .then(() => {
  597. ElMessage.success('操作成功');
  598. state.loading = false;
  599. closeDialog();
  600. emit('updateList');
  601. })
  602. .catch(() => {
  603. state.loading = false;
  604. });
  605. });
  606. };
  607. // 选中常用意见
  608. const chooseAdvice = (item: any, index: number | string) => {
  609. if (state.ruleForm.visitDetails[index].visitContent === null) {
  610. state.ruleForm.visitDetails[index].visitContent = '';
  611. }
  612. state.ruleForm.visitDetails[index].visitContent += item.content;
  613. };
  614. const callId = ref<string>('');
  615. onMounted(() => {
  616. mittBus.on('outboundConnect', (data) => {
  617. console.log(data, '外呼已经接通辣');
  618. if (data.dnis === state.orderDetail.contact) callId.value = data.other_accept;
  619. });
  620. });
  621. onBeforeUnmount(() => {
  622. mittBus.off('outboundConnect');
  623. });
  624. defineExpose({
  625. openDialog,
  626. closeDialog,
  627. });
  628. </script>
  629. <style lang="scss" scoped>
  630. .collapse-box {
  631. :deep(.el-collapse-item__header) {
  632. background-color: var(--hotline-bg-main-color);
  633. height: 40px;
  634. border-radius: var(--el-border-radius-base);
  635. }
  636. :deep(.el-collapse-item__content) {
  637. padding-bottom: 10px !important;
  638. }
  639. .collapse-container {
  640. padding: 10px;
  641. .plug-container {
  642. border: var(--el-border);
  643. border-radius: var(--el-border-radius-base);
  644. margin-bottom: 15px;
  645. &:last-child {
  646. margin-bottom: 0;
  647. }
  648. .plug-container-title {
  649. padding: 10px 15px;
  650. font-weight: bold;
  651. border-bottom: var(--el-border);
  652. font-size: var(--el-font-size-medium);
  653. }
  654. }
  655. }
  656. }
  657. </style>
  658. <style lang="scss">
  659. .demo-tabs-form {
  660. .title {
  661. font-size: var(--el-font-size-medium);
  662. padding: 10px 15px 20px 15px;
  663. }
  664. }
  665. </style>