handler.vue 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203
  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 = loginUserStore.loginUser.menu || []; //菜单
  549. menu.forEach((e) => {
  550. if(e.link=='incidentManagement'){
  551. e.childrens.forEach(item =>{
  552. if (item.link == "handle") {
  553. chuli = true;
  554. }
  555. })
  556. }
  557. });
  558. // 故障处理
  559. if(dataInfo.incidentData.state.value == 'handler' && dataInfo.incidentData.handlingPersonnelUser && dataInfo.incidentData.handlingPersonnelUser.id == loginUserStore.loginUser.user.id && chuli){
  560. let flag = dataInfo.tabs.some(v => v.value === 'doing');
  561. !flag && dataInfo.tabs.splice(0, 0, {id: 5, name: '故障处理', value: 'doing', num: ''});
  562. }
  563. // 延期处理
  564. if(dataInfo.incidentData.state.value == 'handler' && dataInfo.incidentData.handlingPersonnelUser && dataInfo.incidentData.handlingPersonnelUser.id == loginUserStore.loginUser.user.id){
  565. let flag = dataInfo.tabs.some(v => v.value === 'overtime');
  566. !flag && dataInfo.tabs.push({id: 6, name: '延期处理', value: 'overtime', num: ''});
  567. }
  568. dataInfo.tabActiveValue = dataInfo.tabs[0].value;
  569. }
  570. initForm()
  571. }else{
  572. uni.showToast({
  573. icon: 'none',
  574. title: res.msg || '请求数据失败!'
  575. });
  576. }
  577. })
  578. }
  579. // 获取延期原因列表
  580. function getRepairTypes(){
  581. uni.showLoading({
  582. title: "加载中",
  583. mask: true,
  584. });
  585. let postData = {
  586. "key": 'repair_type',
  587. "type": "list",
  588. };
  589. api_getDictionary(postData).then(res => {
  590. uni.hideLoading();
  591. res = res || [];
  592. dataInfo.repairTypeList = res.map(v => ({
  593. text: v.name,
  594. value: v.id,
  595. }));
  596. })
  597. }
  598. // 获取处理方式列表
  599. function getHandleCategorys(){
  600. uni.showLoading({
  601. title: "加载中",
  602. mask: true,
  603. });
  604. let postData = {
  605. "key": 'incident_handle_type',
  606. "type": "list",
  607. };
  608. api_getDictionary(postData).then(res => {
  609. uni.hideLoading();
  610. res = res || [];
  611. dataInfo.handleCategoryList = res.map(v => ({
  612. text: v.name,
  613. value: v.id,
  614. key: v.value,
  615. }));
  616. if(!dataInfo.handleCategory){
  617. let handleCategory = dataInfo.handleCategoryList.find(v => v.key == 'SUPPORT');
  618. dataInfo.handleCategory = handleCategory ? handleCategory.value : undefined;
  619. }
  620. })
  621. }
  622. // 获取处理结果列表
  623. function getClosecodes(){
  624. uni.showLoading({
  625. title: "加载中",
  626. mask: true,
  627. });
  628. let postData = {
  629. "key": 'incident_closecode',
  630. "type": "list",
  631. };
  632. api_getDictionary(postData).then(res => {
  633. uni.hideLoading();
  634. res = res || [];
  635. dataInfo.closecodeList = res.map(v => ({
  636. text: v.name,
  637. value: v.id,
  638. key: v.value,
  639. }));
  640. if(!dataInfo.closecode){
  641. let closecode = dataInfo.closecodeList.find(v => v.key == '1');
  642. dataInfo.closecode = closecode ? closecode.value : undefined;
  643. }
  644. })
  645. }
  646. // 获取延期天数列表
  647. function getDeferralDays(){
  648. dataInfo.deferralDayList = generateNumberArray(1, 15).map(v => ({
  649. text: v + '天',
  650. value: v,
  651. }));
  652. dataInfo.deferralDayList.unshift({
  653. text: '0.5天',
  654. value: 0.5,
  655. })
  656. }
  657. // 获取汇总单信息
  658. function getSummaryList(){
  659. uni.showLoading({
  660. title: "加载中",
  661. mask: true,
  662. });
  663. let postData = {
  664. "incidentId": dataInfo.incidentId,
  665. };
  666. api_querySummaryDoc(postData).then(res => {
  667. uni.hideLoading();
  668. if(res.status == 200){
  669. dataInfo.summaryObj = {...{consumableList:[], workHourManagementList: []}, ...res };
  670. dataInfo.summaryId = res.summaryId;
  671. }else if(res.status == 201){
  672. // 事件第一次绑定汇总单
  673. dataInfo.summaryId = res.summaryId;
  674. }else{
  675. uni.showToast({
  676. icon: 'none',
  677. title: res.msg || '请求数据失败!'
  678. });
  679. }
  680. })
  681. }
  682. // 添加耗材
  683. function addConsumable(){
  684. uni.navigateTo({
  685. url: `/pages/consumableList/consumableList?incidentId=${dataInfo.incidentId}&summaryId=${dataInfo.summaryId}&categoryId=${dataInfo.category.id}`
  686. })
  687. }
  688. // 添加工时
  689. function addWorkHourManagement(){
  690. let hosId = dataInfo.incidentData.duty.id
  691. uni.navigateTo({
  692. url: `/pages/workHourManagementOne/workHourManagementOne?incidentId=${dataInfo.incidentId}&summaryId=${dataInfo.summaryId}&hosId=${hosId}`
  693. })
  694. }
  695. // 提交
  696. function submit(){
  697. isSubmit.value = true;
  698. if(dataInfo.tabActiveValue === 'doing' && isInSummaryOrder.value){
  699. uni.navigateTo({
  700. url: `/pages/handler/handler?incidentId=${dataInfo.incidentId}&isSummaryNext=1&type=0`,
  701. });
  702. }else if(dataInfo.tabActiveValue === 'doing' && !isInSummaryOrder.value){
  703. submitHandler();
  704. }else if(dataInfo.tabActiveValue === 'overtime'){
  705. submitOvertime();
  706. }
  707. }
  708. // 处理提交事件
  709. function handlerOrder(){
  710. dataInfo.incidentData.returnBackupMachine = dataInfo.returnBackupMachine
  711. let postData = {
  712. incident: dataInfo.incidentData,
  713. solutionId:solutionId.value
  714. }
  715. postData.incident.handleDescription = dataInfo.handleDescription;
  716. postData.incident.handleCategory = {id: dataInfo.handleCategory};
  717. postData.incident.closecode = {id: dataInfo.closecode};
  718. postData.incident.category = dataInfo.category;
  719. postData.incident.synergetic = dataInfo.synergetic;
  720. return api_incidentTask(dataInfo.tabActiveValue, postData);
  721. }
  722. // 处理图片
  723. function handlerOrderImg(imgObj){
  724. return uploadFile(imgObj, 'incident', dataInfo.incidentId)
  725. }
  726. // 处理提交
  727. function submitHandler(){
  728. console.log(dataInfo);
  729. if(!dataInfo.handleDescription.trim() && HandleData.simpleness != 1){
  730. uni.showToast({
  731. icon: 'none',
  732. title: '请填写解决方案'
  733. });
  734. return;
  735. }
  736. if(newProvideBackupMachine.value==1 && dataInfo.returnBackupMachine==null){
  737. uni.showToast({
  738. icon: 'none',
  739. title: '请选择是否归还备用机'
  740. });
  741. return;
  742. }
  743. if(!dataInfo.category.id && HandleData.simpleness != 1){
  744. uni.showToast({
  745. icon: 'none',
  746. title: '请选择故障现象'
  747. });
  748. return;
  749. }
  750. if(!dataInfo.handleCategory){
  751. uni.showToast({
  752. icon: 'none',
  753. title: '请选择处理方式'
  754. });
  755. return;
  756. }
  757. if(!dataInfo.closecode && HandleData.simpleness != 1){
  758. uni.showToast({
  759. icon: 'none',
  760. title: '请选择处理结果'
  761. });
  762. return;
  763. }
  764. console.log(dataInfo.handlerImgList)
  765. // if(HandleData.simpleness==1){
  766. // dataInfo.closecode = '1'
  767. // }
  768. uni.showLoading({
  769. title: "加载中",
  770. mask: true,
  771. });
  772. if(dataInfo.handlerImgList.length){
  773. // 有图片
  774. handlerImgRef.value.upload();
  775. }else{
  776. // 没有图片
  777. let handlerOrder$ = handlerOrder();
  778. let requestList = [handlerOrder$];
  779. Promise.all(requestList).then(resList => {
  780. uni.hideLoading();
  781. console.log(resList);
  782. if(resList[0].state == 200){
  783. uni.showToast({
  784. icon: 'none',
  785. title: '处理成功',
  786. mask: true,
  787. });
  788. setTimeout(() => {
  789. uni.reLaunch({
  790. url: '/pages/incidentList/incidentList',
  791. })
  792. }, 1500)
  793. }else{
  794. uni.showToast({
  795. icon: 'none',
  796. title: resList[0].msg || '请求数据失败!'
  797. });
  798. }
  799. })
  800. }
  801. }
  802. // 延期处理提交
  803. function submitOvertime(){
  804. if(!dataInfo.repairTypeId){
  805. uni.showToast({
  806. icon: 'none',
  807. title: '请选择延期原因'
  808. });
  809. return;
  810. }
  811. if(!dataInfo.deferralRemark.trim()){
  812. uni.showToast({
  813. icon: 'none',
  814. title: '请填写延期说明'
  815. });
  816. return;
  817. }
  818. if(!dataInfo.deferralDayId){
  819. uni.showToast({
  820. icon: 'none',
  821. title: '请选择延期天数'
  822. });
  823. return;
  824. }
  825. uni.showLoading({
  826. title: "加载中",
  827. mask: true,
  828. });
  829. dataInfo.incidentData.provideBackupMachine = dataInfo.provideBackupMachine
  830. let postData = {
  831. incident: dataInfo.incidentData,
  832. }
  833. postData.incident.currentLog = {
  834. remark: dataInfo.deferralRemark,
  835. extra1: dataInfo.repairTypeId,
  836. extra2: dataInfo.deferralDayId,
  837. }
  838. api_incidentTask(dataInfo.tabActiveValue, postData).then(res => {
  839. uni.hideLoading();
  840. if(res.state == 200){
  841. uni.showToast({
  842. icon: 'none',
  843. title: '延期处理成功',
  844. mask: true,
  845. });
  846. setTimeout(() => {
  847. uni.reLaunch({
  848. url: '/pages/incidentList/incidentList',
  849. })
  850. }, 1500)
  851. }else{
  852. uni.showToast({
  853. icon: 'none',
  854. title: res.msg || '请求数据失败!'
  855. });
  856. }
  857. })
  858. }
  859. // 获取知识库数量
  860. function getIntroduceCount(categoryId){
  861. uni.showLoading({
  862. title: "加载中",
  863. mask: true,
  864. });
  865. let query = {
  866. "key": 'solution_status',
  867. "type": "list",
  868. };
  869. api_getDictionary(query).then(res=>{
  870. let typeId = res.find(v => v.value == '3');
  871. let postData = {
  872. idx: 0,
  873. sum: 9999,
  874. solution: {
  875. deleteFlag:0,
  876. hosId: loginUserStore.loginUser.user.currentHospital.id,
  877. categoryId:categoryId,
  878. status:{id:typeId.id},
  879. }
  880. }
  881. api_getSolution(postData).then(res => {
  882. uni.hideLoading();
  883. if(res.status == 200){
  884. dataInfo.introduceCount = res.totalNum
  885. }else{
  886. uni.showToast({
  887. icon: 'none',
  888. title: res.msg || '请求数据失败!'
  889. });
  890. }
  891. })
  892. })
  893. }
  894. // 获取文本内容
  895. function getHtml(html) {
  896. const tempDiv = document.createElement('div');
  897. tempDiv.innerHTML = html;
  898. return tempDiv.textContent || tempDiv.innerText || '';
  899. }
  900. // 获取是否开启汇总单、简易处理
  901. function getHosConfig(){
  902. let postData = {
  903. idx: 0,
  904. sum: 9999,
  905. hospitalConfig:{
  906. hosId: loginUserStore.loginUser.user.currentHospital.id,
  907. model: "itsm"
  908. }
  909. };
  910. getFetchDataList("simple/data", "hospitalConfig", postData)
  911. .then((res) => {
  912. if(dataInfo.isSummaryNext!=1){
  913. SummaryData.value = res.list.find(i=>i.key=='itsmSummarySheet')
  914. }
  915. HandleData.simpleness = res.list.find(i=>i.key=='itsmSimpleHandle').value
  916. HandleData.isSolution = res.list.find(i=>i.key=='itsmWriteSolution').value
  917. });
  918. }
  919. onLoad((option) => {
  920. let storeData = handlerStore.handler.data
  921. if(storeData && storeData.type=='rep'){
  922. solutionId.value = storeData.solutionId
  923. dataInfo.isSummaryNext = storeData.isSummaryNext
  924. dataInfo.incidentId = storeData.incidentId;
  925. }else{
  926. dataInfo.incidentId = option.incidentId;
  927. dataInfo.isSummaryNext = option.isSummaryNext == 1;
  928. }
  929. getHosConfig()
  930. getIncidentDetail();
  931. })
  932. </script>
  933. <style lang="scss" scoped>
  934. .handler{
  935. height: 100%;
  936. display: flex;
  937. flex-direction: column;
  938. justify-content: space-between;
  939. .head{
  940. height: 88rpx;
  941. display: flex;
  942. position: fixed;
  943. z-index: 99;
  944. width: 100%;
  945. background-color: #fff;
  946. font-size: 30rpx;
  947. .tab{
  948. flex: 1;
  949. display: flex;
  950. justify-content: center;
  951. align-items: center;
  952. border-bottom: 4rpx solid transparent;
  953. &.active{
  954. color: $uni-primary;
  955. border-color: $uni-primary;
  956. }
  957. }
  958. }
  959. .body{
  960. margin-top: 88rpx;
  961. box-sizing: border-box;
  962. flex: 1;
  963. min-height: 0;
  964. &.bg{
  965. background-color: #F7F7F7;
  966. }
  967. .summaryItem{
  968. &:first-of-type{
  969. .summaryItem_head{
  970. border-bottom: 1rpx solid #DDDDDD;
  971. }
  972. }
  973. .summary_total{
  974. padding: 20rpx 0;
  975. display: flex;
  976. justify-content: center;
  977. align-items: center;
  978. }
  979. .summaryItem_head{
  980. padding: 24rpx;
  981. font-size: 26rpx;
  982. color: #3A3A3A;
  983. }
  984. .summaryItem_body{
  985. font-size: 30rpx;
  986. background-color: #fff;
  987. .summaryItem_bodyItem{
  988. padding: 24rpx;
  989. border-bottom: 1rpx solid #DDDDDD;
  990. .summaryItem_bodyItem_top{
  991. display: flex;
  992. justify-content: space-between;
  993. align-items: center;
  994. .value{
  995. padding-left: 48rpx;
  996. flex-shrink: 0;
  997. }
  998. }
  999. .summaryItem_bodyItem_bottom{
  1000. margin-top: 24rpx;
  1001. display: flex;
  1002. justify-content: space-between;
  1003. align-items: center;
  1004. .name{
  1005. text-align: right;
  1006. flex: 1;
  1007. }
  1008. .value{
  1009. width: 240rpx;
  1010. text-align: right;
  1011. padding-left: 48rpx;
  1012. flex-shrink: 0;
  1013. }
  1014. }
  1015. }
  1016. }
  1017. .summaryItem_foot{
  1018. font-size: 30rpx;
  1019. background-color: #fff;
  1020. &.total{
  1021. margin-top: 24rpx;
  1022. }
  1023. .summaryItem_foot_total{
  1024. padding: 24rpx 0;
  1025. display: flex;
  1026. justify-content: center;
  1027. align-items: center;
  1028. }
  1029. .summaryItem_foot_add{
  1030. border-top: 1rpx solid #DDDDDD;
  1031. padding: 24rpx 0;
  1032. display: flex;
  1033. justify-content: center;
  1034. align-items: center;
  1035. .newicon-icon-test{
  1036. font-size: 30rpx;
  1037. font-weight: bold;
  1038. }
  1039. }
  1040. }
  1041. }
  1042. .form_item_column{
  1043. padding-top: 24rpx;
  1044. min-height: 86rpx;
  1045. .form_item{
  1046. padding-top: 0;
  1047. min-height: auto;
  1048. }
  1049. }
  1050. .form_item{
  1051. display: flex;
  1052. align-items: center;
  1053. padding-top: 24rpx;
  1054. min-height: 86rpx;
  1055. &.column{
  1056. height: auto;
  1057. flex-direction: column;
  1058. align-items: flex-start;
  1059. .import-rep{
  1060. padding: 5rpx 10rpx;
  1061. border-radius: 50rpx;
  1062. background: #d1fcd5;
  1063. color: #49b856;
  1064. font-size: 24rpx;
  1065. }
  1066. .title{
  1067. margin-right: 0;
  1068. }
  1069. .title-width{
  1070. width: 100%;
  1071. }
  1072. .title-fl-sb{
  1073. display: flex;
  1074. justify-content: space-between;
  1075. width: 100%;
  1076. }
  1077. .value{
  1078. margin-top: 10rpx;
  1079. padding-left: 20rpx;
  1080. box-sizing: border-box;
  1081. }
  1082. .tips{
  1083. padding: 24rpx;
  1084. text-align: center;
  1085. font-size: 22rpx;
  1086. color: #909399;
  1087. width: 100%;
  1088. box-sizing: border-box;
  1089. }
  1090. }
  1091. .title{
  1092. font-size: 26rpx;
  1093. display: flex;
  1094. align-items: center;
  1095. margin-right: 12rpx;
  1096. flex-shrink: 0;
  1097. &.select{
  1098. width: calc(5em + 20rpx);
  1099. }
  1100. }
  1101. .value{
  1102. width: 100%;
  1103. &.category{
  1104. width: 100%;
  1105. display: flex;
  1106. justify-content: space-between;
  1107. align-items: center;
  1108. .categoryName{
  1109. font-size: 26rpx;
  1110. color: #555;
  1111. flex: 1;
  1112. }
  1113. .newicon-weibiaoti2010104{
  1114. color: $uni-primary;
  1115. margin-left: 24rpx;
  1116. }
  1117. }
  1118. .imgTips{
  1119. color: #909399;
  1120. font-size: 22rpx;
  1121. }
  1122. }
  1123. .synergeticNames{
  1124. font-size: 26rpx;
  1125. margin-right: 24rpx;
  1126. }
  1127. .synergeticAdd{
  1128. flex-shrink: 0;
  1129. }
  1130. }
  1131. }
  1132. }
  1133. </style>