management.vue 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432
  1. <template>
  2. <scroll-view class="container" :scroll-y="scrollY" @scrolltolower="scrolltolower">
  3. <view class="top_bg"></view>
  4. <!-- 状态统计区域 管理者端 -->
  5. <view class="top_types2" v-if="btns.includes('工单管理分段器')">
  6. <view class="top">
  7. <uni-segmented-control :current="current" :values="items" @clickItem="onClickItem" styleType="text" activeColor="#6FB6B8"></uni-segmented-control>
  8. </view>
  9. <view class="bottom">
  10. <view class="bottom_box" :class="{ active: state === 1 }" @click="handleFilter(1)">
  11. <view class="box_num">{{ receivingCount }}</view>
  12. <view class="box_info">待接单</view>
  13. </view>
  14. <view class="bottom_box" :class="{ active: state === 2 }" @click="handleFilter(2)">
  15. <view class="box_num">{{ maintenanceCount }}</view>
  16. <view class="box_info">维修中</view>
  17. </view>
  18. <view class="bottom_box" :class="{ active: state === 3 }" @click="handleFilter(3)">
  19. <view class="box_num">{{ timeoutCount }}</view>
  20. <view class="box_info">已超时</view>
  21. </view>
  22. <view class="bottom_box" :class="{ active: state === 4 }" @click="handleFilter(4)">
  23. <view class="box_num">{{ examineCount }}</view>
  24. <view class="box_info">待审核</view>
  25. </view>
  26. <view class="bottom_box" :class="{ active: state === 5 }" v-if="current === 0" @click="handleFilter(5)">
  27. <view class="box_num">{{ finishedCount }}</view>
  28. <view class="box_info">已完成</view>
  29. </view>
  30. <view class="bottom_box" :class="{ active: state === 7 }" v-if="current === 0" @click="handleFilter(7)">
  31. <view class="box_num">{{ closedCount }}</view>
  32. <view class="box_info">已关单</view>
  33. </view>
  34. </view>
  35. </view>
  36. <!-- 状态统计区域 维修师傅 后勤端 -->
  37. <view class="top_types" v-else>
  38. <view class="types_box" :class="{ active: state === 1 }" @click="handleFilter(1)">
  39. <view class="box_num">{{ receivingCount }}</view>
  40. <view class="box_info">待接单</view>
  41. </view>
  42. <view class="types_box" :class="{ active: state === 2 }" @click="handleFilter(2)">
  43. <view class="box_num">{{ maintenanceCount }}</view>
  44. <view class="box_info">维修中</view>
  45. </view>
  46. <view class="types_box" :class="{ active: state === 3 }" @click="handleFilter(3)">
  47. <view class="box_num">{{ timeoutCount }}</view>
  48. <view class="box_info">已超时</view>
  49. </view>
  50. <view class="types_box" :class="{ active: state === 4 }" @click="handleFilter(4)">
  51. <view class="box_num">{{ examineCount }}</view>
  52. <view class="box_info">待审核</view>
  53. </view>
  54. <view class="types_box" v-if="btns.includes('分段器按钮')" :class="{ active: state === 6 }" @click="handleFilter(6)">
  55. <view class="box_num">{{ logisticsCount }}</view>
  56. <view class="box_info">待处理</view>
  57. </view>
  58. <view class="types_box" v-if="btns.includes('分段器按钮')" :class="{ active: state === 5 }" @click="handleFilter(5)">
  59. <view class="box_num">{{ finishedCount }}</view>
  60. <view class="box_info">已完成</view>
  61. </view>
  62. <view class="types_box" v-if="btns.includes('分段器按钮')" :class="{ active: state === 7 }" @click="handleFilter(7)">
  63. <view class="box_num">{{ closedCount }}</view>
  64. <view class="box_info">已关单</view>
  65. </view>
  66. </view>
  67. <!-- 订单列表区域 -->
  68. <view class="body">
  69. <!-- 每一个订单区域 -->
  70. <view class="body_item" v-for="item in dataList" :key="item.id" @click="handleGoDetail(item)">
  71. <!-- 工单编号 -->
  72. <view class="item_title">
  73. <img src="../../static/images/repairsImg/order.png" />
  74. <view class="title_info">工单编号:{{ item.recordNo }}</view>
  75. </view>
  76. <!-- 报修时间 -->
  77. <view class="item_time">
  78. <view class="time_msg">
  79. 报修时间:
  80. <text>{{ item.reportTime }}</text>
  81. </view>
  82. <view class="time_type" v-if="item.state === '待接单'">待接单</view>
  83. <view class="time_type" v-if="item.state === '待处理'">待处理</view>
  84. <view class="time_type color_type" v-if="item.state === '维修中'">维修中</view>
  85. <view class="time_type color_type" v-if="item.state === '协作审核'">协作审核</view>
  86. <view class="time_type color_type" v-if="item.state === '转单审核'">转单审核</view>
  87. <view class="time_type color_type2" v-if="item.state === '待审核'">待审核</view>
  88. <view class="time_type color_type3" v-if="item.state === '已完成'">已完成</view>
  89. <view class="time_type" v-if="item.state === '待确认'">待确认</view>
  90. <view class="time_type color_type4" v-if="item.state === '已关单'">已关单</view>
  91. </view>
  92. <!-- 报修姓名 -->
  93. <view class="item_box">
  94. <view class="box_key">报修姓名:</view>
  95. <view class="box_value">{{ item.userName }}</view>
  96. <view class="box_type" v-if="item.timeoutStr">超时未接</view>
  97. <view class="box_type" v-if="item.maintenanceTimeout">维修超时</view>
  98. </view>
  99. <!-- 部门 -->
  100. <view class="item_box" v-if="item.userClass">
  101. <view class="box_key">部门:</view>
  102. <view class="box_value">{{ item.userClass }}</view>
  103. </view>
  104. <!-- 报修电话 -->
  105. <view class="item_box">
  106. <view class="box_key">报修电话:</view>
  107. <view class="box_value phone" @click.stop="handleCallPhone(item.userPhone)">
  108. {{ item.userPhone }}
  109. <img src="../../static/images/repairsImg/phone.png" />
  110. </view>
  111. </view>
  112. <!-- 报修区域 -->
  113. <view class="item_box">
  114. <view class="box_key">报修区域:</view>
  115. <view class="box_value">{{ item.areaName }}</view>
  116. </view>
  117. <!-- 详细地址 -->
  118. <view class="item_box">
  119. <view class="box_key">详细地址:</view>
  120. <view class="box_value">{{ item.address }}</view>
  121. </view>
  122. <!-- 报修物品 -->
  123. <view class="item_box">
  124. <view class="box_key">报修物品:</view>
  125. <view class="box_value">{{ item.articleName }}</view>
  126. </view>
  127. <!-- 故障描述 -->
  128. <view class="item_box" v-if="item.description">
  129. <view class="box_key">故障描述:</view>
  130. <view class="box_value">{{ item.description }}</view>
  131. </view>
  132. <!-- 报修录音 -->
  133. <view class="item_box" v-if="item.voice">
  134. <view class="box_key">报修录音:</view>
  135. <view class="box_value">
  136. <view class="recording" @click.stop="handlePlayRecording(item)">
  137. <img class="voiceImg" :src="item.status ? '../../static/images/repairsImg/play_active.png' : '../../static/images/repairsImg/play.png'" />
  138. {{ item.voiceLength }}″
  139. </view>
  140. </view>
  141. </view>
  142. <!-- 上传图片 -->
  143. <view class="item_img">
  144. <view class="img_key">上传图片:</view>
  145. <img class="img_value" mode="aspectFill" :src="item.images[0]" @click.stop="handleLookImgs(item.images)" />
  146. </view>
  147. <!-- 维修师傅 -->
  148. <view class="item_time" v-if="item.maintenancerName">
  149. <view class="time_msg">
  150. 维修师傅:
  151. <text>{{ item.maintenancerName }}</text>
  152. </view>
  153. </view>
  154. <!-- 师傅电话 -->
  155. <view class="item_box" v-if="item.maintenancerPhone">
  156. <view class="box_key">师傅电话:</view>
  157. <view class="box_value phone" @click.stop="handleCallPhone(item.maintenancerPhone)">
  158. {{ item.maintenancerPhone }}
  159. <img src="../../static/images/repairsImg/phone.png" />
  160. </view>
  161. </view>
  162. <!-- 维修费用 -->
  163. <view class="item_box" v-if="item.price">
  164. <view class="box_key">维修费用:</view>
  165. <view class="box_value2 phone" @click.stop="checkFeeDetail(item)">
  166. {{ item.price }}元
  167. <img src="../../static/images/repairsImg/eye.png" />
  168. </view>
  169. </view>
  170. <!-- 按钮区域 -->
  171. <view class="item_btn">
  172. <!-- 关闭按钮 -->
  173. <img v-if="item.state === '待接单'" src="../../static/images/repairsImg/close.png" @click.stop="handleClose(item)" />
  174. <!-- 协作按钮 -->
  175. <img class="img" src="../../static/images/repairsImg/help.png" v-if="item.state === '待接单' && btns.includes('协作')" @click.stop="handleHelp(item)" />
  176. <!-- 延时按钮 -->
  177. <view class="btn_box type" v-if="(item.state === '待接单' || item.state === '维修中') && btns.includes('延时')" @click.stop="handleDelay(item)">延时</view>
  178. <!-- 接单按钮 -->
  179. <view
  180. class="btn_box type"
  181. v-if="item.state === '待接单' && btns.includes('接单') && (!btns.includes('首页分段器') || current === 1)"
  182. @click.stop="handleOrderReceiving(item)"
  183. >
  184. 接单
  185. </view>
  186. <!-- 转单按钮 -->
  187. <view class="btn_box type2" v-if="item.state === '待接单' && btns.includes('转单')" @click.stop="handleTransferOrder(item)">转单</view>
  188. <!-- 派单按钮 -->
  189. <!-- <view class="btn_box type2" v-if="item.state === '待接单' && btns.includes('派单')" @click.stop="handleSendOrder(item)">派单</view> -->
  190. <!-- 报价按钮 -->
  191. <view class="btn_box type" v-if="!item.price && item.state === '维修中' && btns.includes('报价')" @click.stop="handleOffer(item)">报价</view>
  192. <!-- 维修完成按钮 -->
  193. <view class="btn_box type2" v-if="item.state === '维修中' && btns.includes('维修完成')" @click.stop="handleFinish(item)">维修完成</view>
  194. <!-- 审核按钮 -->
  195. <view class="btn_box type" v-if="(item.state === '协作审核' || item.state === '转单审核') && btns.includes('审核')" @click.stop="handleAudit(item)">审核</view>
  196. <!-- 改价按钮 -->
  197. <view class="btn_box type" v-if="item.state === '待处理'" @click.stop="handleChangeOffer(item)">改价</view>
  198. <!-- 留言按钮 -->
  199. <view class="btn_box type2" v-if="item.state === '待处理'" @click.stop="handleLeaveWords(item)">留言</view>
  200. </view>
  201. </view>
  202. <!-- 关闭按钮弹窗 -->
  203. <uni-popup ref="popup_close" :is-mask-click="false">
  204. <view class="popup_close">
  205. <view class="close_reason">
  206. 关单原因:
  207. <picker @change="bindPickerChange" :value="activeIndex" :range="closeList" range-key="name">
  208. <view class="picker_input">
  209. {{ closeList[activeIndex].name }}
  210. <img src="../../static/images/repairsImg/bottom.png" />
  211. </view>
  212. </picker>
  213. </view>
  214. <view class="close_note">备注(二选一):</view>
  215. <view class="close_voice">
  216. <view class="voice_box" v-if="!recordingPath" @click="handleRecording">
  217. <img src="../../static/images/repairsImg/voice.png" />
  218. </view>
  219. <view v-if="!recordingPath" @click="handleRecording">点击录音</view>
  220. <view class="item_recording" v-if="recordingPath" @click="handlePlayRecordingPop">
  221. <img :src="recordingImg" />
  222. {{ recordingTime }}″
  223. </view>
  224. <view class="recording_icon" v-if="recordingPath" @click="handleDeleteRecording">×</view>
  225. </view>
  226. <textarea class="close_input" placeholder-style="color:#CCCCCC" placeholder="请输入备注" v-model="closeNote"></textarea>
  227. <view class="close_btn">
  228. <view class="btn_box cancel" @click="handleCloseCancel">取消</view>
  229. <view class="btn_box confirm" @click="handleCloseConfirm">确定</view>
  230. </view>
  231. </view>
  232. </uni-popup>
  233. <!-- 留言弹窗 -->
  234. <uni-popup ref="popup_leaveWords" :is-mask-click="false">
  235. <view class="pop_leaveWords">
  236. <view class="leaveWords_title">留言</view>
  237. <view class="leaveWords_body">
  238. <textarea placeholder-style="color:#CCCCCC" placeholder="请输入您宝贵的留言" v-model="leaveWords"></textarea>
  239. </view>
  240. <view class="leaveWords_btn">
  241. <view class="btn_box cancel" @click="$refs.popup_leaveWords.close()">取消</view>
  242. <view class="btn_box confirm" @click="handleLeaveWordsConfirm">确定</view>
  243. </view>
  244. </view>
  245. </uni-popup>
  246. <!-- 维修费用弹窗 -->
  247. <uni-popup :is-mask-click="false" ref="popup_fee">
  248. <view class="pop_fee">
  249. <view class="fee_title">
  250. 维修费用
  251. <text @click="$refs.popup_fee.close()">×</text>
  252. </view>
  253. <view class="fee_content">
  254. <view class="fee_item" v-for="(element, index2) in goodsList" :key="index2">
  255. <view class="fee_box">
  256. 耗材:
  257. <text>{{ element.consumeName }}</text>
  258. </view>
  259. <view class="fee_box">
  260. 耗材单价:
  261. <text>{{ element.price }}元</text>
  262. </view>
  263. <view class="fee_box">
  264. 耗材数量:
  265. <text>{{ element.number }}</text>
  266. </view>
  267. <view class="fee_box">
  268. 耗材费用:
  269. <text>{{ element.totalPrice }}元</text>
  270. </view>
  271. </view>
  272. </view>
  273. </view>
  274. </uni-popup>
  275. <!-- 录音弹窗区域 -->
  276. <uni-popup :safe-area="true" background-color="#fff" ref="popup_recording">
  277. <view class="popup_recording">
  278. <recording @getTempFilePath="getTempFilePath" />
  279. </view>
  280. </uni-popup>
  281. </view>
  282. <!-- 没有数据时展示的图片 -->
  283. <view class="no_data" v-if="dataList.length === 0">
  284. <img src="../../pagesClockIn/static/imgs/nodata.png" />
  285. <view>暂无数据</view>
  286. </view>
  287. </scroll-view>
  288. </template>
  289. <script>
  290. import recording from '../components/recording.vue'
  291. const innerAudioContext = uni.createInnerAudioContext()
  292. export default {
  293. components: {
  294. recording
  295. },
  296. data() {
  297. return {
  298. scrollY: true,
  299. // 按钮权限
  300. btns: [],
  301. // 留言弹窗输入框绑定数据
  302. leaveWords: '',
  303. // 顶部分段器数组
  304. items: ['团队工单', '个人工单'],
  305. // 顶部分段器数组当前索引
  306. current: 0,
  307. // 关闭按钮弹窗当前索引
  308. activeIndex: 0,
  309. // 关闭按钮弹窗选项数组
  310. closeList: [],
  311. // 订单列表
  312. dataList: [],
  313. // 维修费用弹窗数组
  314. goodsList: [],
  315. // 校区id
  316. schoolId: '',
  317. // 用户ID
  318. userId: '',
  319. // 待处理
  320. logisticsCount: '',
  321. // 待审核
  322. examineCount: '',
  323. // 待接单
  324. receivingCount: '',
  325. // 维修中
  326. maintenanceCount: '',
  327. // 已完成
  328. finishedCount: '',
  329. // 已超时
  330. timeoutCount: '',
  331. // 已关单
  332. closedCount: '',
  333. // 当前页
  334. currentPage: 1,
  335. // 每页多少条
  336. pageCount: 2,
  337. // 总条数 团队
  338. total: null,
  339. // 总条数 个人
  340. total2: null,
  341. // 订单状态参数
  342. state: 1,
  343. // 订单id
  344. orderId: '',
  345. // 关闭订单备注
  346. closeNote: '',
  347. // 录音文件路径
  348. recordingPath: '',
  349. // 录音时长
  350. recordingTime: 0,
  351. // 录音图片地址
  352. recordingImg: '../../static/images/repairsImg/recording.jpg',
  353. // 播放状态
  354. playStatus: false,
  355. // 定时器标识
  356. timer: null
  357. }
  358. },
  359. mounted() {
  360. const repairsUserInfo = uni.getStorageSync('repairsUserInfo')
  361. this.schoolId = repairsUserInfo.schoolId
  362. this.userId = repairsUserInfo.userId
  363. this.btns = repairsUserInfo.btns
  364. if (this.btns.includes('工单管理分段器') || this.btns.includes('分段器按钮')) {
  365. // 管理员身份或者后勤
  366. this.getTeamCount()
  367. this.getTeamData()
  368. } else {
  369. // 维修师傅
  370. this.getCount()
  371. this.getData()
  372. }
  373. this.getCloseList()
  374. },
  375. methods: {
  376. // 滚动到底部触发回调
  377. scrolltolower() {
  378. if ((this.btns.includes('工单管理分段器') || this.btns.includes('分段器按钮')) && this.current === 0) {
  379. // 团队工单
  380. if (this.total > this.dataList.length) {
  381. this.currentPage++
  382. this.getTeamData()
  383. } else {
  384. uni.showToast({
  385. title: '没有更多数据了',
  386. icon: 'none'
  387. })
  388. }
  389. } else {
  390. // 个人工单
  391. if (this.total2 > this.dataList.length) {
  392. this.currentPage++
  393. this.getData()
  394. } else {
  395. uni.showToast({
  396. title: '没有更多数据了',
  397. icon: 'none'
  398. })
  399. }
  400. }
  401. },
  402. async getCloseList() {
  403. const res = await this.$myRequest_repairs({
  404. url: '/repairClose/queryRepairCloses'
  405. })
  406. // console.log(res)
  407. if (res.code === '200') {
  408. this.closeList = res.data
  409. }
  410. },
  411. handleFilter(state) {
  412. this.state = state
  413. this.dataList = []
  414. this.currentPage = 1
  415. this.handleResetData()
  416. },
  417. async getCount() {
  418. const res = await this.$myRequest_repairs({
  419. url: '/repairRecord/getTechnicianCountByUserId',
  420. data: {
  421. userId: this.userId
  422. }
  423. })
  424. // console.log(res)
  425. if (res.code === '200') {
  426. this.examineCount = res.data.examineCount
  427. this.maintenanceCount = res.data.maintenanceCount
  428. this.receivingCount = res.data.receivingCount
  429. this.timeoutCount = res.data.timeoutCount
  430. }
  431. },
  432. // 获取个人订单数据
  433. async getData() {
  434. const res = await this.$myRequest_repairs({
  435. url: '/repairRecord/getTechniciansByUserId',
  436. data: {
  437. currentPage: this.currentPage,
  438. pageCount: this.pageCount,
  439. state: this.state,
  440. userId: this.userId
  441. }
  442. })
  443. // console.log(res)
  444. if (res.code === '200') {
  445. this.total2 = res.data.totalCount
  446. res.data.list.forEach((ele) => {
  447. return (ele.status = false)
  448. })
  449. this.dataList = [...this.dataList, ...res.data.list]
  450. }
  451. },
  452. async getTeamCount() {
  453. const res = await this.$myRequest_repairs({
  454. url: '/repairRecord/queryTeamWorkCount',
  455. data: {
  456. schoolId: this.schoolId
  457. }
  458. })
  459. // console.log(res)
  460. if (res.code === '200') {
  461. this.examineCount = res.data.examineCount
  462. this.receivingCount = res.data.receivingCount
  463. this.maintenanceCount = res.data.maintenanceCount
  464. this.finishedCount = res.data.finishedCount
  465. this.timeoutCount = res.data.timeoutCount
  466. this.closedCount = res.data.closedCount
  467. this.logisticsCount = res.data.logisticsCount
  468. }
  469. },
  470. // 获取团队订单数据
  471. async getTeamData() {
  472. const res = await this.$myRequest_repairs({
  473. url: '/repairRecord/queryTeamWorkPage',
  474. data: {
  475. currentPage: this.currentPage,
  476. pageCount: this.pageCount,
  477. state: this.state,
  478. schoolId: this.schoolId
  479. }
  480. })
  481. // console.log(res)
  482. if (res.code === '200') {
  483. this.total = res.data.totalCount
  484. res.data.list.forEach((ele) => {
  485. return (ele.status = false)
  486. })
  487. this.dataList = [...this.dataList, ...res.data.list]
  488. }
  489. },
  490. // 留言弹窗确定按钮回调
  491. async handleLeaveWordsConfirm() {
  492. if (this.leaveWords) {
  493. const res = await this.$myRequest_repairs({
  494. url: '/repairRecord/mobileReply',
  495. method: 'post',
  496. data: {
  497. recordId: this.orderId,
  498. userId: this.userId,
  499. content: this.leaveWords
  500. }
  501. })
  502. // console.log(res)
  503. if (res.code === '200') {
  504. uni.showToast({
  505. title: '留言成功',
  506. icon: 'success',
  507. mask: true
  508. })
  509. this.$refs.popup_leaveWords.close()
  510. }
  511. } else {
  512. uni.showToast({
  513. title: '请输入留言内容',
  514. icon: 'none',
  515. mask: true
  516. })
  517. }
  518. },
  519. // 关闭弹窗取消按钮回调
  520. handleCloseCancel() {
  521. this.recordingPath = ''
  522. this.recordingTime = 0
  523. this.closeNote = ''
  524. this.$refs.popup_close.close()
  525. },
  526. // 关闭弹窗确定按钮回调
  527. handleCloseConfirm() {
  528. if (this.closeNote && this.recordingPath) {
  529. uni.showToast({
  530. title: '录音和备注二选一,不能同时选择',
  531. icon: 'none',
  532. mask: true
  533. })
  534. return
  535. }
  536. if (!this.closeNote && !this.recordingPath) {
  537. uni.showToast({
  538. title: '请录音或者输入备注,二选一',
  539. icon: 'none',
  540. mask: true
  541. })
  542. return
  543. }
  544. uni.showModal({
  545. title: '提示',
  546. content: '确定关闭订单吗?',
  547. success: async (res) => {
  548. if (res.confirm) {
  549. const res = await this.$myRequest_repairs({
  550. url: '/repairRecord/closeOrder',
  551. data: {
  552. recordId: this.orderId,
  553. userId: this.userId,
  554. reason: this.closeList[this.activeIndex].name,
  555. remark: this.recordingPath ? this.recordingPath : this.closeNote,
  556. voiceLength: this.recordingPath ? this.recordingTime : ''
  557. }
  558. })
  559. // console.log(res)
  560. if (res.code === '200') {
  561. uni.showToast({
  562. title: '关单成功',
  563. icon: 'success',
  564. mask: true
  565. })
  566. this.$refs.popup_close.close()
  567. setTimeout(() => {
  568. this.handleResetData()
  569. }, 1500)
  570. }
  571. }
  572. }
  573. })
  574. },
  575. // 重置当前页面获取最新数据
  576. handleResetData() {
  577. this.dataList = []
  578. this.currentPage = 1
  579. if ((this.btns.includes('工单管理分段器') || this.btns.includes('分段器按钮')) && this.current === 0) {
  580. // 管理员身份或者后勤
  581. this.getTeamCount()
  582. this.getTeamData()
  583. } else {
  584. // 维修师傅
  585. this.getCount()
  586. this.getData()
  587. }
  588. },
  589. // 接单按钮回调
  590. handleOrderReceiving(item) {
  591. uni.showModal({
  592. content: '确定接单吗?',
  593. title: '提示',
  594. success: async (res) => {
  595. if (res.confirm) {
  596. const res = await this.$myRequest_repairs({
  597. url: '/repairRecord/receiveOwnOrders',
  598. data: {
  599. recordId: item.id,
  600. userId: this.userId
  601. }
  602. })
  603. // console.log(res)
  604. if (res.code === '200') {
  605. uni.showToast({
  606. title: '接单成功',
  607. icon: 'success',
  608. mask: true
  609. })
  610. setTimeout(() => {
  611. this.handleResetData()
  612. }, 1500)
  613. }
  614. }
  615. }
  616. })
  617. },
  618. // 关闭图标点击回调
  619. handleClose(item) {
  620. this.orderId = item.id
  621. this.activeIndex = 0
  622. this.$refs.popup_close.open('center')
  623. },
  624. // 关闭按钮弹窗选中按钮时回调
  625. bindPickerChange(e) {
  626. this.activeIndex = e.detail.value
  627. },
  628. // 报价按钮回调
  629. handleOffer(item) {
  630. let info = encodeURIComponent(JSON.stringify(item))
  631. uni.navigateTo({
  632. url: `/pagesRepairs/offer/offer?info=${info}`
  633. })
  634. },
  635. // 改价按钮回调
  636. handleChangeOffer(item) {
  637. let info = encodeURIComponent(JSON.stringify(item))
  638. uni.navigateTo({
  639. url: `/pagesRepairs/offer/offer?info=${info}&type=1`
  640. })
  641. },
  642. // 维修完成按钮回调
  643. handleFinish(item) {
  644. const info = JSON.stringify(item)
  645. uni.navigateTo({
  646. url: `/pagesRepairs/repairRecord/repairRecord?info=${info}`
  647. })
  648. },
  649. // 转单按钮回调
  650. handleTransferOrder(item) {
  651. uni.navigateTo({
  652. url: `/pagesRepairs/transferOrder/transferOrder?id=${item.id}`
  653. })
  654. },
  655. // 协作图标点击回调
  656. handleHelp(item) {
  657. uni.navigateTo({
  658. url: `/pagesRepairs/help/help?id=${item.id}`
  659. })
  660. },
  661. // 分段器切换回调
  662. onClickItem(e) {
  663. if (this.current != e.currentIndex) {
  664. this.current = e.currentIndex
  665. this.state = 1
  666. this.dataList = []
  667. this.currentPage = 1
  668. if (this.current === 0) {
  669. // 团队工单
  670. this.getTeamCount()
  671. this.getTeamData()
  672. } else {
  673. // 个人工单
  674. this.getCount()
  675. this.getData()
  676. }
  677. }
  678. },
  679. // 留言按钮回调
  680. handleLeaveWords(item) {
  681. this.orderId = item.id
  682. this.$refs.popup_leaveWords.open('center')
  683. },
  684. // 延时按钮回调
  685. handleDelay(item) {
  686. uni.navigateTo({
  687. url: `/pagesRepairs/delay/delay?id=${item.id}`
  688. })
  689. },
  690. // 派单按钮回调
  691. handleSendOrder(item) {
  692. uni.navigateTo({
  693. url: `/pagesRepairs/helpPeople/helpPeople?type=1&id=${item.id}`
  694. })
  695. },
  696. // 审核按钮回调
  697. handleAudit(item) {
  698. if (item.state === '转单审核') {
  699. uni.navigateTo({
  700. url: `/pagesRepairs/transferOrder/transferOrder?type=1&id=${item.id}`
  701. })
  702. } else if (item.state === '协作审核') {
  703. uni.navigateTo({
  704. url: `/pagesRepairs/help/help?type=1&id=${item.id}`
  705. })
  706. }
  707. },
  708. // 查看维修费用回调
  709. checkFeeDetail(item) {
  710. // console.log(item)
  711. this.goodsList = item.goodsList
  712. this.$refs.popup_fee.open('center')
  713. },
  714. // 点击电话号码回调
  715. handleCallPhone(phone) {
  716. uni.makePhoneCall({
  717. phoneNumber: phone
  718. })
  719. },
  720. // 点击图片回调
  721. handleLookImgs(img) {
  722. // console.log(img)
  723. uni.previewImage({
  724. urls: img
  725. })
  726. },
  727. // 点击录音播放回调
  728. handlePlayRecording(item) {
  729. this.dataList.forEach((ele) => {
  730. if (ele.id !== item.id) {
  731. ele.status = false
  732. }
  733. })
  734. innerAudioContext.src = item.voice
  735. if (!item.status) {
  736. item.status = true
  737. innerAudioContext.play()
  738. //播放结束
  739. innerAudioContext.onEnded(() => {
  740. item.status = false
  741. })
  742. } else {
  743. item.status = false
  744. innerAudioContext.stop()
  745. }
  746. },
  747. handleGoDetail(item) {
  748. uni.navigateTo({
  749. url: `/pagesRepairs/repairDetails/repairDetails?id=${item.id}`
  750. })
  751. },
  752. // 点击录音按钮回调
  753. handleRecording() {
  754. uni.getSetting({
  755. success: (res) => {
  756. if (!res.authSetting['scope.record']) {
  757. uni.authorize({
  758. scope: 'scope.record',
  759. success(res) {
  760. // 授权成功
  761. uni.showToast({
  762. title: '授权成功',
  763. icon: 'none'
  764. })
  765. },
  766. fail() {
  767. uni.showModal({
  768. content: '检测到您没打开麦克风权限,是否去设置打开?',
  769. confirmText: '确认',
  770. cancelText: '取消',
  771. success: (res) => {
  772. if (res.confirm) {
  773. uni.openSetting({
  774. success: (res) => {}
  775. })
  776. } else {
  777. uni.showToast({
  778. title: '获取麦克风权限失败',
  779. icon: 'none'
  780. })
  781. }
  782. }
  783. })
  784. }
  785. })
  786. } else {
  787. this.$refs.popup_recording.open('bottom')
  788. }
  789. },
  790. fail() {
  791. uni.showToast({
  792. title: '获取麦克风权限失败',
  793. icon: 'none'
  794. })
  795. }
  796. })
  797. },
  798. // 自定义事件回调,获取录音文件路径
  799. getTempFilePath(path, time) {
  800. this.recordingPath = path
  801. this.recordingTime = time
  802. this.$refs.popup_recording.close()
  803. },
  804. // 点击录音播放回调
  805. handlePlayRecordingPop() {
  806. innerAudioContext.src = this.recordingPath
  807. if (!this.playStatus) {
  808. this.playStatus = true
  809. innerAudioContext.play()
  810. this.timer = setInterval(() => {
  811. if (this.recordingImg == '../../static/images/repairsImg/recording.jpg') {
  812. this.recordingImg = '../../static/images/repairsImg/recording2.jpg'
  813. } else if (this.recordingImg == '../../static/images/repairsImg/recording2.jpg') {
  814. this.recordingImg = '../../static/images/repairsImg/recording3.jpg'
  815. } else if (this.recordingImg == '../../static/images/repairsImg/recording3.jpg') {
  816. this.recordingImg = '../../static/images/repairsImg/recording.jpg'
  817. }
  818. }, 300)
  819. //播放结束
  820. innerAudioContext.onEnded(() => {
  821. clearInterval(this.timer)
  822. this.timer = null
  823. this.recordingImg = '../../static/images/repairsImg/recording.jpg'
  824. this.playStatus = false
  825. })
  826. } else {
  827. clearInterval(this.timer)
  828. this.recordingImg = '../../static/images/repairsImg/recording.jpg'
  829. this.playStatus = false
  830. innerAudioContext.stop()
  831. }
  832. },
  833. // 删除录音回调
  834. handleDeleteRecording() {
  835. if (this.playStatus) {
  836. uni.showToast({
  837. title: '播放中不能删除',
  838. icon: 'none',
  839. mask: true
  840. })
  841. } else {
  842. uni.showModal({
  843. title: '提示',
  844. content: '确定删除录音吗?',
  845. success: (res) => {
  846. if (res.confirm) {
  847. this.recordingPath = ''
  848. this.recordingTime = 0
  849. }
  850. }
  851. })
  852. }
  853. }
  854. }
  855. }
  856. </script>
  857. <style lang="scss" scoped>
  858. .container {
  859. width: 100vw;
  860. height: calc(100vh - 152rpx);
  861. font-size: 32rpx;
  862. overflow-y: auto;
  863. .top_bg {
  864. height: 165rpx;
  865. background-color: #6fb6b8;
  866. }
  867. .top_types {
  868. display: flex;
  869. flex-wrap: wrap;
  870. justify-content: space-evenly;
  871. margin: auto;
  872. margin-top: -100rpx;
  873. width: 690rpx;
  874. border-radius: 10rpx;
  875. box-shadow: 0px 0px 4rpx rgba(0, 0, 0, 0.25);
  876. background-color: #fff;
  877. .types_box {
  878. width: 25%;
  879. height: 188rpx;
  880. display: flex;
  881. flex-direction: column;
  882. justify-content: center;
  883. align-items: center;
  884. .box_num {
  885. font-size: 46rpx;
  886. color: #ff5733;
  887. }
  888. .box_info {
  889. margin-top: 10rpx;
  890. font-size: 34rpx;
  891. }
  892. }
  893. .active {
  894. color: #fff;
  895. background-color: #6fb6b8;
  896. }
  897. }
  898. .top_types2 {
  899. box-sizing: border-box;
  900. margin: auto;
  901. margin-top: -100rpx;
  902. padding: 0 30rpx;
  903. width: 690rpx;
  904. // height: 402rpx;
  905. border-radius: 10rpx;
  906. box-shadow: 0px 0px 4rpx rgba(0, 0, 0, 0.25);
  907. background-color: #fff;
  908. .top {
  909. height: 112rpx;
  910. border-bottom: 1rpx solid #e6e6e6;
  911. }
  912. .bottom {
  913. display: flex;
  914. flex-wrap: wrap;
  915. justify-content: space-evenly;
  916. .bottom_box {
  917. width: 25%;
  918. height: 145rpx;
  919. display: flex;
  920. flex-direction: column;
  921. justify-content: center;
  922. align-items: center;
  923. .box_num {
  924. font-size: 46rpx;
  925. color: #ff5733;
  926. }
  927. .box_info {
  928. // margin-top: 10rpx;
  929. font-size: 34rpx;
  930. }
  931. }
  932. .active {
  933. color: #fff;
  934. background-color: #6fb6b8;
  935. }
  936. }
  937. }
  938. .body {
  939. box-sizing: border-box;
  940. padding: 0 30rpx 30rpx 30rpx;
  941. .body_item {
  942. margin-top: 20rpx;
  943. padding-bottom: 35rpx;
  944. border-radius: 11rpx;
  945. box-shadow: 0 0 8rpx #d9d9d9;
  946. .item_title {
  947. display: flex;
  948. align-items: center;
  949. padding: 0 30rpx;
  950. height: 87rpx;
  951. border-bottom: 1rpx solid #e6e6e6;
  952. img {
  953. width: 30rpx;
  954. height: 30rpx;
  955. }
  956. .title_info {
  957. margin-left: 16rpx;
  958. font-size: 32rpx;
  959. }
  960. }
  961. .item_time {
  962. display: flex;
  963. justify-content: space-between;
  964. align-items: center;
  965. padding: 0 30rpx;
  966. .time_msg {
  967. width: 500rpx;
  968. color: #808080;
  969. text {
  970. color: #000000;
  971. }
  972. }
  973. .time_type {
  974. flex: 1;
  975. box-sizing: border-box;
  976. padding-left: 10rpx;
  977. font-size: 32rpx;
  978. color: #ff5733;
  979. line-height: 60rpx;
  980. }
  981. .color_type {
  982. color: #1e7dfb;
  983. }
  984. .color_type2 {
  985. color: #d43030;
  986. }
  987. .color_type3 {
  988. color: #6fb6b8;
  989. }
  990. .color_type4 {
  991. color: #a6a6a6;
  992. }
  993. }
  994. .item_box {
  995. display: flex;
  996. padding: 0 30rpx;
  997. line-height: 60rpx;
  998. .box_key {
  999. width: 160rpx;
  1000. color: #808080;
  1001. text-align-last: justify;
  1002. }
  1003. .box_value {
  1004. flex: 1;
  1005. display: flex;
  1006. align-items: center;
  1007. margin-right: auto;
  1008. min-width: calc(100% - width: 160rpx;);
  1009. img {
  1010. margin-left: 10rpx;
  1011. width: 45rpx;
  1012. height: 45rpx;
  1013. }
  1014. .recording {
  1015. display: flex;
  1016. align-items: center;
  1017. margin: 15rpx 0;
  1018. width: 130rpx;
  1019. height: 40rpx;
  1020. color: #000;
  1021. border-radius: 100rpx;
  1022. border: 1rpx solid #cccccc;
  1023. .voiceImg {
  1024. margin: 0 12rpx;
  1025. width: 30rpx;
  1026. height: 30rpx;
  1027. }
  1028. }
  1029. }
  1030. .box_type {
  1031. margin-left: 10rpx;
  1032. width: 137rpx;
  1033. height: 47rpx;
  1034. line-height: 47rpx;
  1035. text-align: center;
  1036. border-radius: 136rpx;
  1037. color: #ff5733;
  1038. font-size: 24rpx;
  1039. border: 1rpx solid #ff5733;
  1040. }
  1041. .box_value2 {
  1042. display: flex;
  1043. align-items: center;
  1044. img {
  1045. margin-top: -2rpx;
  1046. margin-left: 14rpx;
  1047. width: 46rpx;
  1048. height: 46rpx;
  1049. }
  1050. }
  1051. .phone {
  1052. color: #6fb6b8;
  1053. }
  1054. }
  1055. .item_img {
  1056. display: flex;
  1057. align-items: center;
  1058. padding: 0 30rpx;
  1059. margin: 10rpx 0;
  1060. height: 120rpx;
  1061. color: #808080;
  1062. .img_key {
  1063. }
  1064. .img_value {
  1065. width: 120rpx;
  1066. height: 120rpx;
  1067. border-radius: 14rpx;
  1068. }
  1069. }
  1070. .item_btn {
  1071. display: flex;
  1072. align-items: center;
  1073. justify-content: flex-end;
  1074. padding: 0 30rpx;
  1075. line-height: 153rpx;
  1076. img {
  1077. margin-right: auto;
  1078. margin-top: 45rpx;
  1079. width: 56rpx;
  1080. height: 56rpx;
  1081. }
  1082. .img {
  1083. margin-right: auto;
  1084. margin-left: -55rpx;
  1085. margin-top: 45rpx;
  1086. width: 62rpx;
  1087. height: 62rpx;
  1088. }
  1089. .btn_box {
  1090. display: flex;
  1091. justify-content: center;
  1092. align-items: center;
  1093. margin-left: 16rpx;
  1094. margin-top: 45rpx;
  1095. width: 174rpx;
  1096. height: 68rpx;
  1097. border-radius: 11rpx;
  1098. }
  1099. .type {
  1100. color: #fff;
  1101. background-color: #6fb6b8;
  1102. }
  1103. .type2 {
  1104. color: #6fb6b8;
  1105. background-color: #fff;
  1106. border: 1rpx solid #6fb6b8;
  1107. }
  1108. }
  1109. }
  1110. .popup_close {
  1111. width: 690rpx;
  1112. border-radius: 19rpx;
  1113. background-color: #fff;
  1114. .close_reason {
  1115. padding-top: 50rpx;
  1116. margin-left: 80rpx;
  1117. display: flex;
  1118. align-items: center;
  1119. .picker_input {
  1120. display: flex;
  1121. justify-content: space-between;
  1122. align-items: center;
  1123. padding: 10rpx 20rpx;
  1124. width: 300rpx;
  1125. border-radius: 14rpx;
  1126. border: 1rpx solid #e6e6e6;
  1127. img {
  1128. width: 40rpx;
  1129. height: 40rpx;
  1130. }
  1131. }
  1132. }
  1133. .close_note {
  1134. margin: 20rpx 0 20rpx 80rpx;
  1135. }
  1136. .close_voice {
  1137. display: flex;
  1138. align-items: center;
  1139. margin-top: 30rpx;
  1140. margin-left: 80rpx;
  1141. width: 500rpx;
  1142. height: 94rpx;
  1143. font-size: 32rpx;
  1144. color: #cccccc;
  1145. border-radius: 10rpx;
  1146. border: 1rpx solid #cccccc;
  1147. .voice_box {
  1148. display: flex;
  1149. justify-content: center;
  1150. align-items: center;
  1151. margin: 0 38rpx 0 33rpx;
  1152. width: 101rpx;
  1153. height: 47rpx;
  1154. border-radius: 33rpx;
  1155. box-shadow: 0px 0px 4rpx rgba(0, 0, 0, 0.25);
  1156. img {
  1157. width: 33rpx;
  1158. height: 33rpx;
  1159. }
  1160. }
  1161. .item_recording {
  1162. margin-left: 35rpx;
  1163. display: flex;
  1164. align-items: center;
  1165. width: 230rpx;
  1166. height: 65rpx;
  1167. color: #000;
  1168. border-radius: 100rpx;
  1169. border: 1rpx solid #cccccc;
  1170. img {
  1171. margin: 0 12rpx;
  1172. width: 40rpx;
  1173. height: 40rpx;
  1174. }
  1175. }
  1176. .recording_icon {
  1177. margin-left: auto;
  1178. margin-right: 35rpx;
  1179. font-size: 40rpx;
  1180. }
  1181. }
  1182. .close_input {
  1183. box-sizing: border-box;
  1184. margin: 35rpx 40rpx 35rpx 80rpx;
  1185. padding: 20rpx;
  1186. width: 520rpx;
  1187. height: 312rpx;
  1188. border-radius: 14rpx;
  1189. border: 1rpx solid #e6e6e6;
  1190. }
  1191. .close_btn {
  1192. display: flex;
  1193. align-items: center;
  1194. justify-content: space-evenly;
  1195. margin-top: 100rpx;
  1196. height: 121rpx;
  1197. .btn_box {
  1198. display: flex;
  1199. justify-content: center;
  1200. align-items: center;
  1201. width: 203rpx;
  1202. height: 72rpx;
  1203. border-radius: 9rpx;
  1204. font-size: 32rpx;
  1205. }
  1206. .cancel {
  1207. background-color: #e5e5e5;
  1208. color: #6fb6b8;
  1209. }
  1210. .confirm {
  1211. background-color: #6fb6b8;
  1212. color: #fff;
  1213. }
  1214. }
  1215. }
  1216. .pop_leaveWords {
  1217. border-radius: 19rpx;
  1218. background-color: #fff;
  1219. .leaveWords_title {
  1220. display: flex;
  1221. justify-content: center;
  1222. align-items: center;
  1223. width: 690rpx;
  1224. height: 110rpx;
  1225. font-size: 32rpx;
  1226. font-weight: bold;
  1227. border-radius: 19rpx 19rpx 0 0;
  1228. border-bottom: 1rpx solid #e6e6e6;
  1229. }
  1230. .leaveWords_body {
  1231. height: 320rpx;
  1232. textarea {
  1233. box-sizing: border-box;
  1234. margin: 35rpx 40rpx;
  1235. padding: 20rpx;
  1236. width: 610rpx;
  1237. height: 312rpx;
  1238. // font-size: 28rpx;
  1239. border-radius: 14rpx;
  1240. border: 1rpx solid #e6e6e6;
  1241. }
  1242. }
  1243. .leaveWords_btn {
  1244. display: flex;
  1245. align-items: center;
  1246. justify-content: space-evenly;
  1247. height: 121rpx;
  1248. .btn_box {
  1249. display: flex;
  1250. justify-content: center;
  1251. align-items: center;
  1252. width: 203rpx;
  1253. height: 72rpx;
  1254. border-radius: 9rpx;
  1255. font-size: 32rpx;
  1256. }
  1257. .cancel {
  1258. background-color: #e5e5e5;
  1259. color: #6fb6b8;
  1260. }
  1261. .confirm {
  1262. background-color: #6fb6b8;
  1263. color: #fff;
  1264. }
  1265. }
  1266. }
  1267. .pop_fee {
  1268. padding-bottom: 50rpx;
  1269. border-radius: 19rpx;
  1270. background-color: #fff;
  1271. .fee_title {
  1272. display: flex;
  1273. justify-content: space-between;
  1274. align-items: center;
  1275. box-sizing: border-box;
  1276. padding: 0 31rpx 0 42rpx;
  1277. width: 690rpx;
  1278. height: 110rpx;
  1279. font-size: 32rpx;
  1280. font-weight: bold;
  1281. border-radius: 19rpx 19rpx 0 0;
  1282. border-bottom: 1rpx solid #e6e6e6;
  1283. text {
  1284. font-size: 45rpx;
  1285. font-weight: 400;
  1286. color: #808080;
  1287. }
  1288. }
  1289. .fee_content {
  1290. max-height: 50vh;
  1291. overflow-y: auto;
  1292. .fee_item {
  1293. border-bottom: 1rpx solid #e6e6e6;
  1294. .fee_box {
  1295. display: flex;
  1296. align-items: center;
  1297. padding-left: 42rpx;
  1298. height: 80rpx;
  1299. // font-size: 28rpx;
  1300. color: #808080;
  1301. text {
  1302. color: #000000;
  1303. }
  1304. }
  1305. }
  1306. }
  1307. }
  1308. .popup_recording {
  1309. width: 100%;
  1310. height: 460rpx;
  1311. background-color: #fff;
  1312. }
  1313. }
  1314. .no_data {
  1315. text-align: center;
  1316. color: #b3b3b3;
  1317. font-size: 24rpx;
  1318. img {
  1319. margin: 42rpx auto 0;
  1320. width: 432rpx;
  1321. height: 456rpx;
  1322. }
  1323. }
  1324. }
  1325. </style>