index.vue 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841
  1. <template>
  2. <el-button link type="primary" @click="onOrderDetail" title="点击查看工单详情">
  3. <slot>工单详情</slot>
  4. </el-button>
  5. <el-dialog
  6. v-model="state.dialogVisible"
  7. class="order-detail-dialog"
  8. draggable
  9. ref="dialogRef"
  10. width="80%"
  11. append-to-body
  12. destroy-on-close
  13. @close="close"
  14. >
  15. <template #header>
  16. <el-tabs v-model="state.activeName" @tab-change="handleClick">
  17. <el-tab-pane :name="item.value" v-for="item in state.tabPaneList" :key="item.value" :label="item.label"></el-tab-pane>
  18. </el-tabs>
  19. </template>
  20. <!-- 工单详情 -->
  21. <el-collapse v-model="state.collapseArr" v-show="state.activeName === '0'" class="collapse-box" v-loading="state.loading">
  22. <el-collapse-item name="1">
  23. <template #title>
  24. <p class="pl20">
  25. <b class="font14">来电人信息</b>
  26. </p>
  27. </template>
  28. <div class="collapse-container">
  29. <el-form label-width="100px" ref="ruleFormRef">
  30. <el-row :gutter="10">
  31. <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6" v-if="state.ruleForm.transferPhone">
  32. <el-form-item label="转接来源"> {{ state.ruleForm.transferPhone }} </el-form-item>
  33. </el-col>
  34. <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6" v-if="state.ruleForm.fromPhone">
  35. <el-form-item label="来电号码">
  36. {{ state.ruleForm.fromPhone }}
  37. <el-button
  38. plain
  39. title="录音文件"
  40. size="small"
  41. type="primary"
  42. class="ml8"
  43. @click="recordFile(state.ruleForm.recordingFileUrl)"
  44. v-if="state.ruleForm.recordingFileUrl"
  45. >录音文件</el-button
  46. >
  47. </el-form-item>
  48. </el-col>
  49. <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
  50. <el-form-item label="来电人姓名">
  51. {{ state.ruleForm.fromName }} <span class="ml5"> {{ state.ruleForm.fromGenderText }}</span>
  52. </el-form-item>
  53. </el-col>
  54. <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
  55. <el-form-item label="来电人性别">
  56. {{ state.ruleForm.fromGenderText }}
  57. </el-form-item>
  58. </el-col>
  59. <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6" v-if="state.ruleForm.contact">
  60. <el-form-item label="联系电话">
  61. <span v-if="showMaskNumber"> {{ state.ruleForm.contactMask }}</span>
  62. <span v-else>{{ state.ruleForm.contact }}</span>
  63. <el-button plain title="外呼" size="small" type="primary" class="ml8" @click="callPhone(state.ruleForm.contact)">外呼</el-button>
  64. <el-button plain title="查看号码" size="small" type="primary" class="ml8" @click="showMaskNumber = !showMaskNumber">{{
  65. showMaskNumber ? '查看号码' : '隐藏号码'
  66. }}</el-button>
  67. </el-form-item>
  68. </el-col>
  69. <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
  70. <el-form-item label="来电人身份"> {{ state.ruleForm.identityTypeText }} </el-form-item>
  71. </el-col>
  72. <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
  73. <el-form-item label="受理短信"> {{ state.ruleForm.smsSendedText }} </el-form-item>
  74. </el-col>
  75. <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6" v-if="state.ruleForm?.incidentTime">
  76. <el-form-item label="事发时间"> {{ formatDate(state.ruleForm?.incidentTime, 'YYYY-mm-dd HH:MM:SS') }} </el-form-item>
  77. </el-col>
  78. <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6" v-if="state.ruleForm?.incidentPurpose">
  79. <el-form-item label="事发目的"> {{ state.ruleForm.incidentPurpose }} </el-form-item>
  80. </el-col>
  81. <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12" v-if="state.ruleForm.enterpriseName">
  82. <el-form-item label="企业名称"> {{ state.ruleForm.enterpriseName }} </el-form-item>
  83. </el-col>
  84. <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12" v-if="state.ruleForm.zhuanBanMingCheng">
  85. <el-form-item label="专班名称"> {{ state.ruleForm.zhuanBanMingCheng }} </el-form-item>
  86. </el-col>
  87. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  88. <el-form-item label="事发地址"> {{ state.ruleForm.address }} </el-form-item>
  89. </el-col>
  90. </el-row>
  91. </el-form>
  92. </div>
  93. </el-collapse-item>
  94. <el-collapse-item name="2">
  95. <template #title>
  96. <p class="pl20">
  97. <b class="font14">工单信息</b>
  98. </p>
  99. </template>
  100. <div class="collapse-container">
  101. <el-form label-width="100px" ref="ruleFormRef">
  102. <el-row :gutter="10">
  103. <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
  104. <el-form-item label="来源方式"> {{ state.ruleForm.sourceChannel }} </el-form-item>
  105. </el-col>
  106. <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
  107. <el-form-item label="受理类型"> {{ state.ruleForm.acceptType }} </el-form-item>
  108. </el-col>
  109. <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
  110. <el-form-item label="工单编码">
  111. {{ state.ruleForm.no }} <span v-if="state.ruleForm.password"> 【{{ state.ruleForm.password }}】</span>
  112. </el-form-item>
  113. </el-col>
  114. <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6" v-if="state.ruleForm.provinceNo">
  115. <el-form-item label="省工单编码"> {{ state.ruleForm.provinceNo }} </el-form-item>
  116. </el-col>
  117. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" v-if="state.ruleForm?.orderExtension?.orderTypeCode">
  118. <el-form-item label="工单类型">
  119. {{ state.ruleForm.orderExtension?.orderType }}
  120. <el-button link type="primary" class="ml10" @click="showExpandInfo"><SvgIcon name="ele-Document" class="mr2" /> 拓展信息</el-button>
  121. </el-form-item>
  122. </el-col>
  123. <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
  124. <el-form-item label="是否重复">
  125. {{
  126. state.ruleForm.duplicateIds && state.ruleForm.duplicateIds.length > 0 ? '是(' + state.ruleForm.duplicateIds.length + '次)' : '否'
  127. }}
  128. <el-button
  129. plain
  130. title="查看重复工单"
  131. size="small"
  132. type="primary"
  133. class="ml8"
  134. @click="showRepeatInfo"
  135. v-if="state.ruleForm.duplicateIds && state.ruleForm.duplicateIds.length > 0"
  136. >查看重复工单</el-button
  137. >
  138. </el-form-item>
  139. </el-col>
  140. <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
  141. <el-form-item label="紧急程度"> {{ state.ruleForm.emergencyLevelText }} </el-form-item>
  142. </el-col>
  143. <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
  144. <el-form-item label="热点分类"> {{ state.ruleForm.hotspotSpliceName }} </el-form-item>
  145. </el-col>
  146. <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
  147. <el-form-item label="受理人">
  148. <span
  149. >{{ state.ruleForm?.acceptorName }}
  150. <span v-if="state.ruleForm?.acceptorStaffNo">[{{ state.ruleForm?.acceptorStaffNo }}]</span></span
  151. >
  152. </el-form-item>
  153. </el-col>
  154. <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6" v-if="state.ruleForm.startTime">
  155. <el-form-item label="受理时间"> {{ formatDate(state.ruleForm?.startTime, 'YYYY-mm-dd HH:MM:SS') }} </el-form-item>
  156. </el-col>
  157. <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6" v-if="state.ruleForm.pushType">
  158. <el-form-item label="推送分类"> {{ state.ruleForm.pushType }} </el-form-item>
  159. </el-col>
  160. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  161. <el-form-item label="工单标题">
  162. {{ state.ruleForm.title }} <el-tag class="ml10" v-if="state.ruleForm?.workflowId">{{ state.ruleForm.statusText }}</el-tag>
  163. </el-form-item>
  164. </el-col>
  165. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  166. <el-form-item label="受理内容">
  167. {{ state.ruleForm.content }}
  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. <annex-list name="附件列表" readonly :businessId="state.ruleForm.id" classify="查看附件" v-model="state.ruleForm.files" />
  173. </el-form-item>
  174. </el-col>
  175. </el-row>
  176. </el-form>
  177. </div>
  178. </el-collapse-item>
  179. <el-collapse-item name="3">
  180. <template #title>
  181. <p class="pl20">
  182. <b class="font14">结果信息</b>
  183. </p>
  184. </template>
  185. <div class="collapse-container">
  186. <el-form label-width="100px" ref="ruleFormRef">
  187. <el-row :gutter="10">
  188. <el-col :xs="24" :sm="24" :md="8" :lg="6" :xl="6">
  189. <el-form-item label="交办部门"> 热线中心 </el-form-item>
  190. </el-col>
  191. <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
  192. <el-form-item label="交办时间"> {{ formatDate(state.ruleForm.centerToOrgTime, 'YYYY-mm-dd HH:MM:SS') }} </el-form-item>
  193. </el-col>
  194. <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
  195. <el-form-item label="办理部门"> {{ state.ruleForm.actualHandleOrgName }}</el-form-item>
  196. </el-col>
  197. <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
  198. <el-form-item label="办理时间"> {{ formatDate(state.ruleForm.actualHandleTime, 'YYYY-mm-dd HH:MM:SS') }} </el-form-item>
  199. </el-col>
  200. <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
  201. <el-form-item label="工单办理期限"> {{ state.ruleForm.timeLimit }}</el-form-item>
  202. </el-col>
  203. <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
  204. <el-form-item label="工单期满时间"> {{ formatDate(state.ruleForm.expiredTime, 'YYYY-mm-dd HH:MM:SS') }} </el-form-item>
  205. </el-col>
  206. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  207. <el-form-item label="办理结果"> {{ state.ruleForm.actualOpinion }} </el-form-item>
  208. </el-col>
  209. </el-row>
  210. </el-form>
  211. </div>
  212. </el-collapse-item>
  213. <el-collapse-item name="4" v-if="state.supplements && state.supplements.length">
  214. <template #title>
  215. <p class="pl20">
  216. <b class="font14">补充信息</b>
  217. </p>
  218. </template>
  219. <div class="collapse-container">
  220. <div v-for="i in state.supplements" :key="i" class="plug-container">
  221. <el-form label-width="100px" ref="ruleFormRef" class="pt10 pb10">
  222. <el-row :gutter="10">
  223. <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
  224. <el-form-item label="补充部门">
  225. {{ i.creator.organization }}
  226. </el-form-item>
  227. </el-col>
  228. <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
  229. <el-form-item label="补充时间"> {{ formatDate(i.creationTime, 'YYYY-mm-dd HH:MM:SS') }} </el-form-item>
  230. </el-col>
  231. <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
  232. <el-form-item label="补充人">
  233. {{ i.creator.name }} <span v-if="i.creator.staffNo">[{{ i.creator.staffNo }} ]</span></el-form-item
  234. >
  235. </el-col>
  236. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  237. <el-form-item label="补充详情">
  238. {{ i.opinion }}
  239. </el-form-item>
  240. </el-col>
  241. </el-row>
  242. </el-form>
  243. </div>
  244. </div>
  245. </el-collapse-item>
  246. <el-collapse-item name="5" v-if="state.workflow.assignOrgs">
  247. <template #title>
  248. <p class="pl20">
  249. <b class="font14">重办信息</b>
  250. </p>
  251. </template>
  252. <div class="collapse-container">
  253. <el-form label-width="100px" ref="ruleFormRef">
  254. <el-row :gutter="10">
  255. <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
  256. <el-form-item label="被重办部门"> {{ state.workflow.assignOrgs }}</el-form-item>
  257. </el-col>
  258. <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
  259. <el-form-item label="重办时间"> {{ formatDate(state.workflow.assignTime, 'YYYY-mm-dd HH:MM:SS') }} }} </el-form-item>
  260. </el-col>
  261. <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
  262. <el-form-item label="重办理由"> {{ state.workflow.timeLimit }} </el-form-item>
  263. </el-col>
  264. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  265. <el-form-item label="重办原因"> {{ state.workflow.opinion }} </el-form-item>
  266. </el-col>
  267. </el-row>
  268. </el-form>
  269. </div>
  270. </el-collapse-item>
  271. </el-collapse>
  272. <!-- 历史工单 -->
  273. <div v-show="state.activeName === '1'">
  274. <history-order :ruleForm="state.ruleForm" :orderId="state.orderId" ref="historyOrderRef" readonly :maxHeight="500" />
  275. </div>
  276. <!-- 回访记录 -->
  277. <div v-show="state.activeName === '2'">
  278. <!-- <el-table :data="state.ruleForm.orderVisits">
  279. <el-table-column prop="visitStateText" label="回访状态" show-overflow-tooltip width="100"></el-table-column>
  280. <el-table-column prop="visitTypeText" label="回访方式" show-overflow-tooltip width="100"></el-table-column>
  281. <el-table-column prop="creationTime" label="回访任务创建时间" show-overflow-tooltip width="170">
  282. <template #default="{ row }">
  283. <span>{{ formatDate(row.creationTime, 'YYYY-mm-dd HH:MM:SS') }}</span>
  284. </template>
  285. </el-table-column>
  286. <el-table-column prop="employeeName" label="回访人" show-overflow-tooltip></el-table-column>
  287. <el-table-column prop="visitTime" label="回访时间" show-overflow-tooltip width="170">
  288. <template #default="{ row }">
  289. <span>{{ formatDate(row.visitTime, 'YYYY-mm-dd HH:MM:SS') }}</span>
  290. </template>
  291. </el-table-column>
  292. <el-table-column label="语音评价" show-overflow-tooltip>
  293. <template #default="{ row }">
  294. <span v-for="item in row.orderVisitDetails">
  295. <span v-if="item.visitTarget === 10">{{ item.voiceEvaluateText }}</span>
  296. </span>
  297. </template>
  298. </el-table-column>
  299. <el-table-column label="话务员满意度" show-overflow-tooltip>
  300. <template #default="{ row }">
  301. <span v-for="item in row.orderVisitDetails">
  302. <span v-if="item.visitTarget === 10">{{ item.seatEvaluateText }}</span>
  303. </span>
  304. </template>
  305. </el-table-column>
  306. <el-table-column prop="statusText" label="操作" width="100" fixed="right" align="center">
  307. <template #default="{ row }">
  308. <el-button @click="onVisitDetail(row)" link type="primary"> 查看 </el-button>
  309. </template>
  310. </el-table-column>
  311. <template #empty>
  312. <Empty />
  313. </template>
  314. </el-table>-->
  315. <el-form
  316. label-width="120px"
  317. label-position="left"
  318. v-if="state.ruleForm.orderVisits && state.ruleForm.orderVisits.length"
  319. class="show-info-form"
  320. >
  321. <el-row :gutter="10">
  322. <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
  323. <el-form-item label="回访状态">
  324. {{ state.ruleForm?.orderVisits[0]?.visitStateText }}
  325. </el-form-item>
  326. </el-col>
  327. <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
  328. <el-form-item label="回访方式">
  329. {{ state.ruleForm?.orderVisits[0]?.visitTypeText }}
  330. </el-form-item>
  331. </el-col>
  332. <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
  333. <el-form-item label="当前回访人">
  334. {{ state.ruleForm?.orderVisits[0]?.employeeName }}
  335. </el-form-item>
  336. </el-col>
  337. <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
  338. <el-form-item label="回访任务创建时间" label-width="130px">
  339. {{ formatDate(state.ruleForm?.orderVisits[0]?.creationTime, 'YYYY-mm-dd HH:MM:SS') }}
  340. </el-form-item>
  341. </el-col>
  342. <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
  343. <el-form-item label="回访时间">
  344. {{ formatDate(state.ruleForm?.orderVisits[0]?.visitTime, 'YYYY-mm-dd HH:MM:SS') }}
  345. </el-form-item>
  346. </el-col>
  347. <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
  348. <el-form-item label="回访标签">
  349. <span v-if="state.ruleForm?.orderVisits[0]?.isPutThrough !== null">{{
  350. state.ruleForm?.orderVisits[0]?.isPutThrough ? '已接通' : '未接通'
  351. }}</span>
  352. </el-form-item>
  353. </el-col>
  354. </el-row>
  355. <el-row v-for="item in state.ruleForm?.orderVisits[0]?.orderVisitDetails" :key="item.id" :gutter="10">
  356. <!-- 务员评价 -->
  357. <template v-if="item.visitTarget === 10">
  358. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  359. <el-divider content-position="left">
  360. <el-text tag="b" size="large"> 话务员回访 </el-text>
  361. </el-divider>
  362. </el-col>
  363. <el-col :xs="12" :sm="12" :md="12" :lg="12" :xl="12">
  364. <el-form-item label="语音评价">
  365. {{ item.voiceEvaluateText }}
  366. </el-form-item>
  367. </el-col>
  368. <el-col :xs="12" :sm="12" :md="12" :lg="12" :xl="12">
  369. <el-form-item label="话务员评价">
  370. {{ item.seatEvaluateText }}
  371. </el-form-item>
  372. </el-col>
  373. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  374. <el-form-item label="话务员回访内容">
  375. {{ item.visitContent }}
  376. </el-form-item>
  377. </el-col>
  378. </template>
  379. <!-- 部门评价 -->
  380. <template v-if="item.visitTarget === 20">
  381. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  382. <el-divider content-position="left">
  383. <el-text tag="b" size="large"> {{ item.visitOrgName }} </el-text>
  384. </el-divider>
  385. </el-col>
  386. <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12">
  387. <el-form-item label="部门办件结果">
  388. {{ item.orgProcessingResults?.value }}
  389. </el-form-item>
  390. </el-col>
  391. <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12">
  392. <el-form-item label="不满意原因">
  393. {{ item.orgNoSatisfiedReason?.map((item) => item.value).join(',') }}
  394. </el-form-item>
  395. </el-col>
  396. <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12">
  397. <el-form-item label="部门办件态度">
  398. {{ item.orgHandledAttitude?.value }}
  399. </el-form-item>
  400. </el-col>
  401. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  402. <el-form-item label="部门回访内容">
  403. {{ item.visitContent }}
  404. </el-form-item>
  405. </el-col>
  406. </template>
  407. </el-row>
  408. </el-form>
  409. <Empty v-else />
  410. </div>
  411. <!-- 市民画像 -->
  412. <div v-show="state.activeName === '3'" class="flex-center-center">
  413. <div style="max-width: 800px">
  414. <citizen-portrait :orderInfo="state.ruleForm" ref="citizenPortraitRef" :editable="false" />
  415. </div>
  416. </div>
  417. <template #footer>
  418. <span class="dialog-footer">
  419. <!-- 单会签中+未到汇总节点 -->
  420. <!-- <el-button type="primary" @click="onCloseCountersignature" :loading="state.loading" v-auth="'business:order:closeCountersignature'"
  421. >结束会签</el-button
  422. >-->
  423. <!-- 有流程信息就可以查询明细 -->
  424. <el-button type="primary" @click="onRecord" :loading="state.loading" v-if="state.ruleForm?.workflowId">流程明细</el-button>
  425. <!-- 有流程信息就可以撤回 -->
  426. <el-button type="primary" @click="onSpecialHandle" :loading="state.loading" v-if="state.ruleForm?.workflowId" v-auth="'business:order:teti'"
  427. >撤 回(特提)</el-button
  428. >
  429. <!-- 办理中和会签中,可以督办 -->
  430. <el-button
  431. type="primary"
  432. @click="onSupervise"
  433. :loading="state.loading"
  434. v-if="[100, 200].includes(state.ruleForm?.status)"
  435. v-auth="'business:order:supervise:apply'"
  436. >督 办</el-button
  437. >
  438. <!-- 办理中和会签中,可以催办 -->
  439. <el-button
  440. type="primary"
  441. @click="onUrge"
  442. :loading="state.loading"
  443. v-if="[100, 200].includes(state.ruleForm?.status)"
  444. v-auth="'business:order:urge:apply'"
  445. >
  446. 催 办</el-button
  447. >
  448. <!-- 办理中和会签中,可以延期申请 -->
  449. <el-button
  450. type="primary"
  451. @click="onSubmit('延期申请', '延期附件')"
  452. :loading="state.loading"
  453. v-if="[100, 200].includes(state.ruleForm?.status)"
  454. v-auth="'business:order:delay'"
  455. >延 期</el-button
  456. >
  457. <!-- 办理中和会签中并且应该自己办理 -->
  458. <el-button
  459. type="primary"
  460. @click="onSubmit('工单办理')"
  461. :loading="state.loading"
  462. v-if="[100, 200].includes(state.ruleForm?.status) && state.workflow.canHandle"
  463. v-auth="'business:order:handle'"
  464. >办 理</el-button
  465. >
  466. <!-- 流程结束之后不展示补充按钮 -->
  467. <!-- <el-button type="primary" @click="onSupply" :loading="state.loading" v-if="[0].includes(state.workflow.status)"
  468. >补 充</el-button
  469. >-->
  470. <!-- <el-button type="primary" @click="onRevoke" :loading="state.loading">撤 销</el-button>-->
  471. <!-- 工单未归档都可以撤回 -->
  472. <!-- <el-button
  473. type="primary"
  474. @click="onSubmit('工单撤回')"
  475. :loading="state.loading"
  476. v-if="[0].includes(state.ruleForm.workflow?.status)"
  477. >撤 回(特提)</el-button
  478. >-->
  479. <!-- 办理中和会签中并且应该自己办理 -->
  480. <el-button
  481. type="primary"
  482. @click="onSubmit('工单退回', '退回附件')"
  483. :loading="state.loading"
  484. v-if="[100, 200].includes(state.ruleForm?.status) && state.workflow.canHandle"
  485. v-auth="'business:order:return'"
  486. >退 回</el-button
  487. >
  488. </span>
  489. </template>
  490. </el-dialog>
  491. <!-- 扩展信息 -->
  492. <order-expand-detail ref="orderExpandDetailRef" />
  493. <!-- 流转记录 -->
  494. <audit-record ref="AuditRecordRef">
  495. <template #header>
  496. <el-form label-width="90px" ref="ruleFormRef">
  497. <el-row :gutter="35">
  498. <el-col :xs="24" :sm="8" :md="8" :lg="8" :xl="8">
  499. <el-form-item label="工单编码"> {{ state.ruleForm.no }} </el-form-item>
  500. </el-col>
  501. <el-col :xs="24" :sm="16" :md="16" :lg="16" :xl="16">
  502. <el-form-item label="工单标题"> {{ state.ruleForm.title }} </el-form-item>
  503. </el-col>
  504. </el-row>
  505. </el-form>
  506. </template>
  507. </audit-record>
  508. <!-- 工单补充 -->
  509. <order-supply ref="orderSupplyRef" @onSupplySuccess="onSupplySuccess" />
  510. <!-- 工单撤销 -->
  511. <order-revoke ref="orderRevokeRef" @onRevokeSuccess="onRevokeSuccess" />
  512. <!-- 工单督办 -->
  513. <order-supervise ref="orderSuperviseRef" @updateList="onSuperviseSuccess" />
  514. <!-- 工单催办 -->
  515. <order-urge ref="orderUrgeRef" @updateList="onSuperviseSuccess" />
  516. <!-- 流程审批 -->
  517. <process-audit ref="processAuditRef" @orderProcessSuccess="orderProcessSuccess" />
  518. <!-- 重复工单 -->
  519. <order-repeat ref="orderRepeatRef" />
  520. <!-- 特提 -->
  521. <special-handle-order ref="specialHandleOrderRef" @updateList="onSpecialHandleSuccess" />
  522. <!-- 播放录音 -->
  523. <play-record ref="playRecordRef" />
  524. </template>
  525. <script setup lang="ts" name="orderDetail">
  526. import { defineAsyncComponent, PropType, reactive, ref } from 'vue';
  527. import { useRouter } from 'vue-router';
  528. import { throttle, transformFile } from '@/utils/tools';
  529. import { orderDetail } from '@/api/business/order';
  530. import { ElButton, ElMessage, ElMessageBox } from 'element-plus';
  531. import { ola } from '@/utils/ola_api';
  532. import { formatDate } from '@/utils/formatTime';
  533. import Empty from '@/components/Empty/index.vue';
  534. // 引入组件
  535. const OrderExpandDetail = defineAsyncComponent(() => import('@/views/business/order/components/Order-expand-detail.vue')); // 扩展信息
  536. const OrderSupply = defineAsyncComponent(() => import('@/views/business/order/components/Order-supply.vue')); // 工单补充
  537. const OrderRevoke = defineAsyncComponent(() => import('@/views/business/order/components/Order-revoke.vue')); // 工单撤销
  538. const OrderSupervise = defineAsyncComponent(() => import('@/views/business/supervise/components/Order-supervise.vue')); // 工单督办
  539. const OrderUrge = defineAsyncComponent(() => import('@/views/query/urge/components/Order-urge.vue')); // 工单催办
  540. const OrderRepeat = defineAsyncComponent(() => import('@/views/business/order/components/Order-repeat.vue')); // 重复工单
  541. const AuditRecord = defineAsyncComponent(() => import('@/components/AuditRecord/index.vue')); // 审核记录
  542. const AnnexList = defineAsyncComponent(() => import('@/components/AnnexList/index.vue')); // 附件列表
  543. const ProcessAudit = defineAsyncComponent(() => import('@/components/ProcessAudit/index.vue')); // 流程审批
  544. const HistoryOrder = defineAsyncComponent(() => import('@/views/todo/seats/accept/History.vue')); // 历史工单
  545. const CitizenPortrait = defineAsyncComponent(() => import('@/views/todo/seats/accept/Citizen-portrait.vue')); // 市民坏画像
  546. const SpecialHandleOrder = defineAsyncComponent(() => import('@/views/business/special/components/Special-apply-order.vue')); // 特提申请
  547. const PlayRecord = defineAsyncComponent(() => import('@/views/tels/callLog/component/Play-record.vue')); // 播放录音
  548. const props = defineProps({
  549. order: {
  550. type: Object as PropType<any>,
  551. default: {},
  552. required: true,
  553. },
  554. });
  555. // 定义子组件向父组件传值/事件
  556. const emit = defineEmits(['updateList']);
  557. // 定义变量内容
  558. const state = reactive<any>({
  559. dialogVisible: false, // 弹窗显示隐藏
  560. ruleForm: {
  561. // 表单数据
  562. },
  563. activeName: '0', // tab切换
  564. tabPaneList: [
  565. // tab列表
  566. {
  567. label: '工单详情',
  568. value: '0',
  569. },
  570. {
  571. label: '历史工单',
  572. value: '1',
  573. },
  574. {
  575. label: '回访详情',
  576. value: '2',
  577. },
  578. {
  579. label: '市民画像',
  580. value: '3',
  581. },
  582. ],
  583. collapseArr: ['1', '2', '3'], //展开列表
  584. loading: false,
  585. supplements: [], // 补充内容
  586. workflow: {}, // 工单流程内容
  587. orderId: '', //工单id
  588. });
  589. const showMaskNumber = ref<boolean>(true); // 是否展示号码
  590. const ruleFormRef = ref<RefType>(); // 表单ref
  591. const router = useRouter(); // 路由
  592. // 查看工单详情
  593. const getOrderDetail = async (id: string) => {
  594. state.loading = true;
  595. try {
  596. const res: any = await orderDetail(id);
  597. state.ruleForm = res.result;
  598. state.ruleForm.files = transformFile(state.ruleForm.files);
  599. state.workflow = state.ruleForm?.workflow ?? {};
  600. state.supplements = res.result?.workflow?.supplements ?? [];
  601. state.loading = false;
  602. state.dialogVisible = true;
  603. } catch (error) {
  604. state.loading = false;
  605. state.dialogVisible = false;
  606. }
  607. };
  608. // 查询历史工单
  609. const historyOrderRef = ref<RefType>(); // 历史工单
  610. const getHistoryList = async (id: string) => {
  611. state.loading = true;
  612. try {
  613. historyOrderRef.value.searchHistory();
  614. state.dialogVisible = true;
  615. state.loading = false;
  616. } catch (error) {
  617. state.loading = false;
  618. state.dialogVisible = false;
  619. }
  620. };
  621. // 查询市民画像
  622. const citizenPortraitRef = ref<RefType>(); // 市民画像
  623. const getPortraitList = async (id: string) => {
  624. state.loading = true;
  625. try {
  626. citizenPortraitRef.value?.getCitizen(state.ruleForm);
  627. state.dialogVisible = true;
  628. state.loading = false;
  629. } catch (error) {
  630. console.log(error, '2');
  631. state.loading = false;
  632. state.dialogVisible = false;
  633. }
  634. };
  635. // 打开弹窗
  636. const openDialog = (val: any) => {
  637. if (!val || !val.id) {
  638. ElMessage.error('工单id不能为空');
  639. return;
  640. }
  641. state.orderId = val.id;
  642. if (val.activeName) {
  643. state.activeName = val.activeName; //传入查询tab
  644. handleClick(val.activeName);
  645. } else {
  646. getOrderDetail(state.orderId);
  647. }
  648. };
  649. const close = () => {
  650. state.activeName = '0';
  651. currentVisitObj.value = null;
  652. };
  653. // 切换tab 查询列表
  654. const handleClick = (val: string) => {
  655. switch (val) {
  656. case '0': //工单详情
  657. getOrderDetail(state.orderId);
  658. break;
  659. case '1': // 历史工单
  660. getHistoryList(state.orderId);
  661. break;
  662. case '2': // 回访记录
  663. break;
  664. case '3': // 市民画像
  665. getPortraitList(state.orderId);
  666. break;
  667. default:
  668. getOrderDetail(state.orderId);
  669. break;
  670. }
  671. };
  672. // 关闭弹窗
  673. const closeDialog = () => {
  674. state.dialogVisible = false;
  675. };
  676. // 查看录音文件
  677. const playRecordRef = ref<RefType>();
  678. const recordFile = (url: string) => {
  679. playRecordRef.value.openDialog(url);
  680. };
  681. // 电话外呼
  682. const callPhone = (number: number | string) => {
  683. ola.dial(number);
  684. };
  685. const orderRepeatRef = ref<RefType>();
  686. // 展示重复工单列表
  687. const showRepeatInfo = () => {
  688. orderRepeatRef.value.openDialog(state.ruleForm);
  689. };
  690. // 展示扩展表单
  691. const orderExpandDetailRef = ref<RefType>(); // 扩展信息
  692. const showExpandInfo = () => {
  693. orderExpandDetailRef.value.openDialog(state.ruleForm.orderExtension);
  694. };
  695. // 流转记录
  696. const AuditRecordRef = ref<RefType>(); // 流转记录
  697. const onRecord = () => {
  698. const params = {
  699. dialogTitle: '流转记录',
  700. ...state.ruleForm,
  701. };
  702. AuditRecordRef.value.openDialog(params);
  703. };
  704. // 提交流程
  705. const processAuditRef = ref<RefType>(); // 处理流程
  706. const onSubmit = throttle((val: string, annexName: string = '办理附件', classify: string = '办理附件') => {
  707. const params = {
  708. id: state.ruleForm.workflowId,
  709. processType: val,
  710. orderDetail: state.ruleForm,
  711. extra: {
  712. dialogTitle: val,
  713. inputPlaceholder: '办理意见',
  714. annexName,
  715. classify,
  716. },
  717. };
  718. processAuditRef.value.openDialog(params);
  719. }, 300);
  720. // 流程提交成功
  721. const orderProcessSuccess = () => {
  722. closeDialog();
  723. emit('updateList');
  724. };
  725. // 补充信息
  726. const orderSupplyRef = ref<RefType>(); // 工单补充
  727. const onSupply = () => {
  728. // 穿入当前流程id
  729. orderSupplyRef.value.openDialog(state.ruleForm);
  730. };
  731. // 补充意见提交成功
  732. const onSupplySuccess = () => {
  733. handleClick(state.activeName);
  734. emit('updateList');
  735. };
  736. // 撤销
  737. const orderRevokeRef = ref<RefType>(); // 工单撤销
  738. const onRevoke = () => {
  739. orderRevokeRef.value.openDialog(state.ruleForm);
  740. };
  741. // 撤销提交成功
  742. const onRevokeSuccess = () => {
  743. handleClick(state.activeName);
  744. emit('updateList');
  745. };
  746. // 督办
  747. const orderSuperviseRef = ref<RefType>(); // 工单督办
  748. const onSupervise = () => {
  749. orderSuperviseRef.value.openDialog(state.ruleForm);
  750. };
  751. // 催办
  752. const orderUrgeRef = ref<RefType>(); // 工单催办
  753. const onUrge = () => {
  754. orderUrgeRef.value.openDialog(state.ruleForm);
  755. };
  756. // 督办提交成功
  757. const onSuperviseSuccess = () => {
  758. handleClick(state.activeName);
  759. emit('updateList');
  760. };
  761. // 查看回访详情
  762. const currentVisitObj = ref<any>();
  763. const onVisitDetail = (row: any) => {
  764. currentVisitObj.value = row;
  765. };
  766. // 特提
  767. const specialHandleOrderRef = ref<RefType>(); // 特提
  768. const onSpecialHandle = () => {
  769. specialHandleOrderRef.value.openDialog(state.ruleForm);
  770. };
  771. // 特提提交成功
  772. const onSpecialHandleSuccess = () => {
  773. handleClick(state.activeName);
  774. emit('updateList');
  775. };
  776. // 结束会签
  777. const onCloseCountersignature = () => {
  778. ElMessageBox.confirm(`当前工单正在会签中,是否确认结束会签?`, '提示', {
  779. confirmButtonText: '结束会签',
  780. cancelButtonText: '取消',
  781. type: 'warning',
  782. draggable: true,
  783. cancelButtonClass: 'default-button',
  784. autofocus: false,
  785. })
  786. .then(() => {
  787. handleClick(state.activeName);
  788. emit('updateList');
  789. })
  790. .catch(() => {});
  791. };
  792. // 暴露变量
  793. defineExpose({
  794. openDialog,
  795. closeDialog,
  796. });
  797. // 工单详情
  798. const onOrderDetail = () => {
  799. openDialog(props.order);
  800. };
  801. </script>
  802. <style lang="scss" scoped>
  803. .order-detail-container {
  804. display: inline-flex;
  805. }
  806. .collapse-box {
  807. :deep(.el-collapse-item__header) {
  808. background-color: var(--hotline-bg-main-color);
  809. height: 40px;
  810. border-radius: var(--el-border-radius-base);
  811. }
  812. :deep(.el-collapse-item__content) {
  813. padding-bottom: 10px !important;
  814. .el-form-item {
  815. margin-bottom: 5px;
  816. .el-form-item__content {
  817. line-height: 24px;
  818. }
  819. }
  820. }
  821. .collapse-container {
  822. padding: 10px;
  823. .plug-container {
  824. border: var(--el-border);
  825. border-radius: var(--el-border-radius-base);
  826. margin-bottom: 15px;
  827. &:last-child {
  828. margin-bottom: 0;
  829. }
  830. }
  831. }
  832. }
  833. :deep(.el-tabs__item) {
  834. font-size: var(--el-font-size-base);
  835. }
  836. </style>