handler.vue 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185
  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">
  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. })
  248. // 处理图片
  249. const handlerImgRef = ref(null)
  250. // 是否进入汇总单
  251. const isInSummaryOrder = computed(() => {
  252. return dataInfo.tabActiveValue === 'doing' && SummaryData.value.value == 1 && (dataInfo.incidentData.handlingPersonnelUser.id == loginUserStore.loginUser.user.id);
  253. })
  254. // 上一步或者返回列表
  255. function goBackOrToList(){
  256. if(dataInfo.isSummaryNext){
  257. handlerStore.setHandlerData(dataInfo, 'assign', 'assign');
  258. goBack();
  259. }else{
  260. uni.reLaunch({
  261. url: '/pages/incidentList/incidentList'
  262. })
  263. }
  264. }
  265. // 上传处理图片成功
  266. function handlerImgSuccess(e){
  267. dataInfo.handlerImgList.forEach(v => {
  268. v.url = v.path;
  269. })
  270. console.log(dataInfo.handlerImgList);
  271. let handlerOrder$ = handlerOrder();
  272. let requestList = [handlerOrder$];
  273. dataInfo.handlerImgList.forEach(v => {
  274. let handlerOrderImg$ = handlerOrderImg(v);
  275. requestList.push(handlerOrderImg$);
  276. })
  277. Promise.all(requestList).then(resList => {
  278. uni.hideLoading();
  279. console.log(resList);
  280. if(resList[0].state == 200){
  281. uni.showToast({
  282. icon: 'none',
  283. title: '处理成功',
  284. mask: true,
  285. });
  286. setTimeout(() => {
  287. uni.reLaunch({
  288. url: '/pages/incidentList/incidentList',
  289. })
  290. }, 1500)
  291. }else{
  292. uni.showToast({
  293. icon: 'none',
  294. title: resList[0].msg || '请求数据失败!'
  295. });
  296. }
  297. })
  298. }
  299. // 上传处理图片失败
  300. function handlerImgFail(e){
  301. dataInfo.handlerImgList.forEach(v => {
  302. v.url = v.path;
  303. })
  304. console.log(dataInfo.handlerImgList);
  305. }
  306. // 选择上传图片
  307. function handlerImgSelect(e){
  308. dataInfo.handlerImgList = dataInfo.handlerImgList.concat(e.tempFiles);
  309. console.log(dataInfo.handlerImgList);
  310. }
  311. // 删除上传图片
  312. function handlerImgDelete(e){
  313. dataInfo.handlerImgList = dataInfo.handlerImgList.filter(v => e.tempFile.uuid != v.uuid);
  314. console.log(dataInfo.handlerImgList);
  315. }
  316. // 添加协同人员
  317. function synergeticAdd(){
  318. handlerStore.setHandlerData(dataInfo, 'handler');
  319. uni.navigateTo({
  320. url: `/pages/synergeticAdd/synergeticAdd?incidentId=${dataInfo.incidentId}`
  321. })
  322. }
  323. // 引入知识库
  324. function importRep(type){
  325. dataInfo.operateType = type
  326. handlerStore.setHandlerData(dataInfo, 'assign', 'assign');
  327. uni.navigateTo({
  328. url: `/pages/repository/repository`
  329. })
  330. }
  331. // 选择故障现象
  332. function selectCategory(){
  333. handlerStore.setHandlerData(dataInfo, 'handler');
  334. uni.navigateTo({
  335. url: `/pages/categoryOne/categoryOne?incidentId=${dataInfo.incidentId}`
  336. })
  337. }
  338. // 点击修改数量
  339. function numberClick(data, type){
  340. if(type === 'editConsumable'){
  341. dataInfo.evtNumber = data.consumablesNum;
  342. }else if(type === 'editWorkHourManagement'){
  343. dataInfo.evtNumber = data.workHourNum2;
  344. }
  345. dataInfo.isNumber = true;
  346. dataInfo.selectData = data;
  347. dataInfo.selectType = type;
  348. }
  349. // 确认修改数量
  350. function conformNumber(evtNumber){
  351. dataInfo.evtNumber = evtNumber;
  352. dataInfo.isNumber = false;
  353. addSummaryDoc();
  354. }
  355. // 移除数量
  356. function removeNumber(evtNumber){
  357. dataInfo.evtNumber = evtNumber;
  358. dataInfo.isNumber = false;
  359. removeSummaryDoc();
  360. }
  361. // 关闭修改数量
  362. function cancelNumber(){
  363. dataInfo.isNumber = false;
  364. }
  365. // 修改耗材/工时
  366. function addSummaryDoc(){
  367. uni.showLoading({
  368. title: "加载中",
  369. mask: true,
  370. });
  371. let postData = {
  372. "summaryId": dataInfo.summaryId,
  373. "modifyNum": 'edit',
  374. };
  375. if(dataInfo.selectType === 'editConsumable'){
  376. postData.consumableList = [
  377. {
  378. "consumablesId": dataInfo.selectData.consumableId,
  379. "consumablesNum": dataInfo.evtNumber,
  380. }
  381. ];
  382. }else if(dataInfo.selectType === 'editWorkHourManagement'){
  383. postData.workHourManagementList = [
  384. {
  385. "workHourId": dataInfo.selectData.id,
  386. "workHourNum": dataInfo.evtNumber,
  387. }
  388. ];
  389. }
  390. api_addSummaryDoc(postData).then(res => {
  391. uni.hideLoading();
  392. if(res.status == 200){
  393. uni.showToast({
  394. icon: 'none',
  395. title: '修改数量成功',
  396. mask: true,
  397. });
  398. getSummaryList();
  399. }else{
  400. uni.showToast({
  401. icon: 'none',
  402. title: res.msg || '请求数据失败!'
  403. });
  404. }
  405. })
  406. }
  407. // 移除耗材/工时
  408. function removeSummaryDoc(){
  409. uni.showLoading({
  410. title: "加载中",
  411. mask: true,
  412. });
  413. let postData = {
  414. "summaryId": dataInfo.summaryId,
  415. "remove": 'remove',
  416. };
  417. if(dataInfo.selectType === 'editConsumable'){
  418. postData.consumableList = [
  419. {
  420. "consumablesId": dataInfo.selectData.consumableId,
  421. "consumablesNum": dataInfo.evtNumber,
  422. }
  423. ];
  424. }else if(dataInfo.selectType === 'editWorkHourManagement'){
  425. postData.workHourManagementList = [
  426. {
  427. "workHourId": dataInfo.selectData.id,
  428. "workHourNum": dataInfo.evtNumber,
  429. }
  430. ];
  431. }
  432. api_addSummaryDoc(postData).then(res => {
  433. uni.hideLoading();
  434. if(res.status == 200){
  435. uni.showToast({
  436. icon: 'none',
  437. title: '移除成功',
  438. mask: true,
  439. });
  440. getSummaryList();
  441. }else{
  442. uni.showToast({
  443. icon: 'none',
  444. title: res.msg || '请求数据失败!'
  445. });
  446. }
  447. })
  448. }
  449. // 重置
  450. function reset(){
  451. dataInfo.repairTypeList = []; //延期原因列表
  452. dataInfo.repairTypeId = undefined; //延期原因ID
  453. dataInfo.deferralDayList = []; //延期天数列表
  454. dataInfo.deferralDayId = undefined; //延期天数ID
  455. dataInfo.deferralRemark = '';//延期说明
  456. dataInfo.summaryObj = {
  457. consumableList: [],//耗材列表
  458. workHourManagementList: [],//工时列表
  459. };//汇总单信息
  460. dataInfo.summaryId = undefined;//汇总单Id
  461. dataInfo.isNumber = false;//修改数量弹窗
  462. dataInfo.evtNumber = 1;//弹窗返回的数量
  463. dataInfo.selectData = {};//选择的对象
  464. dataInfo.selectType = {};//选择的对象类型
  465. dataInfo.handleDescription = '';//解决方案
  466. solutionId.value = null;//引用知识库id
  467. dataInfo.handleCategory = undefined;//处理方式
  468. dataInfo.handleCategoryList = [];//处理方式列表
  469. dataInfo.closecode = undefined;//处理结果
  470. dataInfo.closecodeList = [];//处理结果列表
  471. dataInfo.handlerImgList = [];//处理图片列表
  472. dataInfo.category = {};//故障现象
  473. dataInfo.synergetic = [];//协同人员
  474. dataInfo.provideBackupMachine = 0
  475. dataInfo.returnBackupMachine = null
  476. }
  477. // 初始化表单
  478. function initForm(){
  479. if(dataInfo.tabActiveValue === 'doing' && isInSummaryOrder.value){
  480. getSummaryList();
  481. }else if(dataInfo.tabActiveValue === 'doing' && !isInSummaryOrder.value){
  482. getHandleCategorys();
  483. getClosecodes();
  484. }else if(dataInfo.tabActiveValue === 'overtime'){
  485. getRepairTypes();
  486. getDeferralDays();
  487. }
  488. }
  489. // 点击tab
  490. function clickTab(tabValue){
  491. if(dataInfo.tabActiveValue == tabValue){
  492. return;
  493. }
  494. dataInfo.tabActiveValue = tabValue;
  495. isSubmit.value = false;
  496. reset();
  497. dataInfo.category = dataInfo.incidentData.category || {};
  498. dataInfo.synergetic = dataInfo.incidentData.synergetic || [];
  499. newProvideBackupMachine.value = dataInfo.incidentData.provideBackupMachine
  500. initForm();
  501. }
  502. // 获取事件详情
  503. function getIncidentDetail(){
  504. uni.showLoading({
  505. title: "加载中",
  506. mask: true,
  507. });
  508. let title = null;
  509. api_incidentDetail(dataInfo.incidentId).then(res => {
  510. uni.hideLoading();
  511. if(res.status == 200){
  512. dataInfo.incidentData = res.data || {};
  513. dataInfo.summaryId = res.data.summaryId;
  514. newProvideBackupMachine.value = dataInfo.incidentData.provideBackupMachine
  515. let storeData = handlerStore.handler.data
  516. if(storeData && storeData.type!='rep'){
  517. if(dataInfo.isSummaryNext){
  518. // 汇总单-下一步
  519. dataInfo.incidentData.duty.addSummary = 0;
  520. }
  521. }
  522. // 跳转页面选择了选项并且工单ID一致
  523. if(handlerStore.handler.data && handlerStore.handler.data.incidentId == dataInfo.incidentId){
  524. if(dataInfo.handleDescription){
  525. dataInfo.handleDescription = null;
  526. }
  527. Object.assign(dataInfo, handlerStore.handler.data);
  528. getIntroduceCount(dataInfo.category.id)
  529. handlerStore.clearHandlerData();
  530. }else{
  531. handlerStore.clearHandlerData();
  532. // 初始化回显
  533. dataInfo.category = dataInfo.incidentData.category || {};
  534. dataInfo.synergetic = dataInfo.incidentData.synergetic || [];
  535. getIntroduceCount(dataInfo.category.id)
  536. let chuli = false;//故障处理权限
  537. for (let i = 0; i < loginUserStore.loginUser.menu.length; i++) {
  538. if (loginUserStore.loginUser.menu[i].link == "handle") {
  539. chuli = true
  540. }
  541. }
  542. // 故障处理
  543. if(dataInfo.incidentData.state.value == 'handler' && dataInfo.incidentData.handlingPersonnelUser && dataInfo.incidentData.handlingPersonnelUser.id == loginUserStore.loginUser.user.id && chuli){
  544. let flag = dataInfo.tabs.some(v => v.value === 'doing');
  545. !flag && dataInfo.tabs.splice(0, 0, {id: 5, name: '故障处理', value: 'doing', num: ''});
  546. }
  547. // 延期处理
  548. if(dataInfo.incidentData.state.value == 'handler' && dataInfo.incidentData.handlingPersonnelUser && dataInfo.incidentData.handlingPersonnelUser.id == loginUserStore.loginUser.user.id){
  549. let flag = dataInfo.tabs.some(v => v.value === 'overtime');
  550. !flag && dataInfo.tabs.push({id: 6, name: '延期处理', value: 'overtime', num: ''});
  551. }
  552. dataInfo.tabActiveValue = dataInfo.tabs[0].value;
  553. }
  554. initForm()
  555. }else{
  556. uni.showToast({
  557. icon: 'none',
  558. title: res.msg || '请求数据失败!'
  559. });
  560. }
  561. })
  562. }
  563. // 获取延期原因列表
  564. function getRepairTypes(){
  565. uni.showLoading({
  566. title: "加载中",
  567. mask: true,
  568. });
  569. let postData = {
  570. "key": 'repair_type',
  571. "type": "list",
  572. };
  573. api_getDictionary(postData).then(res => {
  574. uni.hideLoading();
  575. res = res || [];
  576. dataInfo.repairTypeList = res.map(v => ({
  577. text: v.name,
  578. value: v.id,
  579. }));
  580. })
  581. }
  582. // 获取处理方式列表
  583. function getHandleCategorys(){
  584. uni.showLoading({
  585. title: "加载中",
  586. mask: true,
  587. });
  588. let postData = {
  589. "key": 'incident_handle_type',
  590. "type": "list",
  591. };
  592. api_getDictionary(postData).then(res => {
  593. uni.hideLoading();
  594. res = res || [];
  595. dataInfo.handleCategoryList = res.map(v => ({
  596. text: v.name,
  597. value: v.id,
  598. key: v.value,
  599. }));
  600. if(!dataInfo.handleCategory){
  601. let handleCategory = dataInfo.handleCategoryList.find(v => v.key == 'SUPPORT');
  602. dataInfo.handleCategory = handleCategory ? handleCategory.value : undefined;
  603. }
  604. })
  605. }
  606. // 获取处理结果列表
  607. function getClosecodes(){
  608. uni.showLoading({
  609. title: "加载中",
  610. mask: true,
  611. });
  612. let postData = {
  613. "key": 'incident_closecode',
  614. "type": "list",
  615. };
  616. api_getDictionary(postData).then(res => {
  617. uni.hideLoading();
  618. res = res || [];
  619. dataInfo.closecodeList = res.map(v => ({
  620. text: v.name,
  621. value: v.id,
  622. key: v.value,
  623. }));
  624. if(!dataInfo.closecode){
  625. let closecode = dataInfo.closecodeList.find(v => v.key == '1');
  626. dataInfo.closecode = closecode ? closecode.value : undefined;
  627. }
  628. })
  629. }
  630. // 获取延期天数列表
  631. function getDeferralDays(){
  632. dataInfo.deferralDayList = generateNumberArray(1, 15).map(v => ({
  633. text: v + '天',
  634. value: v,
  635. }));
  636. dataInfo.deferralDayList.unshift({
  637. text: '0.5天',
  638. value: 0.5,
  639. })
  640. }
  641. // 获取汇总单信息
  642. function getSummaryList(){
  643. uni.showLoading({
  644. title: "加载中",
  645. mask: true,
  646. });
  647. let postData = {
  648. "incidentId": dataInfo.incidentId,
  649. };
  650. api_querySummaryDoc(postData).then(res => {
  651. uni.hideLoading();
  652. if(res.status == 200){
  653. dataInfo.summaryObj = {...{consumableList:[], workHourManagementList: []}, ...res };
  654. dataInfo.summaryId = res.summaryId;
  655. }else if(res.status == 201){
  656. // 事件第一次绑定汇总单
  657. dataInfo.summaryId = res.summaryId;
  658. }else{
  659. uni.showToast({
  660. icon: 'none',
  661. title: res.msg || '请求数据失败!'
  662. });
  663. }
  664. })
  665. }
  666. // 添加耗材
  667. function addConsumable(){
  668. uni.navigateTo({
  669. url: `/pages/consumableList/consumableList?incidentId=${dataInfo.incidentId}&summaryId=${dataInfo.summaryId}`
  670. })
  671. }
  672. // 添加工时
  673. function addWorkHourManagement(){
  674. let hosId = dataInfo.incidentData.duty.id
  675. uni.navigateTo({
  676. url: `/pages/workHourManagementOne/workHourManagementOne?incidentId=${dataInfo.incidentId}&summaryId=${dataInfo.summaryId}&hosId=${hosId}`
  677. })
  678. }
  679. // 提交
  680. function submit(){
  681. isSubmit.value = true;
  682. if(dataInfo.tabActiveValue === 'doing' && isInSummaryOrder.value){
  683. uni.navigateTo({
  684. url: `/pages/handler/handler?incidentId=${dataInfo.incidentId}&isSummaryNext=1&type=0`,
  685. });
  686. }else if(dataInfo.tabActiveValue === 'doing' && !isInSummaryOrder.value){
  687. submitHandler();
  688. }else if(dataInfo.tabActiveValue === 'overtime'){
  689. submitOvertime();
  690. }
  691. }
  692. // 处理提交事件
  693. function handlerOrder(){
  694. dataInfo.incidentData.returnBackupMachine = dataInfo.returnBackupMachine
  695. let postData = {
  696. incident: dataInfo.incidentData,
  697. solutionId:solutionId.value
  698. }
  699. postData.incident.handleDescription = dataInfo.handleDescription;
  700. postData.incident.handleCategory = {id: dataInfo.handleCategory};
  701. postData.incident.closecode = {id: dataInfo.closecode};
  702. postData.incident.category = dataInfo.category;
  703. postData.incident.synergetic = dataInfo.synergetic;
  704. return api_incidentTask(dataInfo.tabActiveValue, postData);
  705. }
  706. // 处理图片
  707. function handlerOrderImg(imgObj){
  708. return uploadFile(imgObj, 'incident', dataInfo.incidentId)
  709. }
  710. // 处理提交
  711. function submitHandler(){
  712. console.log(dataInfo);
  713. if(!dataInfo.handleDescription.trim() && HandleData.simpleness != 1){
  714. uni.showToast({
  715. icon: 'none',
  716. title: '请填写解决方案'
  717. });
  718. return;
  719. }
  720. if(newProvideBackupMachine.value==1 && dataInfo.returnBackupMachine==null){
  721. uni.showToast({
  722. icon: 'none',
  723. title: '请选择是否归还备用机'
  724. });
  725. return;
  726. }
  727. if(!dataInfo.category.id && HandleData.simpleness != 1){
  728. uni.showToast({
  729. icon: 'none',
  730. title: '请选择故障现象'
  731. });
  732. return;
  733. }
  734. if(!dataInfo.handleCategory){
  735. uni.showToast({
  736. icon: 'none',
  737. title: '请选择处理方式'
  738. });
  739. return;
  740. }
  741. if(!dataInfo.closecode && HandleData.simpleness != 1){
  742. uni.showToast({
  743. icon: 'none',
  744. title: '请选择处理结果'
  745. });
  746. return;
  747. }
  748. console.log(dataInfo.handlerImgList)
  749. if(HandleData.simpleness==1){
  750. dataInfo.closecode = '20401'
  751. }
  752. uni.showLoading({
  753. title: "加载中",
  754. mask: true,
  755. });
  756. if(dataInfo.handlerImgList.length){
  757. // 有图片
  758. handlerImgRef.value.upload();
  759. }else{
  760. // 没有图片
  761. let handlerOrder$ = handlerOrder();
  762. let requestList = [handlerOrder$];
  763. Promise.all(requestList).then(resList => {
  764. uni.hideLoading();
  765. console.log(resList);
  766. if(resList[0].state == 200){
  767. uni.showToast({
  768. icon: 'none',
  769. title: '处理成功',
  770. mask: true,
  771. });
  772. setTimeout(() => {
  773. uni.reLaunch({
  774. url: '/pages/incidentList/incidentList',
  775. })
  776. }, 1500)
  777. }else{
  778. uni.showToast({
  779. icon: 'none',
  780. title: resList[0].msg || '请求数据失败!'
  781. });
  782. }
  783. })
  784. }
  785. }
  786. // 延期处理提交
  787. function submitOvertime(){
  788. if(!dataInfo.repairTypeId){
  789. uni.showToast({
  790. icon: 'none',
  791. title: '请选择延期原因'
  792. });
  793. return;
  794. }
  795. if(!dataInfo.deferralRemark.trim()){
  796. uni.showToast({
  797. icon: 'none',
  798. title: '请填写延期说明'
  799. });
  800. return;
  801. }
  802. if(!dataInfo.deferralDayId){
  803. uni.showToast({
  804. icon: 'none',
  805. title: '请选择延期天数'
  806. });
  807. return;
  808. }
  809. uni.showLoading({
  810. title: "加载中",
  811. mask: true,
  812. });
  813. dataInfo.incidentData.provideBackupMachine = dataInfo.provideBackupMachine
  814. let postData = {
  815. incident: dataInfo.incidentData,
  816. }
  817. postData.incident.currentLog = {
  818. remark: dataInfo.deferralRemark,
  819. extra1: dataInfo.repairTypeId,
  820. extra2: dataInfo.deferralDayId,
  821. }
  822. api_incidentTask(dataInfo.tabActiveValue, postData).then(res => {
  823. uni.hideLoading();
  824. if(res.state == 200){
  825. uni.showToast({
  826. icon: 'none',
  827. title: '延期处理成功',
  828. mask: true,
  829. });
  830. setTimeout(() => {
  831. uni.reLaunch({
  832. url: '/pages/incidentList/incidentList',
  833. })
  834. }, 1500)
  835. }else{
  836. uni.showToast({
  837. icon: 'none',
  838. title: res.msg || '请求数据失败!'
  839. });
  840. }
  841. })
  842. }
  843. // 获取知识库数量
  844. function getIntroduceCount(categoryId){
  845. uni.showLoading({
  846. title: "加载中",
  847. mask: true,
  848. });
  849. let query = {
  850. "key": 'solution_status',
  851. "type": "list",
  852. };
  853. api_getDictionary(query).then(res=>{
  854. let typeId = res.find(v => v.value == '3');
  855. let postData = {
  856. idx: 0,
  857. sum: 9999,
  858. solution: {
  859. deleteFlag:0,
  860. hosId: loginUserStore.loginUser.user.currentHospital.id,
  861. categoryId:categoryId,
  862. status:{id:typeId.id},
  863. }
  864. }
  865. api_getSolution(postData).then(res => {
  866. uni.hideLoading();
  867. if(res.status == 200){
  868. dataInfo.introduceCount = res.totalNum
  869. }else{
  870. uni.showToast({
  871. icon: 'none',
  872. title: res.msg || '请求数据失败!'
  873. });
  874. }
  875. })
  876. })
  877. }
  878. // 获取文本内容
  879. function getHtml(html) {
  880. const tempDiv = document.createElement('div');
  881. tempDiv.innerHTML = html;
  882. return tempDiv.textContent || tempDiv.innerText || '';
  883. }
  884. // 获取是否开启汇总单、简易处理
  885. function getHosConfig(){
  886. let postData = {
  887. idx: 0,
  888. sum: 9999,
  889. hospitalConfig:{
  890. hosId: loginUserStore.loginUser.user.currentHospital.id,
  891. model: "itsm"
  892. }
  893. };
  894. getFetchDataList("simple/data", "hospitalConfig", postData)
  895. .then((res) => {
  896. if(dataInfo.isSummaryNext!=1){
  897. SummaryData.value = res.list.find(i=>i.key=='itsmSummarySheet')
  898. }
  899. HandleData.simpleness = res.list.find(i=>i.key=='itsmSimpleHandle').value
  900. });
  901. }
  902. onLoad((option) => {
  903. let storeData = handlerStore.handler.data
  904. if(storeData && storeData.type=='rep'){
  905. solutionId.value = storeData.solutionId
  906. dataInfo.isSummaryNext = storeData.isSummaryNext
  907. dataInfo.incidentId = storeData.incidentId;
  908. }else{
  909. dataInfo.incidentId = option.incidentId;
  910. dataInfo.isSummaryNext = option.isSummaryNext == 1;
  911. }
  912. getHosConfig()
  913. getIncidentDetail();
  914. })
  915. </script>
  916. <style lang="scss" scoped>
  917. .handler{
  918. height: 100%;
  919. display: flex;
  920. flex-direction: column;
  921. justify-content: space-between;
  922. .head{
  923. height: 88rpx;
  924. display: flex;
  925. position: fixed;
  926. z-index: 99;
  927. width: 100%;
  928. background-color: #fff;
  929. font-size: 30rpx;
  930. .tab{
  931. flex: 1;
  932. display: flex;
  933. justify-content: center;
  934. align-items: center;
  935. border-bottom: 4rpx solid transparent;
  936. &.active{
  937. color: $uni-primary;
  938. border-color: $uni-primary;
  939. }
  940. }
  941. }
  942. .body{
  943. margin-top: 88rpx;
  944. box-sizing: border-box;
  945. flex: 1;
  946. min-height: 0;
  947. &.bg{
  948. background-color: #F7F7F7;
  949. }
  950. .summaryItem{
  951. &:first-of-type{
  952. .summaryItem_head{
  953. border-bottom: 1rpx solid #DDDDDD;
  954. }
  955. }
  956. .summary_total{
  957. padding: 20rpx 0;
  958. display: flex;
  959. justify-content: center;
  960. align-items: center;
  961. }
  962. .summaryItem_head{
  963. padding: 24rpx;
  964. font-size: 26rpx;
  965. color: #3A3A3A;
  966. }
  967. .summaryItem_body{
  968. font-size: 30rpx;
  969. background-color: #fff;
  970. .summaryItem_bodyItem{
  971. padding: 24rpx;
  972. border-bottom: 1rpx solid #DDDDDD;
  973. .summaryItem_bodyItem_top{
  974. display: flex;
  975. justify-content: space-between;
  976. align-items: center;
  977. .value{
  978. padding-left: 48rpx;
  979. flex-shrink: 0;
  980. }
  981. }
  982. .summaryItem_bodyItem_bottom{
  983. margin-top: 24rpx;
  984. display: flex;
  985. justify-content: space-between;
  986. align-items: center;
  987. .name{
  988. text-align: right;
  989. flex: 1;
  990. }
  991. .value{
  992. width: 240rpx;
  993. text-align: right;
  994. padding-left: 48rpx;
  995. flex-shrink: 0;
  996. }
  997. }
  998. }
  999. }
  1000. .summaryItem_foot{
  1001. font-size: 30rpx;
  1002. background-color: #fff;
  1003. &.total{
  1004. margin-top: 24rpx;
  1005. }
  1006. .summaryItem_foot_total{
  1007. padding: 24rpx 0;
  1008. display: flex;
  1009. justify-content: center;
  1010. align-items: center;
  1011. }
  1012. .summaryItem_foot_add{
  1013. border-top: 1rpx solid #DDDDDD;
  1014. padding: 24rpx 0;
  1015. display: flex;
  1016. justify-content: center;
  1017. align-items: center;
  1018. .newicon-icon-test{
  1019. font-size: 30rpx;
  1020. font-weight: bold;
  1021. }
  1022. }
  1023. }
  1024. }
  1025. .form_item_column{
  1026. padding-top: 24rpx;
  1027. min-height: 86rpx;
  1028. .form_item{
  1029. padding-top: 0;
  1030. min-height: auto;
  1031. }
  1032. }
  1033. .form_item{
  1034. display: flex;
  1035. align-items: center;
  1036. padding-top: 24rpx;
  1037. min-height: 86rpx;
  1038. &.column{
  1039. height: auto;
  1040. flex-direction: column;
  1041. align-items: flex-start;
  1042. .import-rep{
  1043. padding: 5rpx 10rpx;
  1044. border-radius: 50rpx;
  1045. background: #d1fcd5;
  1046. color: #49b856;
  1047. font-size: 24rpx;
  1048. }
  1049. .title{
  1050. margin-right: 0;
  1051. }
  1052. .title-width{
  1053. width: 100%;
  1054. }
  1055. .title-fl-sb{
  1056. display: flex;
  1057. justify-content: space-between;
  1058. width: 100%;
  1059. }
  1060. .value{
  1061. margin-top: 10rpx;
  1062. padding-left: 20rpx;
  1063. box-sizing: border-box;
  1064. }
  1065. .tips{
  1066. padding: 24rpx;
  1067. text-align: center;
  1068. font-size: 22rpx;
  1069. color: #909399;
  1070. width: 100%;
  1071. box-sizing: border-box;
  1072. }
  1073. }
  1074. .title{
  1075. font-size: 26rpx;
  1076. display: flex;
  1077. align-items: center;
  1078. margin-right: 12rpx;
  1079. flex-shrink: 0;
  1080. &.select{
  1081. width: calc(5em + 20rpx);
  1082. }
  1083. }
  1084. .value{
  1085. width: 100%;
  1086. &.category{
  1087. width: 100%;
  1088. display: flex;
  1089. justify-content: space-between;
  1090. align-items: center;
  1091. .categoryName{
  1092. font-size: 26rpx;
  1093. color: #555;
  1094. flex: 1;
  1095. }
  1096. .newicon-weibiaoti2010104{
  1097. color: $uni-primary;
  1098. margin-left: 24rpx;
  1099. }
  1100. }
  1101. .imgTips{
  1102. color: #909399;
  1103. font-size: 22rpx;
  1104. }
  1105. }
  1106. .synergeticNames{
  1107. font-size: 26rpx;
  1108. margin-right: 24rpx;
  1109. }
  1110. .synergeticAdd{
  1111. flex-shrink: 0;
  1112. }
  1113. }
  1114. }
  1115. }
  1116. </style>