handler.vue 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207
  1. <template>
  2. <view class="handler">
  3. <view class="head">
  4. <view class="tab" :class="{active: tab.value === dataInfo.tabActiveValue}" v-for="tab in dataInfo.tabs" :key="tab.id" @click="clickTab(tab.value)">
  5. {{tab.name}}<text v-if="tab.num !== ''">({{tab.num}})</text>
  6. </view>
  7. </view>
  8. <view class="body view-body" :class="{ page_padding: !(dataInfo.tabActiveValue === 'doing' && isInSummaryOrder), bg: (dataInfo.tabActiveValue === 'doing' && isInSummaryOrder) }">
  9. <!-- <scroll-view scroll-y class="body" :class="{ page_padding: !(dataInfo.tabActiveValue === 'doing' && isInSummaryOrder), bg: (dataInfo.tabActiveValue === 'doing' && isInSummaryOrder) }"> -->
  10. <!-- 汇总单 -->
  11. <template v-if="dataInfo.tabActiveValue === 'doing' && isInSummaryOrder">
  12. <!-- 耗材 -->
  13. <view class="summaryItem">
  14. <view class="summaryItem_head">
  15. 耗材清单
  16. </view>
  17. <view class="summaryItem_body" v-if="dataInfo.summaryObj.consumableList.length">
  18. <view class="summaryItem_bodyItem" v-for="item in dataInfo.summaryObj.consumableList" :key="item.id" @click="numberClick(item, 'editConsumable')">
  19. <view class="summaryItem_bodyItem_top">
  20. <text class="name ellipsis">{{ item.consumableName }}<template v-if="item.consumableBrandModel">({{ item.consumableBrandModel }})</template></text>
  21. <text class="value">{{ item.consumableEndPrice }}元</text>
  22. </view>
  23. <view class="summaryItem_bodyItem_bottom">
  24. <text class="name">x{{ item.consumablesNum }}{{ item.consumablesUnit }}</text>
  25. <text class="value">总价{{item.consumablesNum * item.consumableEndPrice}}元</text>
  26. </view>
  27. </view>
  28. </view>
  29. <view class="summaryItem_foot">
  30. <view class="summaryItem_foot_total">
  31. 耗材总价:{{dataInfo.summaryObj.consumablePrice}}元
  32. </view>
  33. <view class="summaryItem_foot_add" @click="addConsumable">
  34. <text class="newicon newicon-icon-test"></text>
  35. </view>
  36. </view>
  37. </view>
  38. <!-- 工时 -->
  39. <view class="summaryItem">
  40. <view class="summaryItem_head">
  41. 工时清单
  42. </view>
  43. <view class="summaryItem_body" v-if="dataInfo.summaryObj.workHourManagementList.length">
  44. <view class="summaryItem_bodyItem" v-for="item in dataInfo.summaryObj.workHourManagementList" :key="item.id" @click="numberClick(item, 'editWorkHourManagement')">
  45. <view class="summaryItem_bodyItem_top">
  46. <text class="name ellipsis">{{ item.workName }}</text>
  47. <text class="value">{{ item.wage }}元</text>
  48. </view>
  49. <view class="summaryItem_bodyItem_bottom">
  50. <text class="name">x{{ item.workHourNum2 }}{{ item.workUnit }}</text>
  51. <text class="value">总价{{item.workHourNum2 * item.wage}}元</text>
  52. </view>
  53. </view>
  54. </view>
  55. <view class="summaryItem_foot">
  56. <view class="summaryItem_foot_total">
  57. 工时总价:{{dataInfo.summaryObj.workHourPrice}}元
  58. </view>
  59. <view class="summaryItem_foot_add" @click="addWorkHourManagement">
  60. <text class="newicon newicon-icon-test"></text>
  61. </view>
  62. </view>
  63. </view>
  64. <!-- 汇总单总价 -->
  65. <view class="summaryItem">
  66. <view class="summaryItem_foot total">
  67. <view class="summary_total">
  68. 汇总单总价:{{dataInfo.summaryObj.totalMaintenancePrice}}元
  69. </view>
  70. </view>
  71. </view>
  72. </template>
  73. <!-- 故障处理 -->
  74. <template v-if="dataInfo.tabActiveValue === 'doing' && !isInSummaryOrder">
  75. <view class="form_item column" v-if="HandleData.simpleness != 1 || (HandleData.simpleness==1 && HandleData.isSolution==1)">
  76. <view class="title title-width">
  77. <text class="required newicon newicon-bitian"></text>
  78. <view class="title-fl-sb">
  79. 解决方案:
  80. <view @click="importRep('malfunction')" class="import-rep">引入知识库({{dataInfo.introduceCount}})</view>
  81. </view>
  82. </view>
  83. <uni-easyinput id="scheme" class="value" type="textarea" v-model="dataInfo.handleDescription" placeholder="请输入解决方案" :class="{formRed: isSubmit && !dataInfo.handleDescription.trim()}" />
  84. </view>
  85. <view class="form_item" v-if="newProvideBackupMachine==1">
  86. <view class="title"><text class="required newicon newicon-bitian"></text>是否归还备用机:</view>
  87. <uni-data-checkbox v-model="dataInfo.returnBackupMachine" :localdata="machineData"></uni-data-checkbox>
  88. </view>
  89. <view class="form_item" v-if="HandleData.simpleness != 1">
  90. <view class="title"><text class="required newicon newicon-bitian"></text>故障现象:</view>
  91. <view class="value category" @click="selectCategory">
  92. <text class="categoryName ellipsis-multiline">{{dataInfo.category.mutiCategory}}</text>
  93. <text class="newicon newicon-weibiaoti2010104"></text>
  94. </view>
  95. </view>
  96. <view class="form_item">
  97. <view class="title select"><text class="required newicon newicon-bitian"></text>处理方式:</view>
  98. <!-- <uni-data-select class="value" v-model="dataInfo.handleCategory" :localdata="dataInfo.handleCategoryList" :clear="false" placeholder="请选择处理方式" :class="{formRed: isSubmit && !dataInfo.handleCategory}"></uni-data-select> -->
  99. <uni-data-picker class="value" placeholder="请选择处理方式"
  100. v-model="dataInfo.handleCategory" :localdata="dataInfo.handleCategoryList"
  101. :clear-icon="false" :class="{formRed: isSubmit && !dataInfo.handleCategory}">
  102. </uni-data-picker>
  103. </view>
  104. <view class="form_item" v-if="HandleData.simpleness != 1">
  105. <view class="title select"><text class="required newicon newicon-bitian"></text>处理结果:</view>
  106. <!-- <uni-data-select class="value" v-model="dataInfo.closecode" :localdata="dataInfo.closecodeList" :clear="false" placeholder="请选择处理结果" :class="{formRed: isSubmit && !dataInfo.closecode}"></uni-data-select> -->
  107. <uni-data-picker class="value" placeholder="请选择处理结果"
  108. v-model="dataInfo.closecode" :localdata="dataInfo.closecodeList"
  109. :clear-icon="false" :class="{formRed: isSubmit && !dataInfo.closecode}">
  110. </uni-data-picker>
  111. </view>
  112. <view class="form_item">
  113. <view class="title"><text class="required newicon newicon-bitian transparent"></text>协同人员:</view>
  114. <text class="synergeticNames ellipsis">{{dataInfo.synergetic.map(v => v.name).join(',')}}</text>
  115. <button type="primary" plain size="mini" class="primaryPlainButton synergeticAdd" @click="synergeticAdd">+立即添加</button>
  116. </view>
  117. <view class="form_item_column">
  118. <view class="form_item">
  119. <view class="title"><text class="required newicon newicon-bitian transparent"></text>处理图片:</view>
  120. <view class="value">
  121. <uni-file-picker ref="handlerImgRef" v-model="dataInfo.handlerImgList" limit="3" @success="handlerImgSuccess" @fail="handlerImgFail" @select="handlerImgSelect" @delete="handlerImgDelete"></uni-file-picker>
  122. </view>
  123. </view>
  124. <view class="form_item">
  125. <view class="title transparent"><text class="required newicon newicon-bitian transparent"></text>处理图片:</view>
  126. <view class="value">
  127. <text class="imgTips ellipsis">(支持JPG/PNG格式图片,单张大小10M以内)</text>
  128. </view>
  129. </view>
  130. </view>
  131. </template>
  132. <!-- 延期处理 -->
  133. <template v-if="dataInfo.tabActiveValue === 'overtime'">
  134. <view class="form_item">
  135. <view class="title select"><text class="required newicon newicon-bitian"></text>延期原因:</view>
  136. <!-- <uni-data-select class="value" v-model="dataInfo.repairTypeId" :localdata="dataInfo.repairTypeList" :clear="false" placeholder="请选择延期原因" :class="{formRed: isSubmit && !dataInfo.repairTypeId}"></uni-data-select> -->
  137. <uni-data-picker class="value" placeholder="请选择延期原因"
  138. v-model="dataInfo.repairTypeId" :localdata="dataInfo.repairTypeList"
  139. :clear-icon="false" :class="{formRed: isSubmit && !dataInfo.repairTypeId}">
  140. </uni-data-picker>
  141. </view>
  142. <view class="form_item column">
  143. <view class="title"><text class="required newicon newicon-bitian"></text>延期说明:</view>
  144. <uni-easyinput class="value" type="textarea" v-model="dataInfo.deferralRemark" placeholder="请输入延期说明" :class="{formRed: isSubmit && !dataInfo.deferralRemark.trim()}" />
  145. </view>
  146. <view class="form_item">
  147. <view class="title select"><text class="required newicon newicon-bitian"></text>延期天数:</view>
  148. <!-- <uni-data-select class="value" v-model="dataInfo.deferralDayId" :localdata="dataInfo.deferralDayList" :clear="false" placeholder="请选择延期天数" :class="{formRed: isSubmit && !dataInfo.deferralDayId}"></uni-data-select> -->
  149. <uni-data-picker class="value" placeholder="请选择延期天数"
  150. v-model="dataInfo.deferralDayId" :localdata="dataInfo.deferralDayList"
  151. :clear-icon="false" :class="{formRed: isSubmit && !dataInfo.deferralDayId}">
  152. </uni-data-picker>
  153. </view>
  154. <view class="form_item">
  155. <view class="title"><text class="required newicon newicon-bitian"></text>是否提供备用机:</view>
  156. <uni-data-checkbox v-model="dataInfo.provideBackupMachine" :localdata="machineData"></uni-data-checkbox>
  157. </view>
  158. </template>
  159. <!-- </scroll-view> -->
  160. </view>
  161. <view class="foot_common_btns">
  162. <button @click="goBackOrToList" type="default" class="cancelButton btn">{{dataInfo.isSummaryNext ? '上一步' : '返回'}}</button>
  163. <button @click="submit" type="default" class="primaryButton btn">{{dataInfo.tabActiveValue === 'doing' && isInSummaryOrder ? '下一步' : '提交'}}</button>
  164. </view>
  165. <NumberModal v-if="dataInfo.isNumber" @cancelEmit="cancelNumber" @confirmEmit="conformNumber" @removeEmit="removeNumber" :selectData="dataInfo.selectData" :selectType="dataInfo.selectType" :evtNumber="dataInfo.evtNumber" showRemove></NumberModal>
  166. </view>
  167. </template>
  168. <script setup>
  169. import { ref, reactive, computed } from 'vue'
  170. import NumberModal from '@/components/NumberModal.vue';
  171. import { onLoad } from '@dcloudio/uni-app'
  172. import { generateNumberArray } from '@/utils/index.js'
  173. import { api_group, api_incidentDetail, getFetchDataList, api_getSolution, api_user, api_incidentTask, api_branch, api_dutyDepartment, api_getDictionary, api_querySummaryDoc, api_addSummaryDoc } from "@/http/api.js"
  174. import { defaultColor } from '@/static/js/theme.js'
  175. import { useSetTitle } from '@/share/useSetTitle.js'
  176. import { useMakePhoneCall } from '@/share/useMakePhoneCall.js'
  177. import { useUploadFile } from '@/share/useUploadFile.js'
  178. import { useGoBack } from '@/share/useGoBack.js'
  179. import { useLoginUserStore } from '@/stores/loginUser'
  180. import { useHandlerStore } from '@/stores/handler'
  181. useSetTitle();
  182. const loginUserStore = useLoginUserStore();
  183. const handlerStore = useHandlerStore();
  184. const { makePhoneCall } = useMakePhoneCall();
  185. const { uploadFile } = useUploadFile();
  186. const { goBack } = useGoBack();
  187. // 主题颜色
  188. const primaryColor = ref(defaultColor)
  189. // 备用机选项
  190. const machineData = ref([
  191. {
  192. text:'是',
  193. value:1
  194. },
  195. {
  196. text:'否',
  197. value:0
  198. },
  199. ])
  200. // 数据
  201. const dataInfo = reactive({
  202. tabs: [
  203. // {id: 5, name: '故障处理', value: 'doing', num: ''},
  204. // {id: 6, name: '延期处理', value: 'overtime', num: ''},
  205. ],
  206. tabActiveValue: 0,//当前选择的tab
  207. incidentId: undefined,//事件ID
  208. incidentData: {},//事件对象
  209. repairTypeList: [], //延期原因列表
  210. repairTypeId: undefined, //延期原因ID
  211. deferralDayList: [], //延期天数列表
  212. deferralDayId: undefined, //延期天数ID
  213. deferralRemark: '',//延期说明
  214. summaryObj: {
  215. consumableList: [],//耗材列表
  216. workHourManagementList: [],//工时列表
  217. },//汇总单信息
  218. summaryId: undefined,//汇总单Id
  219. isNumber: false,//修改数量弹窗
  220. evtNumber: 1,//弹窗返回的数量
  221. selectData: {},//选择的对象
  222. selectType: {},//选择的对象类型
  223. handleDescription: '',//解决方案
  224. handleCategory: undefined,//处理方式
  225. handleCategoryList: [],//处理方式列表
  226. closecode: undefined,//处理结果
  227. closecodeList: [],//处理结果列表
  228. handlerImgList: [],//处理图片列表
  229. category: {},//故障现象
  230. synergetic: [],//协同人员
  231. isSummaryNext: false,//汇总单-下一步
  232. introduceCount :0 ,//引入次数
  233. provideBackupMachine:0,//是否提供备用机
  234. returnBackupMachine:null//是否归还备用机
  235. })
  236. // 故障处理用是否提供备用机
  237. const newProvideBackupMachine = ref(0)
  238. // 知识库id
  239. const solutionId = ref(null)
  240. // 是否提交
  241. const isSubmit = ref(false)
  242. // 是否开启汇总单
  243. const SummaryData = ref(false)
  244. // 是否简单处理
  245. const HandleData = reactive({
  246. simpleness:null,
  247. isSolution:null,
  248. })
  249. // 处理图片
  250. const handlerImgRef = ref(null)
  251. // 是否进入汇总单
  252. const isInSummaryOrder = computed(() => {
  253. return dataInfo.tabActiveValue === 'doing' && SummaryData.value.value == 1 && (dataInfo.incidentData.handlingPersonnelUser.id == loginUserStore.loginUser.user.id);
  254. })
  255. // 上一步或者返回列表
  256. function goBackOrToList(){
  257. if(dataInfo.isSummaryNext){
  258. handlerStore.setHandlerData(dataInfo, 'assign', 'assign');
  259. goBack();
  260. }else{
  261. uni.reLaunch({
  262. url: '/pages/incidentList/incidentList'
  263. })
  264. }
  265. }
  266. // 上传处理图片成功
  267. function handlerImgSuccess(e){
  268. dataInfo.handlerImgList.forEach(v => {
  269. v.url = v.path;
  270. })
  271. console.log(dataInfo.handlerImgList);
  272. let handlerOrder$ = handlerOrder();
  273. let requestList = [handlerOrder$];
  274. dataInfo.handlerImgList.forEach(v => {
  275. let handlerOrderImg$ = handlerOrderImg(v);
  276. requestList.push(handlerOrderImg$);
  277. })
  278. Promise.all(requestList).then(resList => {
  279. uni.hideLoading();
  280. console.log(resList);
  281. if(resList[0].state == 200){
  282. uni.showToast({
  283. icon: 'none',
  284. title: '处理成功',
  285. mask: true,
  286. });
  287. setTimeout(() => {
  288. uni.reLaunch({
  289. url: '/pages/incidentList/incidentList',
  290. })
  291. }, 1500)
  292. }else{
  293. uni.showToast({
  294. icon: 'none',
  295. title: resList[0].msg || '请求数据失败!'
  296. });
  297. }
  298. })
  299. }
  300. // 上传处理图片失败
  301. function handlerImgFail(e){
  302. dataInfo.handlerImgList.forEach(v => {
  303. v.url = v.path;
  304. })
  305. console.log(dataInfo.handlerImgList);
  306. }
  307. // 选择上传图片
  308. function handlerImgSelect(e){
  309. dataInfo.handlerImgList = dataInfo.handlerImgList.concat(e.tempFiles);
  310. console.log(dataInfo.handlerImgList);
  311. }
  312. // 删除上传图片
  313. function handlerImgDelete(e){
  314. dataInfo.handlerImgList = dataInfo.handlerImgList.filter(v => e.tempFile.uuid != v.uuid);
  315. console.log(dataInfo.handlerImgList);
  316. }
  317. // 添加协同人员
  318. function synergeticAdd(){
  319. handlerStore.setHandlerData(dataInfo, 'handler');
  320. uni.navigateTo({
  321. url: `/pages/synergeticAdd/synergeticAdd?incidentId=${dataInfo.incidentId}`
  322. })
  323. }
  324. // 引入知识库
  325. function importRep(type){
  326. dataInfo.operateType = type
  327. handlerStore.setHandlerData(dataInfo, 'assign', 'assign');
  328. uni.navigateTo({
  329. url: `/pages/repository/repository`
  330. })
  331. }
  332. // 选择故障现象
  333. function selectCategory(){
  334. handlerStore.setHandlerData(dataInfo, 'handler');
  335. uni.navigateTo({
  336. url: `/pages/categoryOne/categoryOne?incidentId=${dataInfo.incidentId}`
  337. })
  338. }
  339. // 点击修改数量
  340. function numberClick(data, type){
  341. if(type === 'editConsumable'){
  342. dataInfo.evtNumber = data.consumablesNum;
  343. }else if(type === 'editWorkHourManagement'){
  344. dataInfo.evtNumber = data.workHourNum2;
  345. }
  346. dataInfo.isNumber = true;
  347. dataInfo.selectData = data;
  348. dataInfo.selectType = type;
  349. }
  350. // 确认修改数量
  351. function conformNumber(evtNumber){
  352. dataInfo.evtNumber = evtNumber;
  353. dataInfo.isNumber = false;
  354. addSummaryDoc();
  355. }
  356. // 移除数量
  357. function removeNumber(evtNumber){
  358. dataInfo.evtNumber = evtNumber;
  359. dataInfo.isNumber = false;
  360. removeSummaryDoc();
  361. }
  362. // 关闭修改数量
  363. function cancelNumber(){
  364. dataInfo.isNumber = false;
  365. }
  366. // 修改耗材/工时
  367. function addSummaryDoc(){
  368. uni.showLoading({
  369. title: "加载中",
  370. mask: true,
  371. });
  372. let postData = {
  373. "summaryId": dataInfo.summaryId,
  374. "modifyNum": 'edit',
  375. };
  376. if(dataInfo.selectType === 'editConsumable'){
  377. postData.consumableList = [
  378. {
  379. "consumablesId": dataInfo.selectData.consumableId,
  380. "consumablesNum": dataInfo.evtNumber,
  381. }
  382. ];
  383. }else if(dataInfo.selectType === 'editWorkHourManagement'){
  384. postData.workHourManagementList = [
  385. {
  386. "workHourId": dataInfo.selectData.id,
  387. "workHourNum": dataInfo.evtNumber,
  388. }
  389. ];
  390. }
  391. api_addSummaryDoc(postData).then(res => {
  392. uni.hideLoading();
  393. if(res.status == 200){
  394. uni.showToast({
  395. icon: 'none',
  396. title: '修改数量成功',
  397. mask: true,
  398. });
  399. getSummaryList();
  400. }else{
  401. uni.showToast({
  402. icon: 'none',
  403. title: res.msg || '请求数据失败!'
  404. });
  405. }
  406. })
  407. }
  408. // 移除耗材/工时
  409. function removeSummaryDoc(){
  410. uni.showLoading({
  411. title: "加载中",
  412. mask: true,
  413. });
  414. let postData = {
  415. "summaryId": dataInfo.summaryId,
  416. "remove": 'remove',
  417. };
  418. if(dataInfo.selectType === 'editConsumable'){
  419. postData.consumableList = [
  420. {
  421. "consumablesId": dataInfo.selectData.consumableId,
  422. "consumablesNum": dataInfo.evtNumber,
  423. }
  424. ];
  425. }else if(dataInfo.selectType === 'editWorkHourManagement'){
  426. postData.workHourManagementList = [
  427. {
  428. "workHourId": dataInfo.selectData.id,
  429. "workHourNum": dataInfo.evtNumber,
  430. }
  431. ];
  432. }
  433. api_addSummaryDoc(postData).then(res => {
  434. uni.hideLoading();
  435. if(res.status == 200){
  436. uni.showToast({
  437. icon: 'none',
  438. title: '移除成功',
  439. mask: true,
  440. });
  441. getSummaryList();
  442. }else{
  443. uni.showToast({
  444. icon: 'none',
  445. title: res.msg || '请求数据失败!'
  446. });
  447. }
  448. })
  449. }
  450. // 重置
  451. function reset(){
  452. dataInfo.repairTypeList = []; //延期原因列表
  453. dataInfo.repairTypeId = undefined; //延期原因ID
  454. dataInfo.deferralDayList = []; //延期天数列表
  455. dataInfo.deferralDayId = undefined; //延期天数ID
  456. dataInfo.deferralRemark = '';//延期说明
  457. dataInfo.summaryObj = {
  458. consumableList: [],//耗材列表
  459. workHourManagementList: [],//工时列表
  460. };//汇总单信息
  461. dataInfo.summaryId = undefined;//汇总单Id
  462. dataInfo.isNumber = false;//修改数量弹窗
  463. dataInfo.evtNumber = 1;//弹窗返回的数量
  464. dataInfo.selectData = {};//选择的对象
  465. dataInfo.selectType = {};//选择的对象类型
  466. dataInfo.handleDescription = '';//解决方案
  467. solutionId.value = null;//引用知识库id
  468. dataInfo.handleCategory = undefined;//处理方式
  469. dataInfo.handleCategoryList = [];//处理方式列表
  470. dataInfo.closecode = undefined;//处理结果
  471. dataInfo.closecodeList = [];//处理结果列表
  472. dataInfo.handlerImgList = [];//处理图片列表
  473. dataInfo.category = {};//故障现象
  474. dataInfo.synergetic = [];//协同人员
  475. dataInfo.provideBackupMachine = 0
  476. dataInfo.returnBackupMachine = null
  477. }
  478. // 初始化表单
  479. function initForm(){
  480. if(dataInfo.tabActiveValue === 'doing' && isInSummaryOrder.value){
  481. getSummaryList();
  482. }else if(dataInfo.tabActiveValue === 'doing' && !isInSummaryOrder.value){
  483. getHandleCategorys();
  484. getClosecodes();
  485. }else if(dataInfo.tabActiveValue === 'overtime'){
  486. getRepairTypes();
  487. getDeferralDays();
  488. }
  489. }
  490. // 点击tab
  491. function clickTab(tabValue){
  492. if(dataInfo.tabActiveValue == tabValue){
  493. return;
  494. }
  495. dataInfo.tabActiveValue = tabValue;
  496. isSubmit.value = false;
  497. reset();
  498. dataInfo.category = dataInfo.incidentData.category || {};
  499. dataInfo.synergetic = dataInfo.incidentData.synergetic || [];
  500. newProvideBackupMachine.value = dataInfo.incidentData.provideBackupMachine
  501. initForm();
  502. }
  503. // 获取事件详情
  504. function getIncidentDetail(){
  505. uni.showLoading({
  506. title: "加载中",
  507. mask: true,
  508. });
  509. let title = null;
  510. api_incidentDetail(dataInfo.incidentId).then(res => {
  511. uni.hideLoading();
  512. if(res.status == 200){
  513. dataInfo.incidentData = res.data || {};
  514. if(res.data.state.value!='handler'){
  515. uni.showToast({
  516. icon: 'none',
  517. title: '工单状态异常!请刷新页面再重试',
  518. });
  519. setTimeout(_=>{
  520. goBackOrToList()
  521. },1000)
  522. return
  523. }
  524. dataInfo.summaryId = res.data.summaryId;
  525. newProvideBackupMachine.value = dataInfo.incidentData.provideBackupMachine
  526. let storeData = handlerStore.handler.data
  527. if(storeData && storeData.type!='rep'){
  528. if(dataInfo.isSummaryNext){
  529. // 汇总单-下一步
  530. dataInfo.incidentData.duty.addSummary = 0;
  531. }
  532. }
  533. // 跳转页面选择了选项并且工单ID一致
  534. if(handlerStore.handler.data && handlerStore.handler.data.incidentId == dataInfo.incidentId){
  535. if(dataInfo.handleDescription){
  536. dataInfo.handleDescription = null;
  537. }
  538. Object.assign(dataInfo, handlerStore.handler.data);
  539. getIntroduceCount(dataInfo.category.id)
  540. handlerStore.clearHandlerData();
  541. }else{
  542. handlerStore.clearHandlerData();
  543. // 初始化回显
  544. dataInfo.category = dataInfo.incidentData.category || {};
  545. dataInfo.synergetic = dataInfo.incidentData.synergetic || [];
  546. getIntroduceCount(dataInfo.category.id)
  547. let chuli = false;//故障处理权限
  548. let menu = JSON.parse(uni.getStorageSync("menuList")) || []; //菜单
  549. menu.forEach((e) => {
  550. if (e.title=='故障管理') {
  551. e.childrens.forEach((el) => {
  552. if(el.link=='incidentManagement'){
  553. el.childrens.forEach(item =>{
  554. if (item.link == "handle") {
  555. chuli = true;
  556. }
  557. })
  558. }
  559. });
  560. }
  561. });
  562. // 故障处理
  563. if(dataInfo.incidentData.state.value == 'handler' && dataInfo.incidentData.handlingPersonnelUser && dataInfo.incidentData.handlingPersonnelUser.id == loginUserStore.loginUser.user.id && chuli){
  564. let flag = dataInfo.tabs.some(v => v.value === 'doing');
  565. !flag && dataInfo.tabs.splice(0, 0, {id: 5, name: '故障处理', value: 'doing', num: ''});
  566. }
  567. // 延期处理
  568. if(dataInfo.incidentData.state.value == 'handler' && dataInfo.incidentData.handlingPersonnelUser && dataInfo.incidentData.handlingPersonnelUser.id == loginUserStore.loginUser.user.id){
  569. let flag = dataInfo.tabs.some(v => v.value === 'overtime');
  570. !flag && dataInfo.tabs.push({id: 6, name: '延期处理', value: 'overtime', num: ''});
  571. }
  572. dataInfo.tabActiveValue = dataInfo.tabs[0].value;
  573. }
  574. initForm()
  575. }else{
  576. uni.showToast({
  577. icon: 'none',
  578. title: res.msg || '请求数据失败!'
  579. });
  580. }
  581. })
  582. }
  583. // 获取延期原因列表
  584. function getRepairTypes(){
  585. uni.showLoading({
  586. title: "加载中",
  587. mask: true,
  588. });
  589. let postData = {
  590. "key": 'repair_type',
  591. "type": "list",
  592. };
  593. api_getDictionary(postData).then(res => {
  594. uni.hideLoading();
  595. res = res || [];
  596. dataInfo.repairTypeList = res.map(v => ({
  597. text: v.name,
  598. value: v.id,
  599. }));
  600. })
  601. }
  602. // 获取处理方式列表
  603. function getHandleCategorys(){
  604. uni.showLoading({
  605. title: "加载中",
  606. mask: true,
  607. });
  608. let postData = {
  609. "key": 'incident_handle_type',
  610. "type": "list",
  611. };
  612. api_getDictionary(postData).then(res => {
  613. uni.hideLoading();
  614. res = res || [];
  615. dataInfo.handleCategoryList = res.map(v => ({
  616. text: v.name,
  617. value: v.id,
  618. key: v.value,
  619. }));
  620. if(!dataInfo.handleCategory){
  621. let handleCategory = dataInfo.handleCategoryList.find(v => v.key == 'SUPPORT');
  622. dataInfo.handleCategory = handleCategory ? handleCategory.value : undefined;
  623. }
  624. })
  625. }
  626. // 获取处理结果列表
  627. function getClosecodes(){
  628. uni.showLoading({
  629. title: "加载中",
  630. mask: true,
  631. });
  632. let postData = {
  633. "key": 'incident_closecode',
  634. "type": "list",
  635. };
  636. api_getDictionary(postData).then(res => {
  637. uni.hideLoading();
  638. res = res || [];
  639. dataInfo.closecodeList = res.map(v => ({
  640. text: v.name,
  641. value: v.id,
  642. key: v.value,
  643. }));
  644. if(!dataInfo.closecode){
  645. let closecode = dataInfo.closecodeList.find(v => v.key == '1');
  646. dataInfo.closecode = closecode ? closecode.value : undefined;
  647. }
  648. })
  649. }
  650. // 获取延期天数列表
  651. function getDeferralDays(){
  652. dataInfo.deferralDayList = generateNumberArray(1, 15).map(v => ({
  653. text: v + '天',
  654. value: v,
  655. }));
  656. dataInfo.deferralDayList.unshift({
  657. text: '0.5天',
  658. value: 0.5,
  659. })
  660. }
  661. // 获取汇总单信息
  662. function getSummaryList(){
  663. uni.showLoading({
  664. title: "加载中",
  665. mask: true,
  666. });
  667. let postData = {
  668. "incidentId": dataInfo.incidentId,
  669. };
  670. api_querySummaryDoc(postData).then(res => {
  671. uni.hideLoading();
  672. if(res.status == 200){
  673. dataInfo.summaryObj = {...{consumableList:[], workHourManagementList: []}, ...res };
  674. dataInfo.summaryId = res.summaryId;
  675. }else if(res.status == 201){
  676. // 事件第一次绑定汇总单
  677. dataInfo.summaryId = res.summaryId;
  678. }else{
  679. uni.showToast({
  680. icon: 'none',
  681. title: res.msg || '请求数据失败!'
  682. });
  683. }
  684. })
  685. }
  686. // 添加耗材
  687. function addConsumable(){
  688. uni.navigateTo({
  689. url: `/pages/consumableList/consumableList?incidentId=${dataInfo.incidentId}&summaryId=${dataInfo.summaryId}&categoryId=${dataInfo.category.id}`
  690. })
  691. }
  692. // 添加工时
  693. function addWorkHourManagement(){
  694. let hosId = dataInfo.incidentData.duty.id
  695. uni.navigateTo({
  696. url: `/pages/workHourManagementOne/workHourManagementOne?incidentId=${dataInfo.incidentId}&summaryId=${dataInfo.summaryId}&hosId=${hosId}`
  697. })
  698. }
  699. // 提交
  700. function submit(){
  701. isSubmit.value = true;
  702. if(dataInfo.tabActiveValue === 'doing' && isInSummaryOrder.value){
  703. uni.navigateTo({
  704. url: `/pages/handler/handler?incidentId=${dataInfo.incidentId}&isSummaryNext=1&type=0`,
  705. });
  706. }else if(dataInfo.tabActiveValue === 'doing' && !isInSummaryOrder.value){
  707. submitHandler();
  708. }else if(dataInfo.tabActiveValue === 'overtime'){
  709. submitOvertime();
  710. }
  711. }
  712. // 处理提交事件
  713. function handlerOrder(){
  714. dataInfo.incidentData.returnBackupMachine = dataInfo.returnBackupMachine
  715. let postData = {
  716. incident: dataInfo.incidentData,
  717. solutionId:solutionId.value
  718. }
  719. postData.incident.handleDescription = dataInfo.handleDescription;
  720. postData.incident.handleCategory = {id: dataInfo.handleCategory};
  721. postData.incident.closecode = {id: dataInfo.closecode};
  722. postData.incident.category = dataInfo.category;
  723. postData.incident.synergetic = dataInfo.synergetic;
  724. return api_incidentTask(dataInfo.tabActiveValue, postData);
  725. }
  726. // 处理图片
  727. function handlerOrderImg(imgObj){
  728. return uploadFile(imgObj, 'incident', dataInfo.incidentId)
  729. }
  730. // 处理提交
  731. function submitHandler(){
  732. console.log(dataInfo);
  733. if(!dataInfo.handleDescription.trim() && HandleData.simpleness != 1){
  734. uni.showToast({
  735. icon: 'none',
  736. title: '请填写解决方案'
  737. });
  738. return;
  739. }
  740. if(newProvideBackupMachine.value==1 && dataInfo.returnBackupMachine==null){
  741. uni.showToast({
  742. icon: 'none',
  743. title: '请选择是否归还备用机'
  744. });
  745. return;
  746. }
  747. if(!dataInfo.category.id && HandleData.simpleness != 1){
  748. uni.showToast({
  749. icon: 'none',
  750. title: '请选择故障现象'
  751. });
  752. return;
  753. }
  754. if(!dataInfo.handleCategory){
  755. uni.showToast({
  756. icon: 'none',
  757. title: '请选择处理方式'
  758. });
  759. return;
  760. }
  761. if(!dataInfo.closecode && HandleData.simpleness != 1){
  762. uni.showToast({
  763. icon: 'none',
  764. title: '请选择处理结果'
  765. });
  766. return;
  767. }
  768. console.log(dataInfo.handlerImgList)
  769. // if(HandleData.simpleness==1){
  770. // dataInfo.closecode = '1'
  771. // }
  772. uni.showLoading({
  773. title: "加载中",
  774. mask: true,
  775. });
  776. if(dataInfo.handlerImgList.length){
  777. // 有图片
  778. handlerImgRef.value.upload();
  779. }else{
  780. // 没有图片
  781. let handlerOrder$ = handlerOrder();
  782. let requestList = [handlerOrder$];
  783. Promise.all(requestList).then(resList => {
  784. uni.hideLoading();
  785. console.log(resList);
  786. if(resList[0].state == 200){
  787. uni.showToast({
  788. icon: 'none',
  789. title: '处理成功',
  790. mask: true,
  791. });
  792. setTimeout(() => {
  793. uni.reLaunch({
  794. url: '/pages/incidentList/incidentList',
  795. })
  796. }, 1500)
  797. }else{
  798. uni.showToast({
  799. icon: 'none',
  800. title: resList[0].msg || '请求数据失败!'
  801. });
  802. }
  803. })
  804. }
  805. }
  806. // 延期处理提交
  807. function submitOvertime(){
  808. if(!dataInfo.repairTypeId){
  809. uni.showToast({
  810. icon: 'none',
  811. title: '请选择延期原因'
  812. });
  813. return;
  814. }
  815. if(!dataInfo.deferralRemark.trim()){
  816. uni.showToast({
  817. icon: 'none',
  818. title: '请填写延期说明'
  819. });
  820. return;
  821. }
  822. if(!dataInfo.deferralDayId){
  823. uni.showToast({
  824. icon: 'none',
  825. title: '请选择延期天数'
  826. });
  827. return;
  828. }
  829. uni.showLoading({
  830. title: "加载中",
  831. mask: true,
  832. });
  833. dataInfo.incidentData.provideBackupMachine = dataInfo.provideBackupMachine
  834. let postData = {
  835. incident: dataInfo.incidentData,
  836. }
  837. postData.incident.currentLog = {
  838. remark: dataInfo.deferralRemark,
  839. extra1: dataInfo.repairTypeId,
  840. extra2: dataInfo.deferralDayId,
  841. }
  842. api_incidentTask(dataInfo.tabActiveValue, postData).then(res => {
  843. uni.hideLoading();
  844. if(res.state == 200){
  845. uni.showToast({
  846. icon: 'none',
  847. title: '延期处理成功',
  848. mask: true,
  849. });
  850. setTimeout(() => {
  851. uni.reLaunch({
  852. url: '/pages/incidentList/incidentList',
  853. })
  854. }, 1500)
  855. }else{
  856. uni.showToast({
  857. icon: 'none',
  858. title: res.msg || '请求数据失败!'
  859. });
  860. }
  861. })
  862. }
  863. // 获取知识库数量
  864. function getIntroduceCount(categoryId){
  865. uni.showLoading({
  866. title: "加载中",
  867. mask: true,
  868. });
  869. let query = {
  870. "key": 'solution_status',
  871. "type": "list",
  872. };
  873. api_getDictionary(query).then(res=>{
  874. let typeId = res.find(v => v.value == '3');
  875. let postData = {
  876. idx: 0,
  877. sum: 9999,
  878. solution: {
  879. deleteFlag:0,
  880. hosId: loginUserStore.loginUser.user.currentHospital.id,
  881. categoryId:categoryId,
  882. status:{id:typeId.id},
  883. }
  884. }
  885. api_getSolution(postData).then(res => {
  886. uni.hideLoading();
  887. if(res.status == 200){
  888. dataInfo.introduceCount = res.totalNum
  889. }else{
  890. uni.showToast({
  891. icon: 'none',
  892. title: res.msg || '请求数据失败!'
  893. });
  894. }
  895. })
  896. })
  897. }
  898. // 获取文本内容
  899. function getHtml(html) {
  900. const tempDiv = document.createElement('div');
  901. tempDiv.innerHTML = html;
  902. return tempDiv.textContent || tempDiv.innerText || '';
  903. }
  904. // 获取是否开启汇总单、简易处理
  905. function getHosConfig(){
  906. let postData = {
  907. idx: 0,
  908. sum: 9999,
  909. hospitalConfig:{
  910. hosId: loginUserStore.loginUser.user.currentHospital.id,
  911. model: "itsm"
  912. }
  913. };
  914. getFetchDataList("simple/data", "hospitalConfig", postData)
  915. .then((res) => {
  916. if(dataInfo.isSummaryNext!=1){
  917. SummaryData.value = res.list.find(i=>i.key=='itsmSummarySheet')
  918. }
  919. HandleData.simpleness = res.list.find(i=>i.key=='itsmSimpleHandle').value
  920. HandleData.isSolution = res.list.find(i=>i.key=='itsmWriteSolution').value
  921. });
  922. }
  923. onLoad((option) => {
  924. let storeData = handlerStore.handler.data
  925. if(storeData && storeData.type=='rep'){
  926. solutionId.value = storeData.solutionId
  927. dataInfo.isSummaryNext = storeData.isSummaryNext
  928. dataInfo.incidentId = storeData.incidentId;
  929. }else{
  930. dataInfo.incidentId = option.incidentId;
  931. dataInfo.isSummaryNext = option.isSummaryNext == 1;
  932. }
  933. getHosConfig()
  934. getIncidentDetail();
  935. })
  936. </script>
  937. <style lang="scss" scoped>
  938. .handler{
  939. height: 100%;
  940. display: flex;
  941. flex-direction: column;
  942. justify-content: space-between;
  943. .head{
  944. height: 88rpx;
  945. display: flex;
  946. position: fixed;
  947. z-index: 99;
  948. width: 100%;
  949. background-color: #fff;
  950. font-size: 30rpx;
  951. .tab{
  952. flex: 1;
  953. display: flex;
  954. justify-content: center;
  955. align-items: center;
  956. border-bottom: 4rpx solid transparent;
  957. &.active{
  958. color: $uni-primary;
  959. border-color: $uni-primary;
  960. }
  961. }
  962. }
  963. .body{
  964. margin-top: 88rpx;
  965. box-sizing: border-box;
  966. flex: 1;
  967. min-height: 0;
  968. &.bg{
  969. background-color: #F7F7F7;
  970. }
  971. .summaryItem{
  972. &:first-of-type{
  973. .summaryItem_head{
  974. border-bottom: 1rpx solid #DDDDDD;
  975. }
  976. }
  977. .summary_total{
  978. padding: 20rpx 0;
  979. display: flex;
  980. justify-content: center;
  981. align-items: center;
  982. }
  983. .summaryItem_head{
  984. padding: 24rpx;
  985. font-size: 26rpx;
  986. color: #3A3A3A;
  987. }
  988. .summaryItem_body{
  989. font-size: 30rpx;
  990. background-color: #fff;
  991. .summaryItem_bodyItem{
  992. padding: 24rpx;
  993. border-bottom: 1rpx solid #DDDDDD;
  994. .summaryItem_bodyItem_top{
  995. display: flex;
  996. justify-content: space-between;
  997. align-items: center;
  998. .value{
  999. padding-left: 48rpx;
  1000. flex-shrink: 0;
  1001. }
  1002. }
  1003. .summaryItem_bodyItem_bottom{
  1004. margin-top: 24rpx;
  1005. display: flex;
  1006. justify-content: space-between;
  1007. align-items: center;
  1008. .name{
  1009. text-align: right;
  1010. flex: 1;
  1011. }
  1012. .value{
  1013. width: 240rpx;
  1014. text-align: right;
  1015. padding-left: 48rpx;
  1016. flex-shrink: 0;
  1017. }
  1018. }
  1019. }
  1020. }
  1021. .summaryItem_foot{
  1022. font-size: 30rpx;
  1023. background-color: #fff;
  1024. &.total{
  1025. margin-top: 24rpx;
  1026. }
  1027. .summaryItem_foot_total{
  1028. padding: 24rpx 0;
  1029. display: flex;
  1030. justify-content: center;
  1031. align-items: center;
  1032. }
  1033. .summaryItem_foot_add{
  1034. border-top: 1rpx solid #DDDDDD;
  1035. padding: 24rpx 0;
  1036. display: flex;
  1037. justify-content: center;
  1038. align-items: center;
  1039. .newicon-icon-test{
  1040. font-size: 30rpx;
  1041. font-weight: bold;
  1042. }
  1043. }
  1044. }
  1045. }
  1046. .form_item_column{
  1047. padding-top: 24rpx;
  1048. min-height: 86rpx;
  1049. .form_item{
  1050. padding-top: 0;
  1051. min-height: auto;
  1052. }
  1053. }
  1054. .form_item{
  1055. display: flex;
  1056. align-items: center;
  1057. padding-top: 24rpx;
  1058. min-height: 86rpx;
  1059. &.column{
  1060. height: auto;
  1061. flex-direction: column;
  1062. align-items: flex-start;
  1063. .import-rep{
  1064. padding: 5rpx 10rpx;
  1065. border-radius: 50rpx;
  1066. background: #d1fcd5;
  1067. color: #49b856;
  1068. font-size: 24rpx;
  1069. }
  1070. .title{
  1071. margin-right: 0;
  1072. }
  1073. .title-width{
  1074. width: 100%;
  1075. }
  1076. .title-fl-sb{
  1077. display: flex;
  1078. justify-content: space-between;
  1079. width: 100%;
  1080. }
  1081. .value{
  1082. margin-top: 10rpx;
  1083. padding-left: 20rpx;
  1084. box-sizing: border-box;
  1085. }
  1086. .tips{
  1087. padding: 24rpx;
  1088. text-align: center;
  1089. font-size: 22rpx;
  1090. color: #909399;
  1091. width: 100%;
  1092. box-sizing: border-box;
  1093. }
  1094. }
  1095. .title{
  1096. font-size: 26rpx;
  1097. display: flex;
  1098. align-items: center;
  1099. margin-right: 12rpx;
  1100. flex-shrink: 0;
  1101. &.select{
  1102. width: calc(5em + 20rpx);
  1103. }
  1104. }
  1105. .value{
  1106. width: 100%;
  1107. &.category{
  1108. width: 100%;
  1109. display: flex;
  1110. justify-content: space-between;
  1111. align-items: center;
  1112. .categoryName{
  1113. font-size: 26rpx;
  1114. color: #555;
  1115. flex: 1;
  1116. }
  1117. .newicon-weibiaoti2010104{
  1118. color: $uni-primary;
  1119. margin-left: 24rpx;
  1120. }
  1121. }
  1122. .imgTips{
  1123. color: #909399;
  1124. font-size: 22rpx;
  1125. }
  1126. }
  1127. .synergeticNames{
  1128. font-size: 26rpx;
  1129. margin-right: 24rpx;
  1130. }
  1131. .synergeticAdd{
  1132. flex-shrink: 0;
  1133. }
  1134. }
  1135. }
  1136. }
  1137. </style>