index.vue 125 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780
  1. <template>
  2. <div class="app-container">
  3. <!-- 查询条件区域 -->
  4. <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="100px" label-position="top">
  5. <el-form-item label="工单编码" prop="workOrderProjectNo" label-position="top">
  6. <el-input
  7. v-model="queryParams.workOrderProjectNo"
  8. placeholder="请输入工单编码"
  9. clearable
  10. @keyup.enter="handleQuery"
  11. />
  12. </el-form-item>
  13. <el-form-item label="风机编号" prop="pcsDeviceName" label-position="top">
  14. <el-input
  15. v-model="queryParams.pcsDeviceName"
  16. placeholder="请输入风机编号"
  17. clearable
  18. @keyup.enter="handleQuery"
  19. />
  20. </el-form-item>
  21. <!-- <el-form-item label="检修类型" prop="maintenanceType" label-position="top">-->
  22. <!-- <el-select v-model="queryParams.maintenanceType" placeholder="请选择检修类型" clearable>-->
  23. <!-- <el-option-->
  24. <!-- v-for="dict in gxt_maintenance_type"-->
  25. <!-- :key="dict.value"-->
  26. <!-- :label="dict.label"-->
  27. <!-- :value="dict.value"-->
  28. <!-- />-->
  29. <!-- </el-select>-->
  30. <!-- </el-form-item>-->
  31. <el-form-item label="维保中心" prop="gxtCenter" label-position="top">
  32. <el-select
  33. v-model="queryParams.gxtCenter"
  34. placeholder="请选择维保中心"
  35. clearable
  36. @change="handleMaintenanceCenterChange"
  37. >
  38. <el-option
  39. v-for="item in maintenanceCenterOptions"
  40. :key="item.deptId"
  41. :label="item.deptName"
  42. :value="item.deptName">
  43. </el-option>
  44. </el-select>
  45. </el-form-item>
  46. <el-form-item label="场站" prop="pcsStationName" label-position="top">
  47. <el-select
  48. v-model="queryParams.pcsStationName"
  49. placeholder="请选择场站"
  50. clearable
  51. :disabled="!queryParams.gxtCenter"
  52. >
  53. <el-option
  54. v-for="item in stationOptions"
  55. :key="item.deptId"
  56. :label="item.deptName"
  57. :value="item.deptName">
  58. </el-option>
  59. </el-select>
  60. </el-form-item>
  61. <el-form-item label="工单状态" prop="workOrderStatus" label-position="top">
  62. <el-select v-model="queryParams.workOrderStatus" placeholder="请选择工单状态" clearable>
  63. <el-option
  64. v-for="dict in gxt_work_order_status"
  65. :key="dict.value"
  66. :label="dict.label"
  67. :value="dict.value"
  68. />
  69. </el-select>
  70. </el-form-item>
  71. <el-form-item label="故障代码" prop="faultCode" label-position="top">
  72. <el-input
  73. v-model="queryParams.faultCode"
  74. placeholder="请输入故障代码"
  75. clearable
  76. @keyup.enter="handleQuery"
  77. />
  78. </el-form-item>
  79. </el-form>
  80. <div style="float: right;">
  81. <el-button icon="Refresh" @click="resetQuery">重置</el-button>
  82. <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
  83. </div>
  84. <!-- 操作按钮区域 -->
  85. <el-row :gutter="10" class="mb8">
  86. <el-col :span="1.5">
  87. <el-button
  88. type="primary"
  89. plain
  90. icon="Plus"
  91. @click="handleAdd"
  92. v-hasPermi="['gxt:repairOrder:add']"
  93. >新建工单</el-button>
  94. </el-col>
  95. <el-col :span="1.5">
  96. <el-button
  97. type="info"
  98. icon="Upload"
  99. @click="handleImport"
  100. v-hasPermi="['gxt:repairOrder:import']"
  101. >导入维修工单</el-button>
  102. </el-col>
  103. <el-col :span="1.5">
  104. <el-button
  105. type="info"
  106. icon="Upload"
  107. @click="handleImportMis"
  108. v-hasPermi="['gxt:repairOrder:importMis']"
  109. >导入MIS工单</el-button>
  110. </el-col>
  111. <el-col :span="1.5">
  112. <el-button
  113. type="warning"
  114. icon="Download"
  115. @click="handleExport"
  116. v-hasPermi="['gxt:repairOrder:export']"
  117. >导出</el-button>
  118. </el-col>
  119. <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
  120. </el-row>
  121. <!-- 工单列表 -->
  122. <el-table
  123. :key="forceKey"
  124. v-loading="loading"
  125. :data="repairOrderList"
  126. row-key="id"
  127. @selection-change="handleSelectionChange"
  128. style="width: 100%"
  129. :max-height="tableHeight"
  130. >
  131. <el-table-column type="selection" width="55" align="center" fixed />
  132. <el-table-column label="工单编码" align="center" prop="workOrderProjectNo" width="160" fixed>
  133. <template #default="scope">
  134. <el-button link type="primary" @click="handleView(scope.row)">
  135. {{ scope.row.workOrderProjectNo }}
  136. </el-button>
  137. </template>
  138. </el-table-column>
  139. <el-table-column label="风机编号" align="center" prop="pcsDeviceName" width="120" :show-overflow-tooltip="true">
  140. <template #default="scope">
  141. {{ scope.row.pcsDeviceName || '-' }}
  142. </template>
  143. </el-table-column>
  144. <!-- <el-table-column label="检修类型" align="center" prop="maintenanceType" min-width="100">-->
  145. <!-- <template #default="scope">-->
  146. <!-- <dict-tag :options="gxt_maintenance_type" :value="scope.row.maintenanceType" />-->
  147. <!-- </template>-->
  148. <!-- </el-table-column>-->
  149. <el-table-column label="工单状态" align="center" prop="workOrderStatus" min-width="100">
  150. <template #default="scope">
  151. <dict-tag :options="gxt_work_order_status" :value="scope.row.workOrderStatus" />
  152. </template>
  153. </el-table-column>
  154. <el-table-column label="维保中心" align="center" prop="gxtCenter" width="150" :show-overflow-tooltip="true">
  155. <template #default="scope">
  156. {{ scope.row.gxtCenter || '-' }}
  157. </template>
  158. </el-table-column>
  159. <el-table-column label="场站" align="center" prop="pcsStationName" width="150" :show-overflow-tooltip="true">
  160. <template #default="scope">
  161. {{ scope.row.pcsStationName || '-' }}
  162. </template>
  163. </el-table-column>
  164. <el-table-column label="品牌" align="center" prop="brand" width="120" :show-overflow-tooltip="true">
  165. <template #default="scope">
  166. {{ scope.row.brand || '-' }}
  167. </template>
  168. </el-table-column>
  169. <el-table-column label="机型" align="center" prop="model" width="120" :show-overflow-tooltip="true">
  170. <template #default="scope">
  171. {{ scope.row.model || '-' }}
  172. </template>
  173. </el-table-column>
  174. <el-table-column label="故障代码" align="center" prop="faultCode" width="120" :show-overflow-tooltip="true">
  175. <template #default="scope">
  176. {{ scope.row.faultCode || '-' }}
  177. </template>
  178. </el-table-column>
  179. <el-table-column label="发生时间" align="center" prop="occurTime" width="150" >
  180. <template #default="scope">
  181. <span>{{ scope.row.occurTime ? parseTime(scope.row.occurTime, '{y}-{m}-{d} {h}:{i}') : '-' }}</span>
  182. </template>
  183. </el-table-column>
  184. <el-table-column label="下发人" align="center" prop="assignUserName" width="100" >
  185. <template #default="scope">
  186. {{ scope.row.assignUserName || '-' }}
  187. </template>
  188. </el-table-column>
  189. <el-table-column label="下发时间" align="center" prop="assignTime" width="150">
  190. <template #default="scope">
  191. <span>{{ scope.row.assignTime ? parseTime(scope.row.assignTime, '{y}-{m}-{d} {h}:{i}') : '-' }}</span>
  192. </template>
  193. </el-table-column>
  194. <el-table-column label="接单人" align="center" prop="acceptUserName" width="100" >
  195. <template #default="scope">
  196. {{ scope.row.acceptUserName || '-' }}
  197. </template>
  198. </el-table-column>
  199. <el-table-column label="接单时间" align="center" prop="acceptTime" width="150">
  200. <template #default="scope">
  201. <span>{{ scope.row.acceptTime ? parseTime(scope.row.acceptTime, '{y}-{m}-{d} {h}:{i}') : '-' }}</span>
  202. </template>
  203. </el-table-column>
  204. <el-table-column label="工作负责人" align="center" prop="teamLeaderName" width="100" >
  205. <template #default="scope">
  206. {{ scope.row.teamLeaderName || '-' }}
  207. </template>
  208. </el-table-column>
  209. <el-table-column label="MIS工单编码" align="center" prop="misOrderNo" width="150" :show-overflow-tooltip="true">
  210. <template #default="scope">
  211. {{ scope.row.misOrderNo || '-' }}
  212. </template>
  213. </el-table-column>
  214. <el-table-column label="工作票编号" align="center" prop="workPermitNum" width="150" :show-overflow-tooltip="true">
  215. <template #default="scope">
  216. {{ scope.row.workPermitNum || '-' }}
  217. </template>
  218. </el-table-column>
  219. <el-table-column label="开始时间" align="center" prop="realStartTime" width="150">
  220. <template #default="scope">
  221. <span>{{ scope.row.realStartTime ? parseTime(scope.row.realStartTime, '{y}-{m}-{d} {h}:{i}') : '-' }}</span>
  222. </template>
  223. </el-table-column>
  224. <el-table-column label="结束时间" align="center" prop="realEndTime" width="150">
  225. <template #default="scope">
  226. <span>{{ scope.row.realEndTime ? parseTime(scope.row.realEndTime, '{y}-{m}-{d} {h}:{i}') : '-' }}</span>
  227. </template>
  228. </el-table-column>
  229. <!-- <el-table-column label="维修方式" align="center" prop="repairMethod" min-width="100">-->
  230. <!-- <template #default="scope">-->
  231. <!-- <dict-tag :options="gxt_repair_method" :value="scope.row.repairMethod" />-->
  232. <!-- </template>-->
  233. <!-- </el-table-column>-->
  234. <!-- <el-table-column label="优先级" align="center" prop="priorityType" min-width="100">
  235. <template #default="scope">
  236. <dict-tag :options="gxt_order_priority_type" :value="scope.row.priorityType" />
  237. </template>
  238. </el-table-column>-->
  239. <el-table-column label="操作" align="center" class-name="small-padding fixed-width" min-width="250" fixed="right">
  240. <template #default="scope">
  241. <!-- <el-button-->
  242. <!-- v-if="scope.row.workOrderStatus === 'to_issue'"-->
  243. <!-- type="primary"-->
  244. <!-- link-->
  245. <!-- @click="handleEdit(scope.row)"-->
  246. <!-- v-hasPermi="['gxt:repairOrder:edit']"-->
  247. <!-- ><i class="fa fa-edit"></i>编辑</el-button>-->
  248. <!-- <el-button-->
  249. <!-- v-if="scope.row.workOrderStatus === 'to_issue'"-->
  250. <!-- type="primary"-->
  251. <!-- link-->
  252. <!-- @click="handleAssign(scope.row)"-->
  253. <!-- v-hasPermi="['gxt:repairOrder:assign']"-->
  254. <!-- ><i class="fa fa-user-plus"></i>下发</el-button>-->
  255. <el-button
  256. v-if="scope.row.workOrderStatus === 'to_issue' || scope.row.workOrderStatus === 'accept_return'"
  257. type="primary"
  258. link
  259. @click="handleEdit(scope.row)"
  260. v-hasPermi="['gxt:repairOrder:edit']"
  261. ><i class="fa fa-user-plus"></i>下发</el-button>
  262. <el-button
  263. v-if="scope.row.workOrderStatus === 'assigned' || scope.row.workOrderStatus === 'return'"
  264. type="primary"
  265. link
  266. @click="handleAccept(scope.row)"
  267. v-hasPermi="['gxt:repairOrder:accept']"
  268. ><i class="fa fa-check"></i>接单</el-button>
  269. <el-button
  270. v-if="scope.row.workOrderStatus === 'assigned'"
  271. type="warning"
  272. link
  273. @click="handleRevoke(scope.row)"
  274. v-hasPermi="['gxt:repairOrder:revoke']"
  275. ><i class="fa fa-reply"></i>撤回</el-button>
  276. <el-button
  277. v-if="(scope.row.workOrderStatus === 'suspended') && (scope.row.teamLeaderId == userStore.id || userStore.roles.includes('admin'))"
  278. type="primary"
  279. link
  280. @click="handleResume(scope.row)"
  281. v-hasPermi="['gxt:repairOrder:resume']"
  282. ><i class="fa fa-play"></i>恢复</el-button>
  283. <el-button
  284. v-if="(scope.row.workOrderStatus === 'to_finish') && (scope.row.teamLeaderId == userStore.id || userStore.roles.includes('admin'))"
  285. type="danger"
  286. link
  287. @click="handleSuspend(scope.row)"
  288. v-hasPermi="['gxt:repairOrder:suspend']"
  289. ><i class="fa fa-stop"></i>挂起</el-button>
  290. <el-button
  291. v-if="scope.row.workOrderStatus === 'to_finish'&& (scope.row.teamLeaderId == userStore.id || userStore.roles.includes('admin'))"
  292. type="warning"
  293. link
  294. @click="handleReturn(scope.row)"
  295. v-hasPermi="['gxt:repairOrder:return']"
  296. ><i class="fa fa-sign-in"></i>退回</el-button> <!--结单退回,负责人退回至班长 -->
  297. <el-button
  298. v-if="scope.row.workOrderStatus === 'return'|| scope.row.workOrderStatus === 'assigned'"
  299. type="warning"
  300. link
  301. @click="handleReturn(scope.row)"
  302. v-hasPermi="['gxt:repairOrder:acceptReturn']"
  303. ><i class="fa fa-sign-in"></i>退回</el-button> <!--接单退回,班长退回至下发环节 -->
  304. <!-- <el-button
  305. v-if="scope.row.workOrderStatus === 'processing'"
  306. type="warning"
  307. link
  308. @click="handlePause(scope.row)"
  309. >暂停</el-button>-->
  310. <!-- <el-button
  311. v-if="scope.row.workOrderStatus === 'processing'"
  312. type="success"
  313. link
  314. @click="handleProcessDone(scope.row)"
  315. >结束</el-button>-->
  316. <el-button
  317. v-if="scope.row.workOrderStatus === 'to_finish' && (scope.row.teamLeaderId == userStore.id || userStore.roles.includes('admin'))"
  318. type="success"
  319. link
  320. @click="handleFinalize(scope.row, '1')"
  321. v-hasPermi="['gxt:repairOrder:finalize']"
  322. ><i class="fa fa-check"></i>结单</el-button>
  323. <el-button
  324. v-if="scope.row.workOrderStatus === 'to_finish' && (scope.row.teamLeaderId == userStore.id || userStore.roles.includes('admin'))"
  325. type="primary"
  326. link
  327. @click="handleReset(scope.row)"
  328. v-hasPermi="['gxt:repairOrder:finalize']"
  329. ><i class="fa fa-refresh"></i>复启</el-button>
  330. <el-button
  331. v-if="scope.row.workOrderStatus === 'to_approve'"
  332. type="primary"
  333. link
  334. @click="handleApprove(scope.row)"
  335. v-hasPermi="['gxt:repairOrder:approve']"
  336. ><i class="fa fa-check-circle"></i>审批</el-button>
  337. <!-- <el-button
  338. v-if="scope.row.workOrderStatus === 'paused' || scope.row.workOrderStatus === 'suspended'"
  339. type="primary"
  340. link
  341. @click="handleResume(scope.row)"
  342. >恢复</el-button>-->
  343. <!-- <el-button-->
  344. <!-- v-if="scope.row.workOrderStatus === 'completed' && !scope.row.score"-->
  345. <!-- type="warning"-->
  346. <!-- link-->
  347. <!-- @click="handleRating(scope.row)"-->
  348. <!-- v-hasPermi="['gxt:repairOrder:rating']"-->
  349. <!-- ><i class="fa fa-star"></i>评分</el-button>-->
  350. <el-button
  351. v-if="scope.row.workOrderStatus === 'completed' && scope.row.restartTime == null"
  352. type="success"
  353. link
  354. @click="handleRestart(scope.row)"
  355. v-hasPermi="['gxt:repairOrder:restart']"
  356. ><i class="fa fa-refresh"></i>复运</el-button>
  357. <el-button
  358. type="info"
  359. link
  360. @click="handleView(scope.row)"
  361. v-hasPermi="['gxt:repairOrder:query']"
  362. ><i class="fa fa-eye"></i>查看</el-button>
  363. <el-button
  364. v-if="scope.row.workOrderStatus === 'to_issue'"
  365. type="danger"
  366. link
  367. @click="handleDelete(scope.row)"
  368. v-hasPermi="['gxt:repairOrder:remove']"
  369. ><i class="fa fa-trash"></i>删除</el-button>
  370. <el-button
  371. v-if="scope.row.workOrderStatus !== 'invalid'"
  372. type="danger"
  373. link
  374. @click="handleInvalidate(scope.row)"
  375. v-hasPermi="['gxt:repairOrder:invalidate']"
  376. ><i class="fa fa-ban"></i>作废</el-button>
  377. </template>
  378. </el-table-column>
  379. </el-table>
  380. <pagination
  381. v-show="total>0"
  382. :total="total"
  383. v-model:page="queryParams.pageNum"
  384. v-model:limit="queryParams.pageSize"
  385. @pagination="getList"
  386. />
  387. <!-- 新建/编辑工单对话框 -->
  388. <el-dialog :title="dialogTitle" v-model="openDialog" width="800px" append-to-body @close="cancel">
  389. <el-form ref="repairOrderRef" :model="form" :rules="rules" label-width="120px" label-position="top">
  390. <el-row>
  391. <el-col :span="12">
  392. <el-form-item label="工单编码" prop="workOrderProjectNo" >
  393. <el-input v-model="form.workOrderProjectNo" placeholder="请输入工单编码" :disabled="!!form.id" readonly maxlength="50" show-word-limit v-chinese-limit/>
  394. </el-form-item>
  395. </el-col>
  396. <el-col :span="12">
  397. <el-form-item label="风机编号" prop="pcsDeviceName">
  398. <el-input v-model="form.pcsDeviceName" placeholder="请选择风机编号" readonly>
  399. <template #append>
  400. <el-button @click="handleSelectEquipment" icon="Search"></el-button>
  401. </template>
  402. </el-input>
  403. </el-form-item>
  404. </el-col>
  405. </el-row>
  406. <el-row>
  407. <el-col :span="12">
  408. <el-form-item label="维保中心" prop="gxtCenter">
  409. <el-input v-model="form.gxtCenter" placeholder="请选择风机编号自动填充" readonly />
  410. </el-form-item>
  411. </el-col>
  412. <el-col :span="12">
  413. <el-form-item label="场站" prop="pcsStationName">
  414. <el-input v-model="form.pcsStationName" placeholder="请选择风机编号自动填充" readonly />
  415. </el-form-item>
  416. </el-col>
  417. </el-row>
  418. <el-row>
  419. <el-col :span="12">
  420. <el-form-item label="品牌" prop="brand">
  421. <el-input v-model="form.brand" placeholder="请选择风机编号自动填充" readonly />
  422. </el-form-item>
  423. </el-col>
  424. <el-col :span="12">
  425. <el-form-item label="机型" prop="model">
  426. <el-input v-model="form.model" placeholder="请选择风机编号自动填充" readonly />
  427. </el-form-item>
  428. </el-col>
  429. </el-row>
  430. <el-row>
  431. <el-col :span="12">
  432. <el-form-item label="发生时间" prop="occurTime">
  433. <el-date-picker
  434. v-model="form.occurTime"
  435. type="datetime"
  436. format="YYYY-MM-DD HH:mm"
  437. value-format="YYYY-MM-DD HH:mm"
  438. placeholder="请选择发生时间"
  439. style="width: 100%"
  440. :disabled-date="disabledDate"
  441. :disabled-time="disabledTime"
  442. />
  443. </el-form-item>
  444. </el-col>
  445. <el-col :span="12">
  446. <el-form-item label="故障代码" prop="faultCode">
  447. <el-input
  448. v-model="form.faultCode"
  449. placeholder="请输入故障代码"
  450. maxlength="20"
  451. show-word-limit
  452. />
  453. </el-form-item>
  454. </el-col>
  455. </el-row>
  456. <el-row>
  457. <el-col :span="24">
  458. <el-form-item label="故障信息" prop="faultBarcode">
  459. <el-input
  460. v-model="form.faultBarcode"
  461. type="textarea"
  462. placeholder="请输入故障信息"
  463. maxlength="100"
  464. show-word-limit
  465. :rows="3"
  466. />
  467. </el-form-item>
  468. </el-col>
  469. </el-row>
  470. <!-- <el-row>
  471. <el-col :span="24">
  472. <el-form-item label="故障描述" prop="faultDesc">
  473. <el-input
  474. v-model="form.faultDesc"
  475. type="textarea"
  476. placeholder="请输入故障描述"
  477. maxlength="500"
  478. show-word-limit
  479. :rows="3"
  480. />
  481. </el-form-item>
  482. </el-col>
  483. </el-row>-->
  484. <!-- <el-row>
  485. <el-col :span="24">
  486. <el-form-item label="图片">
  487. <image-upload :limit="10" v-model="form.workUrl" :fileSize="5"></image-upload>
  488. </el-form-item>
  489. </el-col>
  490. </el-row> -->
  491. </el-form>
  492. <template #footer>
  493. <div class="dialog-footer">
  494. <el-button @click="cancel">取 消</el-button>
  495. <el-button type="primary" @click="submitForm" v-if="optType == 'add'">保 存</el-button>
  496. <el-button type="primary" @click="submitFormAndIssue" v-if="!form.workOrderStatus">保存并下发</el-button>
  497. <el-button type="primary" @click="submitFormAndIssue" v-if="optType == 'edit'">确认下发</el-button>
  498. </div>
  499. </template>
  500. </el-dialog>
  501. <!-- 下发对话框 -->
  502. <el-dialog title="下发" v-model="assignDialogVisible" width="800px" append-to-body @close="closeAssignDialog">
  503. <el-form ref="assignFormRef" :model="assignForm" label-width="120px" label-position="top">
  504. <el-row>
  505. <el-col :span="12">
  506. <el-form-item label="工单编码"><el-input v-model="assignForm.workOrderProjectNo" disabled /></el-form-item>
  507. </el-col>
  508. <el-col :span="12">
  509. <el-form-item label="风机编号"><el-input v-model="assignForm.pcsDeviceName" disabled /></el-form-item>
  510. </el-col>
  511. <!-- <el-col :span="12">
  512. <el-form-item label="检修类型">
  513. <dict-tag :options="gxt_maintenance_type" :value="assignForm.maintenanceType" />
  514. </el-form-item>
  515. </el-col>-->
  516. <el-col :span="12">
  517. <el-form-item label="工单状态">
  518. <el-select v-model="assignForm.workOrderStatus" style="width: 100%" disabled>
  519. <el-option
  520. v-for="dict in gxt_work_order_status"
  521. :key="dict.value"
  522. :label="dict.label"
  523. :value="dict.value"
  524. />
  525. </el-select>
  526. </el-form-item>
  527. </el-col>
  528. <el-col :span="12">
  529. <el-form-item label="维保中心"><el-input v-model="assignForm.gxtCenter" disabled /></el-form-item>
  530. </el-col>
  531. <el-col :span="12">
  532. <el-form-item label="场站"><el-input v-model="assignForm.pcsStationName" disabled /></el-form-item>
  533. </el-col>
  534. <el-col :span="12">
  535. <el-form-item label="品牌"><el-input v-model="assignForm.brand" disabled /> </el-form-item>
  536. </el-col>
  537. <el-col :span="12">
  538. <el-form-item label="故障代码"><el-input v-model="assignForm.faultCode" disabled /></el-form-item>
  539. </el-col>
  540. <el-col :span="24">
  541. <el-form-item label="故障信息">
  542. <el-input
  543. v-model="assignForm.faultBarcode"
  544. type="textarea"
  545. placeholder="请输入故障信息"
  546. maxlength="100"
  547. show-word-limit
  548. :rows="3"
  549. disabled
  550. /></el-form-item>
  551. </el-col>
  552. </el-row>
  553. <!-- <el-form-item label="关联维保工单">
  554. <el-select
  555. v-model="assignForm.relatedOrderCode"
  556. filterable
  557. remote
  558. reserve-keyword
  559. placeholder="请输入关联维保工单编码"
  560. :remote-method="searchWorkOrders"
  561. :loading="workOrderSearchLoading"
  562. @change="handleWorkOrderChange"
  563. >
  564. <el-option
  565. v-for="item in workOrderOptions"
  566. :key="item.id"
  567. :label="item.workOrderProjectNo"
  568. :value="item.workOrderProjectNo"
  569. :data-content="item.content"
  570. >
  571. <span style="float: left">{{ item.workOrderProjectNo }}</span>
  572. <span style="float: right; color: #8492a6; font-size: 13px">{{ item.content }}</span>
  573. </el-option>
  574. </el-select>
  575. </el-form-item>
  576. <el-form-item
  577. v-if="assignForm.relatedOrderCode"
  578. label="维保内容"
  579. prop="relatedOrderContent">
  580. <el-input
  581. v-model="assignForm.relatedOrderContent"
  582. type="textarea"
  583. placeholder="请输入维保内容"
  584. maxlength="500"
  585. show-word-limit
  586. :rows="3"
  587. readonly
  588. />
  589. </el-form-item>-->
  590. </el-form>
  591. <template #footer>
  592. <div class="dialog-footer">
  593. <el-button @click="closeAssignDialog">取 消</el-button>
  594. <el-button type="primary" @click="submitAssign">确认下发</el-button>
  595. </div>
  596. </template>
  597. </el-dialog>
  598. <!-- 字段选择对话框 -->
  599. <el-dialog title="选择导出字段" v-model="showExportFieldsDialog" width="600px" append-to-body>
  600. <div style="position: absolute;bottom: 65px;right: 38%;">
  601. <el-button type="primary" icon="upload" size="mini" style="width:5px;" @click="upDown('up')" /><br/>
  602. <el-button type="primary" icon="download" size="mini" style="margin-top:3px;width:5px;" @click="upDown('down')" />
  603. </div>
  604. <el-transfer
  605. v-model="exportFieldsSelected"
  606. :data="exportFieldsData"
  607. :titles="['可选字段', '导出字段']"
  608. target-order = "push"
  609. show-checkbox
  610. filterable
  611. filter-placeholder="请输入字段名称"
  612. @right-check-change="rightCheckHandler">
  613. </el-transfer>
  614. <template #footer>
  615. <div class="dialog-footer">
  616. <el-button @click="showExportFieldsDialog = false">取 消</el-button>
  617. <el-button type="primary" @click="confirmExport">确 定</el-button>
  618. </div>
  619. </template>
  620. </el-dialog>
  621. <!-- 接单对话框 -->
  622. <el-dialog title="接单" v-model="acceptDialogVisible" width="800px" append-to-body @close="closeAcceptDialog">
  623. <el-form ref="acceptFormRef" :model="acceptForm" :rules="acceptRules" label-width="120px" label-position="top">
  624. <el-row>
  625. <el-col :span="12">
  626. <el-form-item label="工单编码"><el-input v-model="acceptForm.workOrderProjectNo" disabled /></el-form-item>
  627. </el-col>
  628. <el-col :span="12">
  629. <el-form-item label="风机编号"><el-input v-model="acceptForm.pcsDeviceName" disabled /></el-form-item>
  630. </el-col>
  631. <el-col :span="12">
  632. <el-form-item label="工单状态">
  633. <el-select v-model="acceptForm.workOrderStatus" style="width: 100%" disabled>
  634. <el-option
  635. v-for="dict in gxt_work_order_status"
  636. :key="dict.value"
  637. :label="dict.label"
  638. :value="dict.value"
  639. />
  640. </el-select>
  641. </el-form-item>
  642. </el-col>
  643. <el-col :span="12">
  644. <el-form-item label="维保中心"><el-input v-model="acceptForm.gxtCenter" disabled /> </el-form-item>
  645. </el-col>
  646. <el-col :span="12">
  647. <el-form-item label="场站"><el-input v-model="acceptForm.pcsStationName" disabled /> </el-form-item>
  648. </el-col>
  649. <el-col :span="12">
  650. <el-form-item label="品牌"><el-input v-model="acceptForm.brand" disabled /> </el-form-item>
  651. </el-col>
  652. <el-col :span="12">
  653. <el-form-item label="故障代码"><el-input v-model="acceptForm.faultCode" disabled /></el-form-item>
  654. </el-col>
  655. <el-col :span="24">
  656. <el-form-item label="故障信息">
  657. <el-input
  658. v-model="acceptForm.faultBarcode"
  659. type="textarea"
  660. placeholder="请输入故障信息"
  661. maxlength="100"
  662. show-word-limit
  663. :rows="3"
  664. disabled
  665. />
  666. </el-form-item>
  667. </el-col>
  668. </el-row>
  669. <el-row>
  670. <el-col :span="12">
  671. <el-form-item label="工作负责人" prop="teamLeaderId">
  672. <!-- <el-select v-model="acceptForm.teamLeaderId" placeholder="请选择工作负责人" style="width: 100%" @change="(userId) => acceptForm.teamLeaderName = userList.find(u => u.userId === userId)?.nickName">-->
  673. <!-- <el-option-->
  674. <!-- v-for="user in userList"-->
  675. <!-- :key="user.userId"-->
  676. <!-- :label="user.nickName"-->
  677. <!-- :value="user.userId"-->
  678. <!-- />-->
  679. <!-- </el-select>-->
  680. <el-input
  681. v-model="acceptForm.teamLeaderName"
  682. placeholder="请输入工作负责人姓名或点击选择"
  683. clearable
  684. @focus="handleTeamLeaderInputFocus"
  685. @blur="handleTeamLeaderInputBlur"
  686. @input="handleTeamLeaderInput"
  687. @clear="handleTeamLeaderClear"
  688. >
  689. </el-input>
  690. <!-- 快速检索下拉框 -->
  691. <div class="quick-select-dropdown" v-show="showTeamLeaderQuickSelect && quickTeamLeaderList.length > 0">
  692. <div
  693. v-for="item in quickTeamLeaderList"
  694. :key="item.userId"
  695. class="quick-select-item"
  696. @click="handleTeamLeaderQuickSelect(item)">
  697. <span class="user-name">{{ item.nickName }}</span>
  698. <span class="user-name">{{ item.dept.deptName }}</span>
  699. </div>
  700. </div>
  701. <div class="quick-select-dropdown no-data" v-show="showTeamLeaderQuickSelect && quickTeamLeaderList.length === 0 && acceptForm.teamLeaderName && !teamLeaderLoading">
  702. <div>未找到匹配的人员</div>
  703. </div>
  704. <div class="quick-select-dropdown no-data" v-show="showTeamLeaderQuickSelect && teamLeaderLoading">
  705. <div>
  706. <i class="el-icon-loading"></i>
  707. 搜索中...
  708. </div>
  709. </div>
  710. </el-form-item>
  711. </el-col>
  712. </el-row>
  713. </el-form>
  714. <template #footer>
  715. <div class="dialog-footer">
  716. <el-button @click="closeAcceptDialog">取 消</el-button>
  717. <el-button type="primary" @click="submitAccept">确认接单</el-button>
  718. </div>
  719. </template>
  720. </el-dialog>
  721. <!-- 挂起对话框 -->
  722. <!-- <el-dialog title="申请挂起工单" v-model="suspendDialogVisible" width="800px" append-to-body @close="closeSuspendDialog">-->
  723. <!-- <el-form ref="suspendFormRef" :model="suspendForm" :rules="suspendRules" label-width="120px" label-position="top">-->
  724. <!-- <el-alert type="warning" :closable="false" title="请选择挂起原因,提交后需等待班长审批。" show-icon />-->
  725. <!-- <el-row>-->
  726. <!-- <el-col :span="12">-->
  727. <!-- <el-form-item label="工单编码">-->
  728. <!-- <el-input v-model="suspendForm.workOrderProjectNo" disabled />-->
  729. <!-- </el-form-item>-->
  730. <!-- </el-col>-->
  731. <!-- <el-col :span="12">-->
  732. <!-- <el-form-item label="风机编号">-->
  733. <!-- <el-input v-model="suspendForm.pcsDeviceName" disabled />-->
  734. <!-- </el-form-item>-->
  735. <!-- </el-col>-->
  736. <!-- <el-col :span="24" v-if="suspendForm.faultBarcode">-->
  737. <!-- <el-form-item label="故障信息">-->
  738. <!-- <el-input v-model="suspendForm.faultBarcode" type="textarea" :rows="3" disabled />-->
  739. <!-- </el-form-item>-->
  740. <!-- </el-col>-->
  741. <!--&lt;!&ndash; <el-form-item label="挂起原因" prop="suspendReason">-->
  742. <!-- <el-input-->
  743. <!-- v-model="suspendForm.suspendReason"-->
  744. <!-- type="textarea"-->
  745. <!-- placeholder="请输入挂起原因"-->
  746. <!-- maxlength="100"-->
  747. <!-- show-word-limit-->
  748. <!-- :rows="3"-->
  749. <!-- />-->
  750. <!-- </el-form-item>&ndash;&gt;-->
  751. <!-- <el-col :span="12">-->
  752. <!-- <el-form-item label="挂起原因" prop="suspendReason">-->
  753. <!-- <el-select v-model="suspendForm.suspendReason" placeholder="请选择挂起原因" style="width: 100%">-->
  754. <!-- <el-option-->
  755. <!-- v-for="dict in gxt_order_suspend_reason"-->
  756. <!-- :key="dict.value"-->
  757. <!-- :label="dict.label"-->
  758. <!-- :value="dict.value"-->
  759. <!-- />-->
  760. <!-- </el-select>-->
  761. <!-- </el-form-item>-->
  762. <!-- </el-col>-->
  763. <!-- </el-row>-->
  764. <!-- &lt;!&ndash;-->
  765. <!-- <el-form-item label="详细说明" prop="suspendDescription">-->
  766. <!-- <el-input-->
  767. <!-- v-model="suspendForm.suspendDescription"-->
  768. <!-- type="textarea"-->
  769. <!-- placeholder="请输入详细说明"-->
  770. <!-- maxlength="100"-->
  771. <!-- show-word-limit-->
  772. <!-- :rows="3"-->
  773. <!-- />-->
  774. <!-- </el-form-item>&ndash;&gt;-->
  775. <!-- </el-form>-->
  776. <!-- <template #footer>-->
  777. <!-- <div class="dialog-footer">-->
  778. <!-- <el-button @click="closeSuspendDialog">取 消</el-button>-->
  779. <!-- <el-button type="primary" @click="submitSuspend">提交申请</el-button>-->
  780. <!-- </div>-->
  781. <!-- </template>-->
  782. <!-- </el-dialog>-->
  783. <!-- 结单对话框组件 -->
  784. <FinalizeDialog
  785. v-model="finalizeDialogVisible"
  786. :data="finalizeFormData"
  787. :work-order-status-options="gxt_work_order_status"
  788. :info-entry-options="gxt_info_entry"
  789. :work-area-options="gxt_work_area"
  790. :on-submit="submitFinalizeFromParent"
  791. :list-repair-order="listRepairOrder"
  792. :list-work-person="listWorkPerson"
  793. :list-mis-info="listMisInfo"
  794. :list-user-data="listUserData"
  795. @success="handleFinalizeSuccess"
  796. @select-mis-info="handleSelectMisInfo"
  797. >
  798. <template #mis-info-select>
  799. <MisInfoSelectSingle :key="commonKey" v-model="misInfoSelectVisible" @onSelected="onMisInfoSelected" :pcsStationName="finalizeFormData.pcsStationName" :pcsDeviceName="finalizeFormData.pcsDeviceName"></MisInfoSelectSingle>
  800. </template>
  801. </FinalizeDialog>
  802. <!-- 复启对话框组件 -->
  803. <ResetDialog
  804. v-model="resetDialogVisible"
  805. :data="resetFormData"
  806. :reset-method-options="gxt_reset_method"
  807. :on-submit="submitResetFromParent"
  808. @success="handleResetSuccess"
  809. />
  810. <!-- 退回对话框 -->
  811. <ReturnDialog
  812. v-model="returnDialogVisible"
  813. :data="returnForm"
  814. :work-order-status-options="gxt_work_order_status"
  815. :return-type-options="gxt_return_type"
  816. :on-submit="submitReturnFromParent"
  817. @success="handleReturnSuccess"
  818. />
  819. <!-- 维修挂起对话框 -->
  820. <SuspendDialog
  821. v-model="suspendDialogVisible"
  822. :data="suspendForm"
  823. :suspend-reason-options="gxt_order_suspend_reason"
  824. :on-submit="submitSuspendFromParent"
  825. @success="handleSuspendSuccess"
  826. />
  827. <!-- 评分对话框 -->
  828. <el-dialog title="工单评分" v-model="ratingDialogVisible" width="800px" append-to-body @close="closeRatingDialog">
  829. <el-form ref="ratingFormRef" :model="ratingForm" :rules="ratingRules" label-width="120px" label-position="top">
  830. <el-row>
  831. <el-col :span="12">
  832. <el-form-item label="工单编码"><el-input v-model="ratingForm.workOrderProjectNo" disabled /> </el-form-item>
  833. </el-col>
  834. <el-col :span="12">
  835. <el-form-item label="风机编号"><el-input v-model="ratingForm.pcsDeviceName" disabled /> </el-form-item>
  836. </el-col>
  837. <el-col :span="12">
  838. <el-form-item label="工单状态">
  839. <el-select v-model="ratingForm.workOrderStatus" style="width: 100%" disabled>
  840. <el-option
  841. v-for="dict in gxt_work_order_status"
  842. :key="dict.value"
  843. :label="dict.label"
  844. :value="dict.value"
  845. />
  846. </el-select>
  847. </el-form-item>
  848. </el-col>
  849. <el-col :span="12">
  850. <el-form-item label="维保中心"><el-input v-model="ratingForm.gxtCenter" disabled /> </el-form-item>
  851. </el-col>
  852. <el-col :span="12">
  853. <el-form-item label="场站"><el-input v-model="ratingForm.pcsStationName" disabled /> </el-form-item>
  854. </el-col>
  855. <el-col :span="12">
  856. <el-form-item label="品牌"><el-input v-model="ratingForm.brand" disabled /> </el-form-item>
  857. </el-col>
  858. <el-col :span="12">
  859. <el-form-item label="故障代码"><el-input v-model="ratingForm.faultCode" disabled /> </el-form-item>
  860. </el-col>
  861. <el-col :span="24">
  862. <el-form-item label="故障信息">
  863. <el-input
  864. v-model="ratingForm.faultBarcode"
  865. type="textarea"
  866. placeholder="请输入故障信息"
  867. maxlength="100"
  868. show-word-limit
  869. :rows="3"
  870. disabled
  871. />
  872. </el-form-item>
  873. </el-col>
  874. <el-col :span="12">
  875. <el-form-item label="MIS工单编码">
  876. <el-input v-model="ratingForm.misOrderNo" disabled />
  877. </el-form-item>
  878. </el-col>
  879. <el-col :span="12">
  880. <el-form-item label="下发人"><el-input v-model="ratingForm.assignUserName" disabled /> </el-form-item>
  881. </el-col>
  882. <el-col :span="12">
  883. <el-form-item label="下发时间"><el-input v-model="ratingForm.assignTime" disabled /> </el-form-item>
  884. </el-col>
  885. <el-col :span="12">
  886. <el-form-item label="接单人"><el-input v-model="ratingForm.acceptUserName" disabled /> </el-form-item>
  887. </el-col>
  888. <el-col :span="12">
  889. <el-form-item label="接单时间"><el-input v-model="ratingForm.acceptTime" disabled /> </el-form-item>
  890. </el-col>
  891. <el-col :span="12">
  892. <el-form-item label="工作负责人"><el-input v-model="ratingForm.teamLeaderName" disabled /> </el-form-item>
  893. </el-col>
  894. <el-col :span="12">
  895. <el-form-item label="开始时间"><el-input v-model="ratingForm.realStartTime" disabled /> </el-form-item>
  896. </el-col>
  897. <el-col :span="12">
  898. <el-form-item label="结束时间"><el-input v-model="ratingForm.realEndTime" disabled /> </el-form-item>
  899. </el-col>
  900. <!-- <el-col :span="12">
  901. <el-form-item label="故障描述">{{ ratingForm.faultDesc || '无' }}</el-form-item>
  902. </el-col>-->
  903. <!-- <el-col :span="24">-->
  904. <!-- <el-form-item label="维修总结">-->
  905. <!-- <el-input-->
  906. <!-- v-model="ratingForm.content"-->
  907. <!-- type="textarea"-->
  908. <!-- :rows="3"-->
  909. <!-- disabled-->
  910. <!-- />-->
  911. <!-- </el-form-item>-->
  912. <!-- </el-col>-->
  913. <!-- <el-col :span="12">-->
  914. <!-- <el-form-item label="检修类型">-->
  915. <!-- <el-select v-model="ratingForm.maintenanceType" style="width: 100%" disabled>-->
  916. <!-- <el-option-->
  917. <!-- v-for="dict in gxt_maintenance_type"-->
  918. <!-- :key="dict.value"-->
  919. <!-- :label="dict.label"-->
  920. <!-- :value="dict.value"-->
  921. <!-- />-->
  922. <!-- </el-select>-->
  923. <!-- </el-form-item>-->
  924. <!-- </el-col>-->
  925. <el-col :span="12">
  926. <el-form-item label="检修人员"><el-input v-model="ratingForm.workGroupMemberName" disabled /></el-form-item>
  927. </el-col>
  928. <el-col :span="24">
  929. <el-form-item label="附件">
  930. <preview :limit="8" v-model="ratingForm.attachmentUrls" :filesize="5" disabled></preview>
  931. </el-form-item>
  932. </el-col>
  933. <el-col :span="12">
  934. <el-form-item label="评分" prop="score">
  935. <el-input-number
  936. v-model="ratingForm.score"
  937. :min="1"
  938. :max="10"
  939. controls-position="right"
  940. style="width: 100%"
  941. />
  942. </el-form-item>
  943. </el-col>
  944. <el-col :span="24">
  945. <el-form-item label="点评">
  946. <el-input
  947. v-model="ratingForm.reviewContent"
  948. type="textarea"
  949. placeholder="请输入点评"
  950. maxlength="200"
  951. show-word-limit
  952. :rows="3"
  953. />
  954. </el-form-item>
  955. </el-col>
  956. </el-row>
  957. </el-form>
  958. <template #footer>
  959. <div class="dialog-footer">
  960. <el-button @click="closeRatingDialog">取 消</el-button>
  961. <el-button type="primary" @click="submitRating">提交评分</el-button>
  962. </div>
  963. </template>
  964. </el-dialog>
  965. <!-- 开始处理对话框 -->
  966. <el-dialog title="开始工单" v-model="startDialogVisible" width="500px" append-to-body @close="closeStartDialog">
  967. <el-form label-width="120px" label-position="top">
  968. <el-row>
  969. <el-col :span="12">
  970. <el-form-item label="工单编码">
  971. {{ startForm.workOrderProjectNo }}
  972. </el-form-item>
  973. </el-col>
  974. <el-col :span="12">
  975. <el-form-item label="风机编号">
  976. {{ startForm.pcsDeviceName }}
  977. </el-form-item>
  978. </el-col>
  979. </el-row>
  980. </el-form>
  981. <template #footer>
  982. <div class="dialog-footer">
  983. <el-button @click="closeStartDialog">取 消</el-button>
  984. <el-button type="primary" @click="submitStart">确认开始</el-button>
  985. </div>
  986. </template>
  987. </el-dialog>
  988. <!-- 复运对话框 -->
  989. <el-dialog title="复运" v-model="restartDialogVisible" width="800px" append-to-body @close="closeRestartDialog">
  990. <el-alert type="info" :closable="false" style="border-color: #0ea5e9; background-color: #ecf7ff; color: #0369a1; height: 35px;">
  991. <template #default>
  992. <i class="fa fa-refresh mr-2" style="color: #0369a1;"> 请填写复运相关信息,完成工单复运。</i>
  993. </template>
  994. </el-alert>
  995. <h4 class="text-sm font-medium text-gray-800 mb-3"></h4>
  996. <el-form ref="restartFormRef" :model="restartForm" :rules="restartRules" label-width="120px" label-position="top">
  997. <el-row>
  998. <el-col :span="12">
  999. <el-form-item label="工单编码"><el-input v-model="restartForm.workOrderProjectNo" disabled /> </el-form-item>
  1000. </el-col>
  1001. <el-col :span="12">
  1002. <el-form-item label="风机编号"><el-input v-model="restartForm.pcsDeviceName" disabled /> </el-form-item>
  1003. </el-col>
  1004. <el-col :span="12">
  1005. <el-form-item label="维保中心"><el-input v-model="restartForm.gxtCenter" disabled /> </el-form-item>
  1006. </el-col>
  1007. <el-col :span="12">
  1008. <el-form-item label="场站"><el-input v-model="restartForm.pcsStationName" disabled /> </el-form-item>
  1009. </el-col>
  1010. <el-col :span="12">
  1011. <el-form-item label="品牌"><el-input v-model="restartForm.brand" disabled /> </el-form-item>
  1012. </el-col>
  1013. <el-col :span="12">
  1014. <el-form-item label="发生时间"><el-input v-model="restartForm.occurTime" disabled /> </el-form-item>
  1015. </el-col>
  1016. <el-col :span="12" v-if="restartForm.infoEntry == '1'">
  1017. <el-form-item label="MIS工单编码"><el-input v-model="restartForm.misOrderNo" disabled /> </el-form-item>
  1018. </el-col>
  1019. <el-col :span="12" v-if="restartForm.infoEntry == '2'">
  1020. <el-form-item label="工作票编号">
  1021. <el-input v-model="restartForm.workPermitNum" disabled />
  1022. </el-form-item>
  1023. </el-col>
  1024. <!-- <el-col :span="12">-->
  1025. <!-- <el-form-item label="检修类型">-->
  1026. <!-- <el-select v-model="restartForm.maintenanceType" style="width: 100%" disabled>-->
  1027. <!-- <el-option-->
  1028. <!-- v-for="dict in gxt_maintenance_type"-->
  1029. <!-- :key="dict.value"-->
  1030. <!-- :label="dict.label"-->
  1031. <!-- :value="dict.value"-->
  1032. <!-- />-->
  1033. <!-- </el-select>-->
  1034. <!-- </el-form-item>-->
  1035. <!-- </el-col>-->
  1036. <!-- <el-col :span="24">-->
  1037. <!-- <el-form-item label="维修总结">-->
  1038. <!-- <el-input-->
  1039. <!-- v-model="restartForm.content"-->
  1040. <!-- type="textarea"-->
  1041. <!-- :rows="3"-->
  1042. <!-- disabled-->
  1043. <!-- />-->
  1044. <!-- </el-form-item>-->
  1045. <!-- </el-col>-->
  1046. <!-- <el-col :span="24">-->
  1047. <!-- <el-form-item label="附件">-->
  1048. <!-- <preview :limit="8" v-model="restartForm.attachmentUrls" :filesize="5" disabled></preview>-->
  1049. <!-- </el-form-item>-->
  1050. <!-- </el-col>-->
  1051. <el-col :span="12">
  1052. <el-form-item label="恢复运行时间" prop="restartTime">
  1053. <el-date-picker
  1054. v-model="restartForm.restartTime"
  1055. type="datetime"
  1056. format="YYYY-MM-DD HH:mm"
  1057. value-format="YYYY-MM-DD HH:mm"
  1058. placeholder="请选择恢复运行时间"
  1059. style="width: 100%"
  1060. />
  1061. </el-form-item>
  1062. </el-col>
  1063. <el-col :span="12">
  1064. <el-form-item label="损失电量(kWh)" prop="lostPower">
  1065. <el-input-number
  1066. v-model="restartForm.lostPower"
  1067. placeholder="请输入损失电量"
  1068. controls-position="right"
  1069. style="width: 100%"
  1070. class="input-number-left"
  1071. :min="0"
  1072. />
  1073. </el-form-item>
  1074. </el-col>
  1075. </el-row>
  1076. </el-form>
  1077. <template #footer>
  1078. <div class="dialog-footer">
  1079. <el-button @click="closeRestartDialog">取 消</el-button>
  1080. <el-button type="primary" @click="submitRestart">确认复运</el-button>
  1081. </div>
  1082. </template>
  1083. </el-dialog>
  1084. <!-- 作废对话框 -->
  1085. <el-dialog title="作废工单" v-model="invalidateDialogVisible" width="800px" append-to-body @close="closeInvalidateDialog">
  1086. <el-alert type="warning" :closable="false" style="border-color: #f59e0b; background-color: #fffbeb; color: #92400e; height: 35px;">
  1087. <template #default>
  1088. <i class="fa fa-exclamation-triangle mr-2" style="color: #92400e;"> 作废后工单将不可恢复,请谨慎操作。</i>
  1089. </template>
  1090. </el-alert>
  1091. <el-form ref="invalidateFormRef" :model="invalidateForm" :rules="invalidateRules" label-width="120px" label-position="top">
  1092. <el-row>
  1093. <el-col :span="12">
  1094. <el-form-item label="工单编码"><el-input v-model="invalidateForm.workOrderProjectNo" disabled /></el-form-item>
  1095. </el-col>
  1096. <el-col :span="12">
  1097. <el-form-item label="风机编号"><el-input v-model="invalidateForm.pcsDeviceName" disabled /></el-form-item>
  1098. </el-col>
  1099. <el-col :span="12">
  1100. <el-form-item label="工单状态">
  1101. <el-select v-model="invalidateForm.workOrderStatus" style="width: 100%" disabled>
  1102. <el-option
  1103. v-for="dict in gxt_work_order_status"
  1104. :key="dict.value"
  1105. :label="dict.label"
  1106. :value="dict.value"
  1107. />
  1108. </el-select>
  1109. </el-form-item>
  1110. </el-col>
  1111. <el-col :span="12">
  1112. <el-form-item label="维保中心"><el-input v-model="invalidateForm.gxtCenter" disabled /> </el-form-item>
  1113. </el-col>
  1114. <el-col :span="12">
  1115. <el-form-item label="场站"><el-input v-model="invalidateForm.pcsStationName" disabled /> </el-form-item>
  1116. </el-col>
  1117. <el-col :span="12">
  1118. <el-form-item label="品牌"><el-input v-model="invalidateForm.brand" disabled /> </el-form-item>
  1119. </el-col>
  1120. <el-col :span="12">
  1121. <el-form-item label="故障代码"><el-input v-model="invalidateForm.faultCode" disabled /></el-form-item>
  1122. </el-col>
  1123. <el-col :span="24">
  1124. <el-form-item label="故障信息">
  1125. <el-input
  1126. v-model="invalidateForm.faultBarcode"
  1127. type="textarea"
  1128. placeholder="请输入故障信息"
  1129. maxlength="100"
  1130. show-word-limit
  1131. :rows="3"
  1132. disabled
  1133. />
  1134. </el-form-item>
  1135. </el-col>
  1136. <el-col :span="24">
  1137. <el-form-item label="作废原因" prop="invalidReason">
  1138. <el-input
  1139. v-model="invalidateForm.invalidReason"
  1140. type="textarea"
  1141. placeholder="请输入作废原因"
  1142. maxlength="200"
  1143. show-word-limit
  1144. :rows="4"
  1145. />
  1146. </el-form-item>
  1147. </el-col>
  1148. </el-row>
  1149. </el-form>
  1150. <template #footer>
  1151. <div class="dialog-footer">
  1152. <el-button @click="closeInvalidateDialog">取 消</el-button>
  1153. <el-button type="primary" @click="submitInvalidate">确认作废</el-button>
  1154. </div>
  1155. </template>
  1156. </el-dialog>
  1157. <!-- 审批对话框 -->
  1158. <!-- <el-dialog title="退回" v-model="returnDialogVisible" width="800px" append-to-body @close="closeReturnDialog">-->
  1159. <!-- <el-alert type="info" :closable="false" style="border-color: #a855f7; background-color: #f8f5ff; color: #6d28d9; height: 35px;">-->
  1160. <!-- <template #default>-->
  1161. <!-- <i class="fa fa-sign-in mr-2" style="color: #6d28d9;"> 请选择退回类型,填写退回原因,完成工单退回。</i>-->
  1162. <!-- </template>-->
  1163. <!-- </el-alert>-->
  1164. <!-- &lt;!&ndash; 工单信息 &ndash;&gt;-->
  1165. <!-- <h3 class="text-sm font-medium text-gray-800 mb-3"></h3>-->
  1166. <!-- <el-form ref="returnFormRef" :model="returnForm" :rules="returnRules" label-width="120px" label-position="top">-->
  1167. <!-- <el-row>-->
  1168. <!-- <el-col :span="12">-->
  1169. <!-- <el-form-item label="工单编码"><el-input v-model="returnForm.workOrderProjectNo" disabled /></el-form-item>-->
  1170. <!-- </el-col>-->
  1171. <!-- <el-col :span="12">-->
  1172. <!-- <el-form-item label="风机编号"><el-input v-model="returnForm.pcsDeviceName" disabled /> </el-form-item>-->
  1173. <!-- </el-col>-->
  1174. <!-- <el-col :span="12">-->
  1175. <!-- <el-form-item label="工单状态">-->
  1176. <!-- <el-select v-model="returnForm.workOrderStatus" style="width: 100%" disabled>-->
  1177. <!-- <el-option-->
  1178. <!-- v-for="dict in gxt_work_order_status"-->
  1179. <!-- :key="dict.value"-->
  1180. <!-- :label="dict.label"-->
  1181. <!-- :value="dict.value"-->
  1182. <!-- />-->
  1183. <!-- </el-select>-->
  1184. <!-- </el-form-item>-->
  1185. <!-- </el-col>-->
  1186. <!-- <el-col :span="12">-->
  1187. <!-- <el-form-item label="维保中心"><el-input v-model="returnForm.gxtCenter" disabled /> </el-form-item>-->
  1188. <!-- </el-col>-->
  1189. <!-- <el-col :span="12">-->
  1190. <!-- <el-form-item label="场站"><el-input v-model="returnForm.pcsStationName" disabled /> </el-form-item>-->
  1191. <!-- </el-col>-->
  1192. <!-- <el-col :span="12">-->
  1193. <!-- <el-form-item label="品牌"><el-input v-model="returnForm.brand" disabled /> </el-form-item>-->
  1194. <!-- </el-col>-->
  1195. <!-- <el-col :span="12">-->
  1196. <!-- <el-form-item label="工作负责人"><el-input v-model="returnForm.teamLeaderName" disabled /> </el-form-item>-->
  1197. <!-- </el-col>-->
  1198. <!-- <el-col :span="12">-->
  1199. <!-- <el-form-item label="退回类型" prop="returnType">-->
  1200. <!-- <el-select v-model="returnForm.returnType" style="width: 100%" :disabled="returnForm.workOrderStatus === 'return'">-->
  1201. <!-- <el-option-->
  1202. <!-- v-for="dict in gxt_return_type"-->
  1203. <!-- :key="dict.value"-->
  1204. <!-- :label="dict.label"-->
  1205. <!-- :value="dict.value"-->
  1206. <!-- />-->
  1207. <!-- </el-select>-->
  1208. <!-- </el-form-item>-->
  1209. <!-- </el-col>-->
  1210. <!-- </el-row>-->
  1211. <!-- &lt;!&ndash; <el-form-item label="审批决定" prop="approvalStatus">-->
  1212. <!-- <el-radio-group v-model="returnForm.approvalStatus" @change="toggleRejectionReason">-->
  1213. <!-- <el-radio label="approved">通过</el-radio>-->
  1214. <!-- <el-radio label="rejected">驳回</el-radio>-->
  1215. <!-- </el-radio-group>-->
  1216. <!-- </el-form-item>&ndash;&gt;-->
  1217. <!-- <el-form-item label="退回原因" prop="returnReason">-->
  1218. <!-- <el-input-->
  1219. <!-- v-model="returnForm.returnReason"-->
  1220. <!-- type="textarea"-->
  1221. <!-- placeholder="请输入退回原因"-->
  1222. <!-- maxlength="100"-->
  1223. <!-- show-word-limit-->
  1224. <!-- :rows="3"-->
  1225. <!-- :disabled="returnForm.workOrderStatus === 'return'"-->
  1226. <!-- />-->
  1227. <!-- </el-form-item>-->
  1228. <!-- </el-form>-->
  1229. <!-- <template #footer>-->
  1230. <!-- <div class="dialog-footer">-->
  1231. <!-- <el-button @click="closeReturnDialog">取 消</el-button>-->
  1232. <!-- <el-button type="primary" @click="submitReturn()">退 回</el-button>-->
  1233. <!-- </div>-->
  1234. <!-- </template>-->
  1235. <!-- </el-dialog>-->
  1236. <!-- 查看工单详情对话框 -->
  1237. <ViewDialog
  1238. v-model="viewDialogVisible"
  1239. :data="viewForm"
  1240. :work-order-status-options="gxt_work_order_status"
  1241. :reset-method-options="gxt_reset_method"
  1242. :repair-order-flow-action-type-options="gxt_repair_order_flow_action_type"
  1243. />
  1244. <!-- 审批对话框组件 -->
  1245. <ApproveDialog
  1246. v-model="approveDialogVisible"
  1247. :data="approveForm"
  1248. :work-order-status-options="gxt_work_order_status"
  1249. :suspend-reason-options="gxt_order_suspend_reason"
  1250. :on-submit="submitApproveFromParent"
  1251. @success="handleApproveSuccess"
  1252. />
  1253. <!-- MIS工单导入对话框 --> <el-dialog :title="uploadMis.title" v-model="uploadMis.open" width="400px" append-to-body>
  1254. <el-upload ref="uploadMisRef" :limit="1" accept=".xlsx, .xls" :headers="uploadMis.headers" :action="uploadMis.url + '?updateSupport=' + uploadMis.updateSupport" :disabled="uploadMis.isUploading" :on-progress="handleFileUploadProgressMis" :on-success="handleFileSuccessMis" :on-change="handleFileChangeMis" :on-remove="handleFileRemoveMis" :auto-upload="false" drag>
  1255. <el-icon class="el-icon--upload"><upload-filled /></el-icon>
  1256. <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
  1257. <template #tip>
  1258. <div class="el-upload__tip text-center">
  1259. <!-- <div class="el-upload__tip">
  1260. <el-checkbox v-model="upload.updateSupport" />是否更新已经存在的工单数据
  1261. </div>-->
  1262. <span>仅允许导入xls、xlsx格式文件。</span>
  1263. <el-link type="primary" :underline="false" style="font-size: 12px; vertical-align: baseline" @click="importTemplateMis">下载模板</el-link>
  1264. </div>
  1265. </template>
  1266. </el-upload>
  1267. <template #footer>
  1268. <div class="dialog-footer">
  1269. <el-button type="primary" @click="submitFileFormMis">确 定</el-button>
  1270. <el-button @click="uploadMis.open = false">取 消</el-button>
  1271. </div>
  1272. </template>
  1273. </el-dialog>
  1274. <!-- 维修工单导入对话框 -->
  1275. <el-dialog :title="upload.title" v-model="upload.open" width="400px" append-to-body>
  1276. <el-upload ref="uploadRef" :limit="1" accept=".xlsx, .xls" :headers="upload.headers" :action="upload.url + '?updateSupport=' + upload.updateSupport" :disabled="upload.isUploading" :on-progress="handleFileUploadProgress" :on-success="handleFileSuccess" :on-change="handleFileChange" :on-remove="handleFileRemove" :auto-upload="false" drag>
  1277. <el-icon class="el-icon--upload"><upload-filled /></el-icon>
  1278. <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
  1279. <template #tip>
  1280. <div class="el-upload__tip text-center">
  1281. <div class="el-upload__tip">
  1282. <el-checkbox v-model="upload.updateSupport" />是否更新已经存在的工单数据
  1283. </div>
  1284. <span>仅允许导入xls、xlsx格式文件。</span>
  1285. <el-link type="primary" :underline="false" style="font-size: 12px; vertical-align: baseline" @click="importTemplate">下载模板</el-link>
  1286. </div>
  1287. </template>
  1288. </el-upload>
  1289. <template #footer>
  1290. <div class="dialog-footer">
  1291. <el-button type="primary" @click="submitFileForm">确 定</el-button>
  1292. <el-button @click="upload.open = false">取 消</el-button>
  1293. </div>
  1294. </template>
  1295. </el-dialog>
  1296. <!-- 设备选择组件 -->
  1297. <equipment-select-single v-model="equipmentSelectVisible" @onSelected="onEquipmentSelected"></equipment-select-single>
  1298. </div>
  1299. </template>
  1300. <script setup name="RepairOrder">
  1301. import { getToken } from "@/utils/auth"
  1302. import {
  1303. listRepairOrder,
  1304. getRepairOrder,
  1305. delRepairOrder,
  1306. addRepairOrder,
  1307. updateRepairOrder,
  1308. assignRepairOrder,
  1309. acceptRepairOrder,
  1310. startRepairOrder,
  1311. pauseRepairOrder,
  1312. processDoneRepairOrder,
  1313. ratingRepairOrder,
  1314. suspendRepairOrder,
  1315. resumeRepairOrder,
  1316. approveSuspendRepairOrder,
  1317. finalizeRepairOrder,
  1318. restartRepairOrder,
  1319. getRepairOrderByMisOrderNo,
  1320. revokeRepairOrder,
  1321. invalidateRepairOrder,
  1322. returnRepairOrder,
  1323. getExportFields
  1324. } from "@/api/gxt/repairOrder";
  1325. import { listDept,getDept } from "@/api/system/dept";
  1326. import { listFaultCodes } from "@/api/gxt/faultCodes"
  1327. /*import { listGxtOrder } from "@/api/gxt/gxtOrder";*/
  1328. import {listUser, listUserData, listUserNoPermi, listLeader} from "@/api/system/user";
  1329. import EquipmentSelectSingle from "@/components/equipmentSelect/single.vue"
  1330. import { ElMessage, ElMessageBox, ElNotification, ElLoading } from 'element-plus'
  1331. import { listMaintenanceCenters, listStationsByMaintenanceCenter } from "@/api/gxt/equipment"
  1332. import preview from '@/components/FileUpload/preview.vue'
  1333. import { getConfigKey } from "@/api/system/config"
  1334. import {genCode} from "@/api/system/autocode/rule.js";
  1335. import MisInfoSelectSingle from "@/components/misInfoSelect/single.vue";
  1336. import {listMisInfo, listWorkPerson} from "@/api/gxt/misInfo.js";
  1337. import {listGxtOrder} from "@/api/gxt/gxtOrder.js";
  1338. import useUserStore from '@/store/modules/user'
  1339. import { useRoute } from 'vue-router'
  1340. import { watch } from 'vue'
  1341. import { decryptParams } from '@/utils/encrypt'
  1342. import ResetDialog from '@/components/repairOrder/reset.vue'
  1343. import FinalizeDialog from '@/components/repairOrder/finalize.vue'
  1344. import ReturnDialog from '@/components/repairOrder/return.vue'
  1345. import SuspendDialog from '@/components/repairOrder/suspend.vue'
  1346. import ViewDialog from '@/components/repairOrder/view.vue'
  1347. import ApproveDialog from '@/components/repairOrder/approve.vue'
  1348. const { proxy } = getCurrentInstance()
  1349. const { gxt_maintenance_type, gxt_work_order_status, gxt_order_priority_type,gxt_repair_order_flow_action_type,gxt_order_suspend_reason,gxt_repair_method,gxt_reset_method,gxt_return_type,gxt_info_entry,gxt_work_area } = proxy.useDict("gxt_maintenance_type", "gxt_work_order_status", "gxt_order_priority_type","gxt_repair_order_flow_action_type","gxt_order_suspend_reason","gxt_repair_method","gxt_reset_method","gxt_return_type","gxt_info_entry","gxt_work_area")
  1350. // 数据列表相关
  1351. const repairOrderList = ref([])
  1352. const openDialog = ref(false)
  1353. const viewDialogVisible = ref(false)
  1354. const loading = ref(true)
  1355. const showSearch = ref(true)
  1356. const ids = ref([])
  1357. const single = ref(true)
  1358. const multiple = ref(true)
  1359. const total = ref(0)
  1360. const dialogTitle = ref("")
  1361. const tableHeight = ref(window.innerHeight - 300)
  1362. const startDialogVisible = ref(false) // 添加开始处理对话框控制变量
  1363. const misInfoSelectVisible = ref(false)
  1364. let commonKey = 0
  1365. const optType = ref("")
  1366. // 导出字段选择相关
  1367. const showExportFieldsDialog = ref(false)
  1368. const exportFieldsSelected = ref([])
  1369. const exportFieldsData = ref([])
  1370. // 表单相关
  1371. const repairOrderRef = ref(null)
  1372. const queryRef = ref(null)
  1373. const assignFormRef = ref(null)
  1374. const acceptFormRef = ref(null)
  1375. const suspendFormRef = ref(null)
  1376. const completeFormRef = ref(null)
  1377. const ratingFormRef = ref(null)
  1378. const startFormRef = ref(null) // 添加开始处理表单引用
  1379. const restartFormRef = ref(null) // 添加复运表单引用
  1380. const invalidateFormRef = ref(null) // 添加作废表单引用
  1381. const returnFormRef = ref(null)
  1382. // 各种表单数据
  1383. const form = ref({})
  1384. const viewForm = ref({})
  1385. const assignForm = ref({})
  1386. const acceptForm = ref({
  1387. id: null,
  1388. workOrderProjectNo: null,
  1389. pcsDeviceName: null,
  1390. maintenanceType: null,
  1391. workOrderStatus: null,
  1392. gxtCenter: null,
  1393. pcsStationName: null,
  1394. brand: null,
  1395. faultCode: null,
  1396. faultDesc: null,
  1397. relatedOrderCode: null,
  1398. relatedOrderContent: null,
  1399. teamLeaderName: null,
  1400. selectedMembers: [],
  1401. repairOrderPersonList: [],
  1402. pcsStationId: null // 添加场站ID用于查询用户
  1403. })
  1404. const suspendForm = ref({})
  1405. const approveForm = ref({})
  1406. const completeForm = ref({})
  1407. const finalizeForm = ref({
  1408. repairOrderPersonList: [],
  1409. infoEntry: null,
  1410. workArea: []
  1411. })
  1412. const invalidateForm = ref({}) // 添加作废表单
  1413. const ratingForm = ref({
  1414. score: null
  1415. })
  1416. const startForm = ref({}) // 添加开始处理表单数据
  1417. const restartForm = ref({
  1418. realEndTime: null,
  1419. lostPower: null
  1420. // restartTime: '' // 必须有这个字段
  1421. }) // 添加复运表单数据
  1422. const returnForm = ref({})
  1423. // 控制结单表单中字段是否可编辑
  1424. const getMisDataConfig = ref("0") // 默认值为"0",表示可以手动输入
  1425. // 下发对话框中的维保工单搜索相关
  1426. const workOrderSearchLoading = ref(false)
  1427. const workOrderOptions = ref([])
  1428. // 文件列表
  1429. const fileList = ref([])
  1430. // 对话框显示控制
  1431. const assignDialogVisible = ref(false);
  1432. const acceptDialogVisible = ref(false);
  1433. const userList = ref([]); // 添加用户列表
  1434. const suspendDialogVisible = ref(false)
  1435. const approveDialogVisible = ref(false)
  1436. const completeDialogVisible = ref(false)
  1437. const finalizeDialogVisible = ref(false)
  1438. const invalidateDialogVisible = ref(false) // 添加作废对话框显示控制
  1439. const ratingDialogVisible = ref(false)
  1440. const equipmentSelectVisible = ref(false)
  1441. const restartDialogVisible = ref(false) // 添加复运对话框显示控制
  1442. const returnDialogVisible = ref(false)
  1443. const resetDialogVisible = ref(false) // 添加复启对话框显示控制
  1444. // 工单流转记录
  1445. const flowList = ref([])
  1446. // 维保中心和场站选项
  1447. const maintenanceCenterOptions = ref([])
  1448. const stationOptions = ref([])
  1449. // 故障代码选项
  1450. const faultCodeOptions = ref([])
  1451. // 工作负责人快速检索相关响应式数据
  1452. const showTeamLeaderQuickSelect = ref(false)
  1453. const quickTeamLeaderList = ref([])
  1454. const teamLeaderLoading = ref(false)
  1455. const teamLeaderSearchTimer = ref(null)
  1456. const allUserList = ref([]) // 存储所有设备数据用于快速检索
  1457. const lastLoadedCenterId = ref(null) // Track last loaded maintenance center ID
  1458. const forceKey = ref(0)
  1459. const userStore = useUserStore();
  1460. const disabledDate = (time) => {
  1461. return time.getTime() > Date.now();
  1462. };
  1463. const disabledStartDate = (time) => {
  1464. const getYYYYMMDD = (date) => {
  1465. const y = date.getFullYear();
  1466. const m = String(date.getMonth() + 1).padStart(2, '0');
  1467. const d = String(date.getDate()).padStart(2, '0');
  1468. return `${y}-${m}-${d}`;
  1469. };
  1470. const today = getYYYYMMDD(new Date());
  1471. let acceptDateStr = null;
  1472. const acceptStr = finalizeForm.value.acceptTime; // 脚本中用 .value
  1473. if (acceptStr) {
  1474. // 假设 acceptTime 格式是 "2025-12-09 18:01",取前面日期部分
  1475. acceptDateStr = acceptStr.split(' ')[0]; // 得到 "2025-12-09"
  1476. }
  1477. const selectedDateStr = getYYYYMMDD(time);
  1478. // 如果没有 acceptTime,只禁用未来日期
  1479. if (!acceptDateStr) {
  1480. return selectedDateStr > today;
  1481. }
  1482. // 禁用:早于 acceptDate 或 晚于今天
  1483. return selectedDateStr < acceptDateStr || selectedDateStr > today;
  1484. };
  1485. const disabledEndDate = (time) => {
  1486. const getYYYYMMDD = (date) => {
  1487. const y = date.getFullYear();
  1488. const m = String(date.getMonth() + 1).padStart(2, '0');
  1489. const d = String(date.getDate()).padStart(2, '0');
  1490. return `${y}-${m}-${d}`;
  1491. };
  1492. const today = getYYYYMMDD(new Date());
  1493. let acceptDateStr = null;
  1494. const acceptStr = finalizeForm.value.acceptTime; // 脚本中用 .value
  1495. const startStr = finalizeForm.value.realStartTime;
  1496. if (startStr) {
  1497. // 假设 acceptTime 格式是 "2025-12-09 18:01",取前面日期部分
  1498. acceptDateStr = startStr.split(' ')[0]; // 得到 "2025-12-09"
  1499. } else if(acceptStr) {
  1500. acceptDateStr = acceptStr.split(' ')[0];
  1501. }
  1502. const selectedDateStr = getYYYYMMDD(time);
  1503. // 如果没有 acceptTime,只禁用未来日期
  1504. if (!acceptDateStr) {
  1505. return selectedDateStr > today;
  1506. }
  1507. // 禁用:早于 acceptDate 或 晚于今天
  1508. return selectedDateStr < acceptDateStr || selectedDateStr > today;
  1509. };
  1510. const disabledTime = (date) => {
  1511. const now = new Date();
  1512. if (date && date.toDateString() === now.toDateString()) {
  1513. const currentHour = now.getHours();
  1514. const currentMinute = now.getMinutes();
  1515. const disabledHours = () => {
  1516. const hours = [];
  1517. for (let i = currentHour + 1; i < 24; i++) {
  1518. hours.push(i);
  1519. }
  1520. return hours;
  1521. };
  1522. const disabledMinutes = (hour) => {
  1523. if (hour === currentHour) {
  1524. const minutes = [];
  1525. for (let i = currentMinute + 1; i < 60; i++) {
  1526. minutes.push(i);
  1527. }
  1528. return minutes;
  1529. }
  1530. return [];
  1531. };
  1532. return {
  1533. disabledHours,
  1534. disabledMinutes
  1535. };
  1536. };
  1537. return {};
  1538. };
  1539. /** 过滤快速检索用户列表 */
  1540. const filterQuickUserList = (keyword) => {
  1541. debugger
  1542. if (!allUserList.value.length) {
  1543. loadQuickTeamLeaderList();
  1544. return;
  1545. }
  1546. const lowerKeyword = keyword.toLowerCase();
  1547. quickTeamLeaderList.value = allUserList.value.filter(item =>
  1548. (item.nickName && item.nickName.toLowerCase().includes(lowerKeyword))
  1549. );
  1550. }
  1551. // 工作负责人快速检索方法
  1552. /** 工作负责人输入框获取焦点 */
  1553. const handleTeamLeaderInputFocus = () => {
  1554. showTeamLeaderQuickSelect.value = true
  1555. // 如果已有输入内容,立即搜索
  1556. if (acceptForm.value.teamLeaderName && acceptForm.value.teamLeaderName.trim()) {
  1557. handleTeamLeaderInput(acceptForm.value.teamLeaderName)
  1558. } else {
  1559. // 如果没有输入内容,加载默认列表
  1560. loadQuickTeamLeaderList()
  1561. }
  1562. }
  1563. /** 工作负责人输入框失去焦点 */
  1564. const handleTeamLeaderInputBlur = () => {
  1565. // 延迟隐藏下拉框,确保点击选项能触发
  1566. setTimeout(() => {
  1567. showTeamLeaderQuickSelect.value = false
  1568. }, 200)
  1569. }
  1570. /** 工作负责人输入事件 - 实时搜索 */
  1571. const handleTeamLeaderInput = (value) => {
  1572. const searchText = value.trim()
  1573. if (!searchText) {
  1574. quickTeamLeaderList.value = []
  1575. showTeamLeaderQuickSelect.value = false
  1576. return
  1577. }
  1578. showTeamLeaderQuickSelect.value = true
  1579. // 清除之前的定时器
  1580. if (teamLeaderSearchTimer.value) {
  1581. clearTimeout(teamLeaderSearchTimer.value)
  1582. }
  1583. filterQuickUserList(searchText)
  1584. // 设置新的定时器,防抖处理(300ms)
  1585. // teamLeaderSearchTimer.value = setTimeout(() => {
  1586. // searchTeamLeaderList(searchText)
  1587. // }, 300)
  1588. }
  1589. /** 搜索工作负责人列表 */
  1590. const searchTeamLeaderList = async (keyword) => {
  1591. if (!keyword) {
  1592. quickTeamLeaderList.value = []
  1593. return
  1594. }
  1595. teamLeaderLoading.value = true
  1596. try {
  1597. const response = await listLeader({
  1598. nickName: keyword,
  1599. // 可以根据需要添加其他搜索条件
  1600. status: '0' // 只搜索启用状态的用户
  1601. })
  1602. quickTeamLeaderList.value = response.data || []
  1603. } catch (error) {
  1604. console.error('搜索工作负责人失败:', error)
  1605. proxy.$modal.msgError('搜索失败,请重试')
  1606. quickTeamLeaderList.value = []
  1607. } finally {
  1608. teamLeaderLoading.value = false
  1609. }
  1610. }
  1611. /** 加载快速检索工作负责人列表 */
  1612. const loadQuickTeamLeaderList = async () => {
  1613. // 如果已有所有用户数据,且是同一个维保中心,直接使用
  1614. if (allUserList.value.length > 0) {
  1615. quickTeamLeaderList.value = allUserList.value;
  1616. return;
  1617. }
  1618. // 记录当前维保中心ID
  1619. lastLoadedCenterId.value = acceptForm.value.gxtCenterId;
  1620. teamLeaderLoading.value = true
  1621. try {
  1622. // 加载当前部门下的用户列表
  1623. const response = await listLeader({
  1624. deptId: -1, // 通过后台配置部门
  1625. status: '0'
  1626. })
  1627. allUserList.value = response.data || []
  1628. quickTeamLeaderList.value = allUserList.value;
  1629. } catch (error) {
  1630. console.error('加载工作负责人列表失败:', error)
  1631. allUserList.value = []
  1632. } finally {
  1633. teamLeaderLoading.value = false
  1634. }
  1635. }
  1636. /** 快速选择工作负责人 */
  1637. const handleTeamLeaderQuickSelect = (item) => {
  1638. acceptForm.value.teamLeaderId = item.userId
  1639. acceptForm.value.teamLeaderName = item.nickName
  1640. showTeamLeaderQuickSelect.value = false
  1641. }
  1642. /** 清空工作负责人 */
  1643. const handleTeamLeaderClear = () => {
  1644. acceptForm.value.teamLeaderId = undefined
  1645. acceptForm.value.teamLeaderName = ''
  1646. quickTeamLeaderList.value = []
  1647. showTeamLeaderQuickSelect.value = false
  1648. }
  1649. // MIS工单快速检索相关响应式数据
  1650. const showMisNoQuickSelect = ref(false)
  1651. const quickMisNoList = ref([])
  1652. const misNoLoading = ref(false)
  1653. const misNoSearchTimer = ref(null)
  1654. // 快速检索方法
  1655. /** MIS工单编码输入框获取焦点 */
  1656. const handleMisNoInputFocus = () => {
  1657. showMisNoQuickSelect.value = true
  1658. // 如果已有输入内容,立即搜索
  1659. if (form.misNo && form.misNo.trim()) {
  1660. handleMisNoInput(form.misNo)
  1661. }
  1662. }
  1663. /** MIS工单编码输入框失去焦点 */
  1664. const handleMisNoInputBlur = () => {
  1665. // 延迟隐藏下拉框,确保点击选项能触发
  1666. setTimeout(() => {
  1667. showMisNoQuickSelect.value = false
  1668. }, 200)
  1669. }
  1670. /** MIS工单编码输入事件 - 实时搜索 */
  1671. const handleMisNoInput = (value) => {
  1672. const searchText = value.trim()
  1673. if (!searchText) {
  1674. quickMisNoList.value = []
  1675. showMisNoQuickSelect.value = false
  1676. return
  1677. }
  1678. showMisNoQuickSelect.value = true
  1679. // 清除之前的定时器
  1680. if (misNoSearchTimer.value) {
  1681. clearTimeout(misNoSearchTimer.value)
  1682. }
  1683. // 设置新的定时器,防抖处理(500ms)
  1684. misNoSearchTimer.value = setTimeout(() => {
  1685. searchMisNoList(searchText)
  1686. }, 500)
  1687. }
  1688. /** 搜索MIS工单列表 */
  1689. const searchMisNoList = async (keyword) => {
  1690. if (!keyword) {
  1691. quickMisNoList.value = []
  1692. return
  1693. }
  1694. misNoLoading.value = true
  1695. try {
  1696. const response = await listMisInfo({
  1697. pageNum: 1,
  1698. // pageSize: 10, // 只显示前10条结果
  1699. misNo: keyword,
  1700. pcsDeviceName: keyword,
  1701. pcsStationName: keyword
  1702. // 注意:这里假设后端API支持这些字段的模糊查询
  1703. // 如果后端不支持多字段同时查询,可能需要调整
  1704. })
  1705. quickMisNoList.value = response.rows || []
  1706. // 如果没有找到结果,可以尝试更宽松的搜索
  1707. if (quickMisNoList.value.length === 0 && keyword.length >= 2) {
  1708. // 可以尝试只按MIS工单编码搜索
  1709. const retryResponse = await listMisInfo({
  1710. pageNum: 1,
  1711. // pageSize: 10,
  1712. misNo: keyword
  1713. })
  1714. quickMisNoList.value = retryResponse.rows || []
  1715. }
  1716. } catch (error) {
  1717. console.error('搜索MIS工单失败:', error)
  1718. proxy.$modal.msgError('搜索失败,请重试')
  1719. quickMisNoList.value = []
  1720. } finally {
  1721. misNoLoading.value = false
  1722. }
  1723. }
  1724. /** 快速选择MIS工单 */
  1725. const handleMisNoQuickSelect = (item) => {
  1726. onMisInfoSelected(item)
  1727. showMisNoQuickSelect.value = false
  1728. }
  1729. /** 清空MIS工单编码 */
  1730. const handleMisNoClear = () => {
  1731. // 清空与MIS工单相关的字段
  1732. finalizeForm.value.misOrderNo = null
  1733. finalizeForm.value.realStartTime = null
  1734. finalizeForm.value.realEndTime = null
  1735. finalizeForm.value.repairOrderPersonList = [];
  1736. finalizeForm.value.workGroupMemberName = null
  1737. quickMisNoList.value = []
  1738. showMisNoQuickSelect.value = false
  1739. }
  1740. /** 查询故障代码列表 */
  1741. function getFaultCodeList() {
  1742. listFaultCodes({ isActive: 0 }).then(response => {
  1743. faultCodeOptions.value = response.rows;
  1744. });
  1745. }
  1746. // 查询参数
  1747. const queryParams = ref({
  1748. pageNum: 1,
  1749. pageSize: 10,
  1750. workOrderProjectNo: null,
  1751. workOrderStatus: null,
  1752. gxtCenterId: null,
  1753. gxtCenter: null,
  1754. pcsStationId: null,
  1755. pcsStationName: null,
  1756. pcsDeviceId: null,
  1757. pcsDeviceName: null,
  1758. brand: null,
  1759. model: null,
  1760. faultCode: null,
  1761. faultBarcode: null,
  1762. assignTime: null,
  1763. assignUserId: null,
  1764. assignUserName: null,
  1765. acceptTime: null,
  1766. acceptUserId: null,
  1767. acceptUserName: null,
  1768. realStartTime: null,
  1769. realEndTime: null,
  1770. teamLeaderId: null,
  1771. teamLeaderName: null,
  1772. workGroupMemberId: null,
  1773. workGroupMemberName: null,
  1774. content: null,
  1775. planHour: null,
  1776. priorityType: null,
  1777. score: null,
  1778. reviewContent: null,
  1779. maintenanceType: null,
  1780. outTimeParam: null,
  1781. })
  1782. // 表单验证规则
  1783. const rules = ref({
  1784. // workOrderProjectNo: [
  1785. // { required: true, message: "工单编码不能为空", trigger: "blur" }
  1786. // ],
  1787. pcsDeviceName: [
  1788. { required: true, message: "风机编号不能为空", trigger: "change" }
  1789. ],
  1790. /*faultCode: [
  1791. { required: true, message: "请选择故障代码", trigger: "change" }
  1792. ],*/
  1793. occurTime: [
  1794. { required: true, message: "请选择发生时间", trigger: "change" },
  1795. {
  1796. validator: (rule, value, callback) => {
  1797. if (value && new Date(value) > new Date()) {
  1798. callback(new Error('发生时间不能大于当前时间'));
  1799. } else {
  1800. callback();
  1801. }
  1802. },
  1803. trigger: 'change'
  1804. }
  1805. ],
  1806. // maintenanceType: [
  1807. // { required: true, message: "请选择检修类型", trigger: "change" }
  1808. // ],
  1809. /* priorityType: [
  1810. { required: true, message: "请选择优先级", trigger: "change" }
  1811. ],*/
  1812. faultBarcode: [
  1813. { required: true, message: "故障信息不能为空", trigger: "change" }
  1814. ],
  1815. })
  1816. // 接单表单验证规则
  1817. const acceptRules = ref({
  1818. teamLeaderId: [
  1819. { required: true, message: "请选择工作负责人", trigger: "change" }
  1820. ],
  1821. /*selectedMembers: [
  1822. { required: true, message: "请至少选择一名检修人员", trigger: "change" }
  1823. ]*/
  1824. })
  1825. // 挂起表单验证规则
  1826. const suspendRules = ref({
  1827. suspendReason: [
  1828. { required: true, message: "请选择挂起原因", trigger: "change" }
  1829. ],
  1830. /*suspendDescription: [
  1831. { required: true, message: "请输入详细说明", trigger: "blur" }
  1832. ]*/
  1833. })
  1834. // 审批表单验证规则
  1835. const approveRules = ref({
  1836. /*approvalStatus: [
  1837. { required: true, message: "请选择审批决定", trigger: "change" }
  1838. ],
  1839. rejectionReason: [
  1840. { required: true, message: "请输入驳回原因", trigger: "blur" }
  1841. ]*/
  1842. })
  1843. // 复启表单验证规则
  1844. const resetRules = ref({
  1845. resetMethod: [
  1846. { required: true, message: "请选择复位方式", trigger: "change" }
  1847. ]
  1848. })
  1849. // 结单表单验证规则
  1850. const finalizeRules = ref({
  1851. // maintenanceType: [
  1852. // { required: true, message: "请选择检修类型", trigger: "change" }
  1853. // ],
  1854. // content: [
  1855. // { required: true, message: "请输入维修总结", trigger: "blur" }
  1856. // ],
  1857. repairMethod: [
  1858. { required: true, message: "请选择维修方式", trigger: "change" }
  1859. ],
  1860. misOrderNo: [
  1861. { required: true, message: "MIS工单编码不能为空", trigger: "blur" }
  1862. ],
  1863. realStartTime: [
  1864. { required: true, message: "请选择开始时间", trigger: "change" },
  1865. {
  1866. validator: (rule, value, callback) => {
  1867. if (value && new Date(value) > new Date() && finalizeForm.value.infoEntry == '2') {
  1868. callback(new Error('开始时间不能大于当前时间'));
  1869. } else if(value && new Date(value) < new Date(finalizeForm.value.acceptTime) && finalizeForm.value.infoEntry == '2') {
  1870. callback(new Error('开始时间不能小于接单时间'));
  1871. } else {
  1872. callback();
  1873. }
  1874. },
  1875. trigger: 'change'
  1876. }
  1877. ],
  1878. realEndTime: [
  1879. { required: true, message: "请选择结束时间", trigger: "change" },
  1880. {
  1881. validator: (rule, value, callback) => {
  1882. if (value && new Date(value) > new Date() && finalizeForm.value.infoEntry == '2') {
  1883. callback(new Error('结束时间不能大于当前时间'));
  1884. } else if(value && new Date(value) < new Date(finalizeForm.value.realStartTime) && finalizeForm.value.infoEntry == '2') {
  1885. callback(new Error('结束时间不能小于开始时间'));
  1886. } else {
  1887. callback();
  1888. }
  1889. },
  1890. trigger: 'change'
  1891. }
  1892. ],
  1893. workGroupMemberName: [
  1894. { required: false, message: "请输入检修人员", trigger: "blur" },
  1895. {
  1896. validator: async (rule, value, callback) => {
  1897. // 如果值为空、关联MIS,直接通过验证
  1898. if (!value || finalizeForm.value.infoEntry == '1') {
  1899. return callback();
  1900. }
  1901. try {
  1902. // 将输入的检修人员姓名按逗号分割
  1903. const names = value.split(',').map(name => name.trim());
  1904. // 验证每个检修人员是否存在于组织架构中
  1905. for (const name of names) {
  1906. debugger
  1907. if (name.length > 0) {
  1908. const response = await listUserData({nickName: name});
  1909. if (!response.rows || response.rows.length === 0) {
  1910. return callback(new Error(`检修人员"${name}"非系统内人员,请重新输入`));
  1911. }
  1912. } else {
  1913. return callback(new Error(`请正确输入检修人员名单`));
  1914. }
  1915. }
  1916. callback();
  1917. } catch (error) {
  1918. callback(new Error('验证检修人员时发生错误'));
  1919. }
  1920. },
  1921. trigger: 'blur'
  1922. }
  1923. ],
  1924. workArea: [
  1925. { required: true, message: "请选择工作部位", trigger: "change" }
  1926. ],
  1927. workPermitNum: [
  1928. { required: true, message: "工作票编号不能为空", trigger: "blur" },
  1929. {
  1930. validator: (rule, value, callback) => {
  1931. if (finalizeForm.value.infoEntry == '2') {
  1932. if (!value) {
  1933. callback(new Error('工作票编号不能为空'))
  1934. } else if (!/^[a-zA-Z0-9_\-\.]*$/.test(value)) {
  1935. callback(new Error('仅支持英文、数字、下划线'))
  1936. } else if (value.length > 20) {
  1937. callback(new Error('不能超过20个字符'))
  1938. } else {
  1939. // 验证唯一性
  1940. if (value) {
  1941. listRepairOrder({pageNum: 1, pageSize: 10, workPermitNum: value}).then(response => {
  1942. const gxtOrders = response.rows
  1943. if (gxtOrders.length > 0) {
  1944. if (gxtOrders[0].id != finalizeForm.value.id) {
  1945. callback(new Error('工作票编号已存在!'))
  1946. } else {
  1947. callback()
  1948. }
  1949. } else {
  1950. callback()
  1951. }
  1952. })
  1953. } else {
  1954. callback()
  1955. }
  1956. }
  1957. } else {
  1958. callback()
  1959. }
  1960. },
  1961. trigger: 'blur'
  1962. }
  1963. ]
  1964. })
  1965. // 作废表单验证规则
  1966. const invalidateRules = ref({
  1967. invalidReason: [
  1968. { required: true, message: "作废原因不能为空", trigger: "blur" }
  1969. ]
  1970. })
  1971. // 评分表单验证规则
  1972. const ratingRules = ref({
  1973. score: [
  1974. { required: true, message: "请评分", trigger: "change" },
  1975. { type: "number", min: 1, max: 10, message: "评分必须在1-10之间", trigger: "change" }
  1976. ]
  1977. })
  1978. // 复运表单验证规则
  1979. const restartRules = ref({
  1980. lostPower: [
  1981. { required: true, message: "损失电量不能为空", trigger: "change" }
  1982. ],
  1983. restartTime: [
  1984. { required: true, message: "请选择恢复运行时间", trigger: "change" },
  1985. {
  1986. validator: (rule, value, callback) => {
  1987. debugger
  1988. if (value && new Date(value) > new Date()) {
  1989. callback(new Error('恢复运行时间不能大于当前时间'));
  1990. } else if(value && new Date(value) < new Date(restartForm.value.realEndTime)) {
  1991. callback(new Error('恢复运行时间不能小于结束时间'));
  1992. } else {
  1993. callback();
  1994. }
  1995. },
  1996. trigger: 'change'
  1997. }
  1998. ]
  1999. })
  2000. // 退回表单验证规则
  2001. const returnRules = ref({
  2002. returnType: [
  2003. { required: true, message: "请选择退回类型", trigger: "change" }
  2004. ],
  2005. returnReason: [
  2006. { required: true, message: "请输入退回原因", trigger: "blur" }
  2007. ]
  2008. })
  2009. // 监听窗口大小变化
  2010. function handleResize() {
  2011. tableHeight.value = window.innerHeight - 300
  2012. }
  2013. // 关闭接单对话框并重置表单
  2014. function closeAcceptDialog() {
  2015. acceptDialogVisible.value = false
  2016. acceptForm.value = {}
  2017. proxy.resetForm("acceptFormRef")
  2018. }
  2019. // 关闭下发表单对话框并重置表单
  2020. function closeAssignDialog() {
  2021. assignDialogVisible.value = false
  2022. assignForm.value = {}
  2023. proxy.resetForm("assignFormRef")
  2024. }
  2025. // 关闭挂起对话框并重置表单
  2026. function closeSuspendDialog() {
  2027. suspendDialogVisible.value = false
  2028. suspendForm.value = {}
  2029. proxy.resetForm("suspendFormRef")
  2030. }
  2031. // 关闭审批对话框并重置表单
  2032. function closeApproveDialog() {
  2033. approveDialogVisible.value = false
  2034. approveForm.value = {}
  2035. proxy.resetForm("approveFormRef")
  2036. }
  2037. // 关闭结单对话框并重置表单
  2038. function closeFinalizeDialog() {
  2039. finalizeDialogVisible.value = false
  2040. finalizeForm.value = {}
  2041. proxy.resetForm("finalizeFormRef")
  2042. }
  2043. // 关闭结束工单对话框并重置表单
  2044. function closeCompleteDialog() {
  2045. completeDialogVisible.value = false
  2046. completeForm.value = {}
  2047. proxy.resetForm("completeFormRef")
  2048. }
  2049. // 关闭评分对话框并重置表单
  2050. function closeRatingDialog() {
  2051. ratingDialogVisible.value = false
  2052. ratingForm.value = {}
  2053. proxy.resetForm("ratingFormRef")
  2054. }
  2055. // 关闭开始处理对话框并重置表单
  2056. function closeStartDialog() {
  2057. startDialogVisible.value = false
  2058. startForm.value = {}
  2059. proxy.resetForm("startFormRef")
  2060. }
  2061. // 关闭复运对话框并重置表单
  2062. function closeRestartDialog() {
  2063. restartDialogVisible.value = false
  2064. restartForm.value = {}
  2065. proxy.resetForm("restartFormRef")
  2066. }
  2067. // 关闭作废对话框并重置表单
  2068. function closeInvalidateDialog() {
  2069. invalidateDialogVisible.value = false
  2070. invalidateForm.value = {}
  2071. proxy.resetForm("invalidateFormRef")
  2072. }
  2073. // 关闭查看详情对话框并重置表单
  2074. function closeViewDialog() {
  2075. viewDialogVisible.value = false
  2076. viewForm.value = {}
  2077. flowList.value = []
  2078. }
  2079. // 关闭审批对话框并重置表单
  2080. function closeReturnDialog() {
  2081. returnDialogVisible.value = false
  2082. returnForm.value = {}
  2083. proxy.resetForm("returnFormRef")
  2084. }
  2085. // 解析路由参数的函数
  2086. function parseRouteParams(route) {
  2087. // 只有当路由参数存在时才更新,避免覆盖已有的查询条件
  2088. if (route.query.data) {
  2089. // 解密参数
  2090. const decryptedParams = decryptParams(route.query.data);
  2091. if (decryptedParams.timeOutNum !== undefined) {
  2092. queryParams.value.outTimeParam = decryptedParams.timeOutNum;
  2093. }
  2094. if (decryptedParams.workOrderStatus !== undefined) {
  2095. queryParams.value.workOrderStatus = decryptedParams.workOrderStatus;
  2096. }
  2097. if (decryptedParams.userType !== undefined) {
  2098. queryParams.value.homePageParam = decryptedParams.userType;
  2099. }
  2100. } else {
  2101. // 为了向后兼容,也支持原始的参数传递方式
  2102. if (route.query.timeOutNum !== undefined) {
  2103. queryParams.value.outTimeParam = route.query.timeOutNum;
  2104. }
  2105. if (route.query.workOrderStatus !== undefined) {
  2106. queryParams.value.workOrderStatus = route.query.workOrderStatus;
  2107. }
  2108. }
  2109. // 确保分页参数正确设置
  2110. if (!queryParams.value.pageNum) {
  2111. queryParams.value.pageNum = 1;
  2112. }
  2113. if (!queryParams.value.pageSize) {
  2114. queryParams.value.pageSize = 10;
  2115. }
  2116. }
  2117. onMounted(() => {
  2118. // 从路由参数中获取值
  2119. const route = useRoute();
  2120. parseRouteParams(route);
  2121. getList()
  2122. getMaintenanceCenterAndStationList()
  2123. getFaultCodeList()
  2124. getGetMisDataConfig() // 获取配置参数
  2125. getExportFieldsData() // 获取导出字段数据
  2126. window.addEventListener('resize', handleResize)
  2127. })
  2128. // 监听路由变化,当从其他路由跳转到当前路由时重新解析参数
  2129. const route = useRoute();
  2130. watch(() => route.query, (newQuery, oldQuery) => {
  2131. // 当路由查询参数发生变化时,重新解析参数
  2132. parseRouteParams(route);
  2133. // 重新获取列表数据
  2134. getList();
  2135. }, { deep: true });
  2136. onUnmounted(() => {
  2137. window.removeEventListener('resize', handleResize)
  2138. })
  2139. /** 获取配置参数 gxt.repairOder.getMisData */
  2140. function getGetMisDataConfig() {
  2141. getConfigKey("gxt.repairOder.getMisData").then(response => {
  2142. getMisDataConfig.value = response.msg || "0";
  2143. }).catch(error => {
  2144. console.error("获取配置参数失败:", error);
  2145. getMisDataConfig.value = "0"; // 获取失败时默认为可手动输入
  2146. });
  2147. }
  2148. /** 查询维修工单列表 */
  2149. function getList() {
  2150. loading.value = true
  2151. listRepairOrder(queryParams.value).then(response => {
  2152. console.log(response.rows);
  2153. repairOrderList.value = response.rows
  2154. total.value = response.total
  2155. loading.value = false
  2156. forceKey.value += 1
  2157. })
  2158. }
  2159. /** 查询维保中心和场站列表 */
  2160. /*function getMaintenanceCenterAndStationList() {
  2161. listDept({}).then(response => {
  2162. const depts = response.data;
  2163. // 筛选出维保中心(level=2)
  2164. maintenanceCenterOptions.value = depts.filter(dept => dept.level === "2");
  2165. // 筛选出场站(level=3)
  2166. const stations = depts.filter(dept => dept.level === "3");
  2167. // 如果已选择维保中心,则筛选出该维保中心下的场站
  2168. if (queryParams.value.gxtCenter) {
  2169. const selectedMaintenanceCenter = maintenanceCenterOptions.value.find(
  2170. center => center.deptName === queryParams.value.gxtCenter
  2171. );
  2172. if (selectedMaintenanceCenter) {
  2173. stationOptions.value = stations.filter(
  2174. station => station.ancestors.includes(selectedMaintenanceCenter.deptId)
  2175. );
  2176. } else {
  2177. stationOptions.value = [];
  2178. }
  2179. } else {
  2180. // 如果未选择维保中心,则清空场站选项
  2181. stationOptions.value = [];
  2182. }
  2183. });
  2184. }*/
  2185. function getMaintenanceCenterAndStationList() {
  2186. listMaintenanceCenters().then(response => {
  2187. maintenanceCenterOptions.value = response.data.map(item => {
  2188. return { deptName: item, deptId: item };
  2189. });
  2190. // 如果已选择维保中心,则筛选出该维保中心下的场站
  2191. if (queryParams.value.maintenanceCenter) {
  2192. listStationsByMaintenanceCenter(queryParams.value.maintenanceCenter).then(res => {
  2193. stationOptions.value = res.data.map(item => {
  2194. return { deptName: item, deptId: item };
  2195. });
  2196. });
  2197. } else {
  2198. // 如果未选择维保中心,则清空场站选项
  2199. stationOptions.value = [];
  2200. }
  2201. });
  2202. }
  2203. /** 维保中心选择变化时 */
  2204. /*function handleMaintenanceCenterChange(selectedCenter) {
  2205. // 清空场站选择
  2206. queryParams.value.pcsStationName = null;
  2207. // 如果选择了维保中心,则加载对应的场站
  2208. if (selectedCenter) {
  2209. listDept({}).then(response => {
  2210. const depts = response.data;
  2211. const stations = depts.filter(dept => dept.level === "3");
  2212. // 找到选中的维保中心
  2213. const selectedMaintenanceCenter = maintenanceCenterOptions.value.find(
  2214. center => center.deptName === selectedCenter
  2215. );
  2216. if (selectedMaintenanceCenter) {
  2217. // 筛选出该维保中心下的场站
  2218. stationOptions.value = stations.filter(
  2219. station => station.ancestors.includes(selectedMaintenanceCenter.deptId)
  2220. );
  2221. }
  2222. });
  2223. } else {
  2224. // 如果未选择维保中心,则清空场站选项
  2225. stationOptions.value = [];
  2226. }
  2227. }*/
  2228. function handleMaintenanceCenterChange(selectedCenter) {
  2229. // 清空场站选择
  2230. queryParams.value.station = null;
  2231. // 如果选择了维保中心,则加载对应的场站
  2232. if (selectedCenter) {
  2233. listStationsByMaintenanceCenter(selectedCenter).then(response => {
  2234. stationOptions.value = response.data.map(item => {
  2235. return { deptName: item, deptId: item };
  2236. });
  2237. });
  2238. } else {
  2239. // 如果未选择维保中心,则清空场站选项
  2240. stationOptions.value = [];
  2241. }
  2242. }
  2243. /**
  2244. * 根据部门ID获取部门信息,并根据level判断是否需要查找父部门
  2245. * @param {Number} deptId 部门ID
  2246. * @returns {Promise<Number>} 返回level为3的部门ID
  2247. */
  2248. function getDeptAndUserByLevel(deptId) {
  2249. return new Promise((resolve) => {
  2250. // 获取部门信息
  2251. getDeptInfoAndParent(deptId).then(dept => {
  2252. resolve(dept.deptId);
  2253. });
  2254. });
  2255. }
  2256. /**
  2257. * 递归获取部门信息,查找父部门直到level为3
  2258. * @param {Number} deptId 部门ID
  2259. * @returns {Promise<Object>} 返回level为3的部门对象
  2260. */
  2261. function getDeptInfoAndParent(deptId) {
  2262. return new Promise((resolve) => {
  2263. getDept(deptId).then(response => {
  2264. const dept = response.data;
  2265. // 如果部门level为3,直接返回
  2266. if (dept.level === "3") {
  2267. resolve(dept);
  2268. }
  2269. // 如果有祖先部门,则继续向上查找
  2270. else if (dept.ancestors) {
  2271. // 从ancestors中提取父部门ID
  2272. // ancestors格式类似 "0,100,101,102"
  2273. const ancestorIds = dept.ancestors.split(',');
  2274. if (ancestorIds.length <= 1){
  2275. resolve(dept);
  2276. }else {
  2277. const parentDeptId = ancestorIds[ancestorIds.length - 1];
  2278. // 递归获取父部门信息
  2279. getDeptInfoAndParent(parentDeptId).then(parentDept => {
  2280. resolve(parentDept);
  2281. });
  2282. }
  2283. }
  2284. // 其他情况也直接返回
  2285. else {
  2286. resolve(dept);
  2287. }
  2288. }).catch(error => {
  2289. // 如果获取部门信息失败,返回null
  2290. console.error("获取部门信息失败:", error);
  2291. resolve(null);
  2292. });
  2293. });
  2294. }
  2295. // 取消按钮
  2296. function cancel() {
  2297. openDialog.value = false
  2298. reset()
  2299. }
  2300. function resetTimeOutOrder() {
  2301. if (queryParams.value.outTimeParam != null) {
  2302. queryParams.value.outTimeParam = null;
  2303. queryParams.value.workOrderStatus = null;
  2304. queryParams.value.userType = null;
  2305. }
  2306. }
  2307. // 表单重置
  2308. function reset() {
  2309. form.value = {}
  2310. proxy.resetForm("repairOrderRef")
  2311. }
  2312. /** 搜索按钮操作 */
  2313. function handleQuery() {
  2314. queryParams.value.pageNum = 1
  2315. getList()
  2316. }
  2317. /** 打开设备选择对话框 */
  2318. function handleSelectEquipment() {
  2319. equipmentSelectVisible.value = true
  2320. }
  2321. /** 设备选择回调 */
  2322. function onEquipmentSelected(row) {
  2323. if (row) {
  2324. // 检查维保中心ID和场站ID是否存在
  2325. if (!row.maintenanceCenterId) {
  2326. proxy.$modal.msgError("该设备的维保中心没有对应的部门,请完善部门信息后再更新设备数据!");
  2327. return;
  2328. }
  2329. if (!row.stationId) {
  2330. proxy.$modal.msgError("该设备的场站没有对应的部门,请完善部门信息后再更新设备数据!");
  2331. return;
  2332. }
  2333. form.value.pcsDeviceId = row.equipmentId
  2334. form.value.pcsDeviceName = row.equipmentCode
  2335. form.value.gxtCenterId = row.maintenanceCenterId
  2336. form.value.gxtCenter = row.maintenanceCenter
  2337. form.value.pcsStationId = row.stationId
  2338. form.value.pcsStationName = row.station
  2339. form.value.brand = row.brand
  2340. form.value.model = row.model
  2341. }
  2342. equipmentSelectVisible.value = false
  2343. }
  2344. /** 重置按钮操作 */
  2345. function resetQuery() {
  2346. resetTimeOutOrder();
  2347. proxy.resetForm("queryRef")
  2348. handleQuery()
  2349. }
  2350. // 多选框选中数据
  2351. function handleSelectionChange(selection) {
  2352. ids.value = selection.map(item => item.id)
  2353. single.value = selection.length != 1
  2354. multiple.value = !selection.length
  2355. }
  2356. /** 新增按钮操作 */
  2357. function handleAdd() {
  2358. reset()
  2359. //生成工单编码
  2360. genCode('REPAIR_ORDER_CODE').then(response =>{
  2361. form.value.workOrderProjectNo = response;
  2362. });
  2363. openDialog.value = true
  2364. dialogTitle.value = "新建维修工单"
  2365. optType.value = "add"
  2366. // 设置默认发生时间
  2367. form.value.occurTime = now
  2368. }
  2369. /** 修改按钮操作 */
  2370. function handleEdit(row) {
  2371. reset()
  2372. const id = row.id || ids.value
  2373. getRepairOrder(id).then(response => {
  2374. form.value = response.data
  2375. openDialog.value = true
  2376. dialogTitle.value = "下发"
  2377. optType.value = "edit"
  2378. })
  2379. }
  2380. /** 提交按钮 */
  2381. function submitForm() {
  2382. proxy.$refs["repairOrderRef"].validate(valid => {
  2383. if (valid) {
  2384. form.value.workOrderStatus = "to_issue"
  2385. if (form.value.id != null) {
  2386. updateRepairOrder(form.value).then(response => {
  2387. proxy.$modal.msgSuccess("下发成功")
  2388. openDialog.value = false
  2389. resetTimeOutOrder();
  2390. getList()
  2391. })
  2392. } else {
  2393. addRepairOrder(form.value).then(response => {
  2394. proxy.$modal.msgSuccess("新建成功")
  2395. openDialog.value = false
  2396. resetTimeOutOrder();
  2397. getList()
  2398. })
  2399. }
  2400. }
  2401. })
  2402. }
  2403. /** 保存并下发 */
  2404. function submitFormAndIssue() {
  2405. proxy.$refs["repairOrderRef"].validate(valid => {
  2406. if (valid) {
  2407. // 设置状态为待接单
  2408. form.value.workOrderStatus = "assigned"
  2409. if (form.value.id != null) {
  2410. updateRepairOrder(form.value).then(response => {
  2411. proxy.$modal.msgSuccess("下发成功")
  2412. openDialog.value = false
  2413. resetTimeOutOrder();
  2414. getList()
  2415. })
  2416. } else {
  2417. addRepairOrder(form.value).then(response => {
  2418. proxy.$modal.msgSuccess("新建成功")
  2419. openDialog.value = false
  2420. resetTimeOutOrder();
  2421. getList()
  2422. })
  2423. }
  2424. }
  2425. })
  2426. }
  2427. /** 删除按钮操作 */
  2428. function handleDelete(row) {
  2429. const ids = row.id || ids.value
  2430. const workOrderProjectNo = row.workOrderProjectNo || (repairOrderList.value.find(item => item.id === ids)?.workOrderProjectNo)
  2431. proxy.$modal.confirm('是否确认删除维修工单编码为"' + workOrderProjectNo + '"的数据项?').then(function() {
  2432. return delRepairOrder(ids)
  2433. }).then(() => {
  2434. resetTimeOutOrder();
  2435. getList()
  2436. proxy.$modal.msgSuccess("删除成功")
  2437. }).catch(() => {})
  2438. }
  2439. /** 导出按钮操作 */
  2440. function handleExport() {
  2441. // 显示字段选择对话框
  2442. showExportFieldsDialog.value = true;
  2443. // 定义默认选中的字段(基于字段标签)
  2444. const defaultSelectedLabels = [
  2445. '工单编码',
  2446. '风机编号',
  2447. '工单状态',
  2448. '维保中心',
  2449. '场站',
  2450. '品牌',
  2451. '机型',
  2452. '发生时间',
  2453. '工作负责人',
  2454. '开始时间',
  2455. '结束时间',
  2456. ];
  2457. // 在导出字段中查找对应的key
  2458. const selectedKeys = [];
  2459. exportFieldsData.value.forEach(field => {
  2460. if (defaultSelectedLabels.includes(field.label)) {
  2461. selectedKeys.push(field.key);
  2462. }
  2463. });
  2464. // 设置默认选中的字段
  2465. exportFieldsSelected.value = selectedKeys;
  2466. }
  2467. /** 确认导出 */
  2468. function confirmExport() {
  2469. if (exportFieldsSelected.value.length === 0) {
  2470. proxy.$modal.msgWarning("请至少选择一个导出字段");
  2471. return;
  2472. }
  2473. // 将导出字段拼接成字符串
  2474. const exportFieldsStr = exportFieldsSelected.value.join(',');
  2475. const exportParams = {
  2476. ...queryParams.value,
  2477. exportFields: exportFieldsStr
  2478. };
  2479. proxy.download('gxt/repairOrder/export', exportParams, `repairOrder_${new Date().getTime()}.xlsx`);
  2480. showExportFieldsDialog.value = false;
  2481. }
  2482. /** 故障代码变化处理 */
  2483. function handleFaultCodeChange(value) {
  2484. if (value === '无') {
  2485. // 当选择"无"时,故障信息设置为"-"并允许手动输入
  2486. form.value.faultBarcode = "-";
  2487. } else {
  2488. // 当选择具体的故障代码时,自动填充故障信息并设为只读
  2489. const selectedFaultCode = faultCodeOptions.value.find(item => item.faultCode === value);
  2490. if (selectedFaultCode) {
  2491. form.value.faultBarcode = selectedFaultCode.faultBarcode || "";
  2492. } else {
  2493. form.value.faultBarcode = "";
  2494. }
  2495. }
  2496. }
  2497. /** 获取字典标签文本 */
  2498. function getDictLabel(dictOptions, value) {
  2499. const dict = dictOptions.find(item => item.value === value);
  2500. return dict ? dict.label : value;
  2501. }
  2502. /** 下发操作 */
  2503. function handleAssign(row) {
  2504. getRepairOrder(row.id).then(response => {
  2505. assignForm.value = response.data
  2506. // 初始化维保工单选项为空
  2507. workOrderOptions.value = []
  2508. assignDialogVisible.value = true
  2509. })
  2510. }
  2511. /** 关联维保工单变化处理 */
  2512. function handleRelatedOrderChange() {
  2513. // 当关联维保工单编码输入时,如果清空了内容,则清空维保内容
  2514. if (!assignForm.value.relatedOrderCode) {
  2515. assignForm.value.relatedOrderContent = ""
  2516. }
  2517. }
  2518. /** 搜索维保工单 */
  2519. /*function searchWorkOrders(query) {
  2520. if (!query) {
  2521. workOrderOptions.value = []
  2522. return
  2523. }
  2524. workOrderSearchLoading.value = true
  2525. listGxtOrder({ workOrderProjectNo: query }).then(response => {
  2526. workOrderOptions.value = response.rows
  2527. workOrderSearchLoading.value = false
  2528. }).catch(() => {
  2529. workOrderSearchLoading.value = false
  2530. workOrderOptions.value = []
  2531. })
  2532. }*/
  2533. /** 选择维保工单 */
  2534. function handleWorkOrderChange(val) {
  2535. if (!val) {
  2536. assignForm.value.relatedOrderContent = ""
  2537. return
  2538. }
  2539. // 查找选中的维保工单
  2540. const selectedWorkOrder = workOrderOptions.value.find(item => item.workOrderProjectNo === val)
  2541. if (selectedWorkOrder) {
  2542. // 自动填充维保内容
  2543. assignForm.value.relatedOrderContent = selectedWorkOrder.content || ""
  2544. } else {
  2545. assignForm.value.relatedOrderContent = ""
  2546. }
  2547. }
  2548. /** 提交下发 */
  2549. async function submitAssign() {
  2550. proxy.$refs["assignFormRef"].validate(async valid => {
  2551. if (valid) {
  2552. try {
  2553. await assignRepairOrder(assignForm.value)
  2554. proxy.$modal.msgSuccess("下发成功")
  2555. assignDialogVisible.value = false
  2556. resetTimeOutOrder();
  2557. getList()
  2558. } catch (error) {
  2559. proxy.$modal.msgError("下发失败: " + error.message)
  2560. }
  2561. }
  2562. })
  2563. }
  2564. /** 接单操作 */
  2565. function handleAccept(row) {
  2566. getRepairOrder(row.id).then(response => {
  2567. acceptForm.value = { ...response.data, selectedMembers: [] }
  2568. // 获取场站ID用于查询用户
  2569. acceptForm.value.pcsStationId = response.data.pcsStationId
  2570. acceptForm.value.pcsStationPid = response.data.pcsStationPid
  2571. if (lastLoadedCenterId.value !== acceptForm.value.gxtCenterId) {
  2572. allUserList.value = [];
  2573. }
  2574. // 预加载工作负责人列表
  2575. loadQuickTeamLeaderList()
  2576. acceptDialogVisible.value = true
  2577. })
  2578. }
  2579. /** 提交接单 */
  2580. async function submitAccept() {
  2581. proxy.$refs["acceptFormRef"].validate(async valid => {
  2582. if (valid) {
  2583. try {
  2584. // 更新检修人员列表
  2585. //handleMembersChange('acceptForm');
  2586. await acceptRepairOrder(acceptForm.value)
  2587. proxy.$modal.msgSuccess("接单成功")
  2588. acceptDialogVisible.value = false
  2589. resetTimeOutOrder();
  2590. getList()
  2591. } catch (error) {
  2592. proxy.$modal.msgError("接单失败: " + error.message)
  2593. }
  2594. }
  2595. })
  2596. }
  2597. /** 开始操作 */
  2598. function handleStart(row) {
  2599. /*startForm.value = {
  2600. id: row.id,
  2601. workOrderProjectNo: row.workOrderProjectNo,
  2602. pcsDeviceName: row.pcsDeviceName
  2603. }
  2604. startDialogVisible.value = true*/
  2605. ElMessageBox.confirm('确定要恢复工单"' + row.workOrderProjectNo + '"吗?', '提示', {
  2606. confirmButtonText: '确认恢复',
  2607. cancelButtonText: '取消',
  2608. type: 'warning'
  2609. }).then(function() {
  2610. startRepairOrder(row);
  2611. }).then(() => {
  2612. resetTimeOutOrder();
  2613. getList()
  2614. proxy.$modal.msgSuccess("恢复成功")
  2615. }).catch(() => {})
  2616. }
  2617. /** 提交开始处理 */
  2618. async function submitStart() {
  2619. try {
  2620. await startRepairOrder(startForm.value);
  2621. proxy.$modal.msgSuccess("工单已开始处理");
  2622. startDialogVisible.value = false;
  2623. resetTimeOutOrder();
  2624. getList();
  2625. } catch (error) {
  2626. proxy.$modal.msgError("操作失败: " + error.message);
  2627. }
  2628. }
  2629. /** 暂停操作 */
  2630. async function handlePause(row) {
  2631. proxy.$modal.confirm('是否确认暂停该工单?').then(async function() {
  2632. try {
  2633. const updateData = {
  2634. id: row.id,
  2635. workOrderStatus: "paused"
  2636. }
  2637. await pauseRepairOrder(updateData)
  2638. proxy.$modal.msgSuccess("工单已暂停")
  2639. resetTimeOutOrder();
  2640. getList()
  2641. } catch (error) {
  2642. proxy.$modal.msgError("操作失败: " + error.message)
  2643. }
  2644. }).catch(() => {})
  2645. }
  2646. /** 恢复工单 */
  2647. async function handleResume(row) {
  2648. ElMessageBox.confirm('确定要恢复工单"' + row.workOrderProjectNo + '"吗?', '提示', {
  2649. confirmButtonText: '确认恢复',
  2650. cancelButtonText: '取消',
  2651. type: 'warning'
  2652. }).then(function() {
  2653. const updateData = {
  2654. id: row.id,
  2655. workOrderStatus: "to_finish"
  2656. };
  2657. resumeRepairOrder(updateData);
  2658. }).then(() => {
  2659. resetTimeOutOrder();
  2660. getList()
  2661. proxy.$modal.msgSuccess("恢复成功")
  2662. }).catch(() => {})
  2663. }
  2664. /** 撤回工单 */
  2665. async function handleRevoke(row) {
  2666. ElMessageBox.confirm('确定要撤回工单"' + row.workOrderProjectNo + '"吗?', '提示', {
  2667. confirmButtonText: '确认撤回',
  2668. cancelButtonText: '取消',
  2669. type: 'warning'
  2670. }).then(function() {
  2671. const updateData = {
  2672. id: row.id,
  2673. workOrderStatus: "to_issue"
  2674. };
  2675. revokeRepairOrder(updateData);
  2676. }).then(() => {
  2677. resetTimeOutOrder();
  2678. getList()
  2679. proxy.$modal.msgSuccess("撤回成功")
  2680. }).catch(() => {})
  2681. }
  2682. /** 驳回工单 */
  2683. function handleReject(row) {
  2684. approveForm.value = {
  2685. id: row.id,
  2686. approvalStatus: "rejected",
  2687. rejectionReason: ""
  2688. };
  2689. approveDialogVisible.value = true;
  2690. }
  2691. /** 处理结束操作 */
  2692. function handleProcessDone(row) {
  2693. completeForm.value = {
  2694. id: row.id,
  2695. completeDescription: ""
  2696. }
  2697. completeDialogVisible.value = true
  2698. }
  2699. /** 处理MIS工单编码失去焦点事件 */
  2700. function handleMisOrderNoBlur() {
  2701. // 只有当配置为1时才自动获取数据
  2702. if (getMisDataConfig.value === "1" && finalizeForm.value.misOrderNo) {
  2703. // 创建一个只包含必要字段的对象,避免传递repairOrderFlowList等复杂对象
  2704. const requestData = {
  2705. id: finalizeForm.value.id,
  2706. misOrderNo: finalizeForm.value.misOrderNo
  2707. };
  2708. getRepairOrderByMisOrderNo(requestData).then(response => {
  2709. const data = response.data;
  2710. if (data) {
  2711. // 填充开始时间
  2712. if (data.realStartTime) {
  2713. finalizeForm.value.realStartTime = data.realStartTime;
  2714. }
  2715. // 填充结束时间
  2716. if (data.realEndTime) {
  2717. finalizeForm.value.realEndTime = data.realEndTime;
  2718. }
  2719. // 填充检修人员列表
  2720. if (data.workGroupMemberName) {
  2721. finalizeForm.value.workGroupMemberName = data.workGroupMemberName;
  2722. }
  2723. if (data.repairOrderPersonList && data.repairOrderPersonList.length > 0) {
  2724. finalizeForm.value.repairOrderPersonList = data.repairOrderPersonList;
  2725. }
  2726. } else {
  2727. finalizeForm.value.realStartTime = null;
  2728. finalizeForm.value.realEndTime = null;
  2729. finalizeForm.value.workGroupMemberName = null;
  2730. finalizeForm.value.repairOrderPersonList = [];
  2731. proxy.$modal.msgWarning("未找到对应的MIS工单信息");
  2732. }
  2733. }).catch(error => {
  2734. finalizeForm.value.realStartTime = null;
  2735. finalizeForm.value.realEndTime = null;
  2736. finalizeForm.value.workGroupMemberName = null;
  2737. finalizeForm.value.repairOrderPersonList = [];
  2738. proxy.$modal.msgError("获取MIS工单信息失败: " + error.message);
  2739. });
  2740. }
  2741. }
  2742. /** 维修方式变化处理 */
  2743. function handleRepairMethodChange(value) {
  2744. // 如果切换到正常维修(1),清除复位方式
  2745. if (value === '1') {
  2746. finalizeForm.value.resetMethod = undefined;
  2747. }
  2748. // 如果切换到复位启机(2),清除MIS相关字段
  2749. else if (value === '2') {
  2750. finalizeForm.value.misOrderNo = undefined;
  2751. finalizeForm.value.realStartTime = undefined;
  2752. finalizeForm.value.realEndTime = undefined;
  2753. finalizeForm.value.workGroupMemberName = undefined;
  2754. finalizeForm.value.repairOrderPersonList = [];
  2755. }
  2756. }
  2757. /** 提交完成 */
  2758. async function submitComplete() {
  2759. proxy.$refs["completeFormRef"].validate(async valid => {
  2760. if (valid) {
  2761. try {
  2762. const updateData = {
  2763. id: completeForm.value.id,
  2764. workOrderStatus: "to_be_finalized",
  2765. realEndTime: new Date(),
  2766. completeDescription: completeForm.value.completeDescription
  2767. }
  2768. await processDoneRepairOrder(updateData)
  2769. proxy.$modal.msgSuccess("处理完成,工单进入待结单状态")
  2770. completeDialogVisible.value = false
  2771. resetTimeOutOrder();
  2772. getList()
  2773. } catch (error) {
  2774. proxy.$modal.msgError("操作失败: " + error.message)
  2775. }
  2776. }
  2777. })
  2778. }
  2779. /** 获取导出字段数据 */
  2780. function getExportFieldsData() {
  2781. getExportFields().then(response => {
  2782. exportFieldsData.value = response.data;
  2783. });
  2784. }
  2785. /** 评分操作 */
  2786. function handleRating(row) {
  2787. getRepairOrder(row.id).then(response => {
  2788. ratingForm.value = response.data
  2789. ratingForm.value.score = null
  2790. ratingDialogVisible.value = true
  2791. })
  2792. }
  2793. /** 提交评分 */
  2794. async function submitRating() {
  2795. proxy.$refs["ratingFormRef"].validate(async valid => {
  2796. if (valid) {
  2797. try {
  2798. await ratingRepairOrder(ratingForm.value)
  2799. proxy.$modal.msgSuccess("评分成功")
  2800. ratingDialogVisible.value = false
  2801. resetTimeOutOrder();
  2802. getList()
  2803. } catch (error) {
  2804. proxy.$modal.msgError("操作失败: " + error.message)
  2805. }
  2806. }
  2807. })
  2808. }
  2809. /** 查看按钮操作 */
  2810. async function handleView(row) {
  2811. try {
  2812. // 获取工单详情
  2813. const response = await getRepairOrder(row.id)
  2814. viewForm.value = response.data
  2815. // 从工单详情中获取流转记录
  2816. flowList.value = response.data.repairOrderFlowList || []
  2817. viewDialogVisible.value = true
  2818. } catch (error) {
  2819. proxy.$modal.msgError("获取工单信息失败: " + error.message)
  2820. }
  2821. }
  2822. /** 挂起工单 */
  2823. function handleSuspend(row) {
  2824. suspendForm.value = row
  2825. suspendForm.value.suspendReason = undefined
  2826. suspendDialogVisible.value = true
  2827. }
  2828. /** 提交挂起 */
  2829. async function submitSuspend() {
  2830. proxy.$refs["suspendFormRef"].validate(async valid => {
  2831. if (valid) {
  2832. try {
  2833. await suspendRepairOrder(suspendForm.value);
  2834. proxy.$modal.msgSuccess("挂起申请已提交");
  2835. suspendDialogVisible.value = false;
  2836. resetTimeOutOrder();
  2837. getList();
  2838. } catch (error) {
  2839. proxy.$modal.msgError("挂起申请失败: " + error.message);
  2840. }
  2841. }
  2842. });
  2843. }
  2844. /** 审批挂起 */
  2845. function handleApprove(row) {
  2846. getRepairOrder(row.id).then(response => {
  2847. approveForm.value = response.data
  2848. approveForm.value.approvalStatus = undefined
  2849. approveForm.value.rejectionReason = undefined
  2850. approveDialogVisible.value = true
  2851. // 打开对话框后重置表单验证错误
  2852. proxy.resetForm("approveFormRef")
  2853. })
  2854. }
  2855. /** 退回 */
  2856. function handleReturn(row) {
  2857. getRepairOrder(row.id).then(response => {
  2858. returnForm.value = response.data
  2859. if (row.workOrderStatus != 'return') {
  2860. returnForm.value.returnType = undefined
  2861. returnForm.value.returnReason = undefined
  2862. }
  2863. returnDialogVisible.value = true
  2864. })
  2865. }
  2866. /** 提交退回 */
  2867. async function submitReturn() {
  2868. proxy.$refs["returnFormRef"].validate(async valid => {
  2869. if (valid) {
  2870. try {
  2871. if (returnForm.value.workOrderStatus == 'return' || returnForm.value.workOrderStatus == 'assigned') {
  2872. returnForm.value.workOrderStatus = "accept_return";
  2873. } else {
  2874. returnForm.value.workOrderStatus = "return";
  2875. }
  2876. await returnRepairOrder(returnForm.value);
  2877. proxy.$modal.msgSuccess("退回成功");
  2878. returnDialogVisible.value = false;
  2879. resetTimeOutOrder();
  2880. getList();
  2881. } catch (error) {
  2882. proxy.$modal.msgError("退回失败: " + error.message);
  2883. }
  2884. }
  2885. });
  2886. }
  2887. /** 切换驳回原因显示 */
  2888. function toggleRejectionReason() {
  2889. // 驳回原因的必填验证由表单规则控制
  2890. }
  2891. /** 提交审批 */
  2892. async function submitApprove(approvalStatusValue) {
  2893. proxy.$refs["approveFormRef"].validate(async valid => {
  2894. if (valid) {
  2895. try {
  2896. approveForm.value.approvalStatus = approvalStatusValue
  2897. /*if (approveForm.value.approvalStatus === 'approved') {
  2898. approveForm.value.rejectionReason = undefined;
  2899. }*/
  2900. if (approveForm.value.approvalStatus === 'rejected' && !approveForm.value.rejectionReason) {
  2901. proxy.$modal.msgError("驳回时审批意见不能为空");
  2902. return;
  2903. }
  2904. await approveSuspendRepairOrder(approveForm.value);
  2905. proxy.$modal.msgSuccess("操作完成");
  2906. approveDialogVisible.value = false;
  2907. resetTimeOutOrder();
  2908. getList();
  2909. } catch (error) {
  2910. proxy.$modal.msgError("操作失败: " + error.message);
  2911. }
  2912. }
  2913. });
  2914. }
  2915. /** 结单操作 */
  2916. function handleFinalize(row, method) {
  2917. getRepairOrder(row.id).then(response => {
  2918. finalizeFormData.value = { ...response.data, selectedMembers: [] }
  2919. debugger
  2920. finalizeFormData.value.repairMethod = method;
  2921. if (method == '1') {
  2922. finalizeFormData.value.infoEntry = '1'
  2923. }
  2924. finalizeDialogVisible.value = true
  2925. commonKey++
  2926. })
  2927. }
  2928. /** 复启操作 */
  2929. function handleReset(row) {
  2930. getRepairOrder(row.id).then(response => {
  2931. // 使用新的组件方式
  2932. resetFormData.value = { ...response.data }
  2933. resetDialogVisible.value = true
  2934. })
  2935. }
  2936. // 添加响应式数据用于复启组件
  2937. const resetFormData = ref({})
  2938. // 在提交复启成功后的回调函数
  2939. function handleResetSuccess() {
  2940. resetDialogVisible.value = false
  2941. resetTimeOutOrder()
  2942. getList()
  2943. }
  2944. // 添加响应式数据用于结单组件
  2945. const finalizeFormData = ref({})
  2946. // 在提交结单成功后的回调函数
  2947. function handleFinalizeSuccess() {
  2948. finalizeDialogVisible.value = false
  2949. resetTimeOutOrder()
  2950. getList()
  2951. }
  2952. // 用于传递给结单组件的提交方法
  2953. async function submitFinalizeFromParent(data) {
  2954. await finalizeRepairOrder(data)
  2955. }
  2956. // 用于传递给复启组件的提交方法
  2957. async function submitResetFromParent(data) {
  2958. await finalizeRepairOrder(data)
  2959. }
  2960. /** 提交复启 */
  2961. async function submitReset() {
  2962. proxy.$refs["resetFormRef"].validate(async valid => {
  2963. if (valid) {
  2964. try {
  2965. finalizeForm.value.repairMethod = '2';
  2966. await finalizeRepairOrder(finalizeForm.value)
  2967. proxy.$modal.msgSuccess("复启成功")
  2968. resetDialogVisible.value = false
  2969. resetTimeOutOrder();
  2970. getList()
  2971. } catch (error) {
  2972. proxy.$modal.msgError("操作失败: " + error.message)
  2973. }
  2974. }
  2975. })
  2976. }
  2977. // 用于传递给退回组件的提交方法
  2978. async function submitReturnFromParent(data) {
  2979. await returnRepairOrder(data)
  2980. }
  2981. // 在提交退回成功后的回调函数
  2982. function handleReturnSuccess() {
  2983. returnDialogVisible.value = false
  2984. resetTimeOutOrder()
  2985. getList()
  2986. }
  2987. // 用于传递给挂起组件的提交方法
  2988. async function submitSuspendFromParent(data) {
  2989. await suspendRepairOrder(data)
  2990. }
  2991. // 在提交审批成功后的回调函数
  2992. async function submitApproveFromParent(data) {
  2993. await approveSuspendRepairOrder(data)
  2994. }
  2995. // 在提交挂起成功后的回调函数
  2996. function handleSuspendSuccess() {
  2997. suspendDialogVisible.value = false
  2998. resetTimeOutOrder()
  2999. getList()
  3000. }
  3001. // 在提交审批成功后的回调函数
  3002. function handleApproveSuccess() {
  3003. approveDialogVisible.value = false
  3004. resetTimeOutOrder()
  3005. getList()
  3006. }
  3007. /** 检修人员选择变化 */
  3008. function handleMembersChange(formName) {
  3009. // 默认使用 acceptForm,但也支持其他表单
  3010. const targetForm = formName === 'finalizeForm' ? finalizeForm : acceptForm;
  3011. // 清空之前的列表
  3012. targetForm.value.repairOrderPersonList = [];
  3013. // 为每个选中的成员创建 GxtRepairOrderPerson 对象
  3014. targetForm.value.selectedMembers.forEach(userId => {
  3015. const user = userList.value.find(u => u.userId === userId)
  3016. if (user) {
  3017. targetForm.value.repairOrderPersonList.push({
  3018. userId: user.userId,
  3019. nickName: user.nickName,
  3020. orderId: targetForm.value.id,
  3021. orderCode: targetForm.value.workOrderProjectNo,
  3022. status: 1
  3023. });
  3024. }
  3025. });
  3026. }
  3027. /** 复运操作 */
  3028. function handleRestart(row) {
  3029. getRepairOrder(row.id).then(response => {
  3030. restartForm.value = response.data
  3031. restartDialogVisible.value = true
  3032. })
  3033. }
  3034. /** 提交复运 */
  3035. async function submitRestart() {
  3036. proxy.$refs["restartFormRef"].validate(async valid => {
  3037. if (valid) {
  3038. try {
  3039. await restartRepairOrder(restartForm.value)
  3040. proxy.$modal.msgSuccess("复运成功")
  3041. restartDialogVisible.value = false
  3042. resetTimeOutOrder();
  3043. getList()
  3044. } catch (error) {
  3045. proxy.$modal.msgError("操作失败: " + error.message)
  3046. }
  3047. }
  3048. })
  3049. }
  3050. function handleImgUplaoded(imgUrl){
  3051. from.value.workUrl = imgUrl;
  3052. }
  3053. function handleImgRemoved(imgUrl){
  3054. form.value.workUrl = null;
  3055. }
  3056. /*** MIS导入参数 */
  3057. const uploadMis = reactive({
  3058. // 是否显示弹出层(设备导入)
  3059. open: false,
  3060. // 弹出层标题(设备导入)
  3061. title: "",
  3062. // 是否禁用上传
  3063. isUploading: false,
  3064. // 是否更新已经存在的设备数据
  3065. updateSupport: 0,
  3066. // 设置上传的请求头部
  3067. headers: { Authorization: "Bearer " + getToken() },
  3068. // 上传的地址
  3069. url: import.meta.env.VITE_APP_BASE_API + "/gxt/repairOrder/importDataMis"
  3070. })
  3071. /** 导入按钮操作 */
  3072. function handleImportMis() {
  3073. uploadMis.title = "MIS工单导入"
  3074. uploadMis.open = true
  3075. uploadMis.selectedFile = null
  3076. }
  3077. /** 下载模板操作 */
  3078. function importTemplateMis() {
  3079. proxy.download("gxt/repairOrder/importTemplateMis", {
  3080. }, `repairOrderMis_template_${new Date().getTime()}.xlsx`)
  3081. }
  3082. /**文件上传中处理 */
  3083. const handleFileUploadProgressMis = (event, file, fileList) => {
  3084. uploadMis.isUploading = true
  3085. }
  3086. /** 文件选择处理 */
  3087. const handleFileChangeMis = (file, fileList) => {
  3088. uploadMis.selectedFile = file
  3089. }
  3090. /** 文件删除处理 */
  3091. const handleFileRemoveMis = (file, fileList) => {
  3092. uploadMis.selectedFile = null
  3093. }
  3094. /** 文件上传成功处理 */
  3095. const handleFileSuccessMis = (response, file, fileList) => {
  3096. uploadMis.open = false
  3097. uploadMis.isUploading = false
  3098. proxy.$refs["uploadMisRef"].handleRemove(file)
  3099. proxy.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导入结果", { dangerouslyUseHTMLString: true })
  3100. resetTimeOutOrder();
  3101. getList()
  3102. }
  3103. /** 提交上传文件 */
  3104. function submitFileFormMis() {
  3105. const file = uploadMis.selectedFile
  3106. if (!file || file.length === 0 || !file.name.toLowerCase().endsWith('.xls') && !file.name.toLowerCase().endsWith('.xlsx')) {
  3107. proxy.$modal.msgError("请选择后缀为 “xls”或“xlsx”的文件。")
  3108. return
  3109. }
  3110. proxy.$refs["uploadMisRef"].submit()
  3111. }
  3112. /*** 维修工单导入参数 */
  3113. const upload = reactive({
  3114. // 是否显示弹出层(设备导入)
  3115. open: false,
  3116. // 弹出层标题(设备导入)
  3117. title: "",
  3118. // 是否禁用上传
  3119. isUploading: false,
  3120. // 是否更新已经存在的设备数据
  3121. updateSupport: 0,
  3122. // 设置上传的请求头部
  3123. headers: { Authorization: "Bearer " + getToken() },
  3124. // 上传的地址
  3125. url: import.meta.env.VITE_APP_BASE_API + "/gxt/repairOrder/importData"
  3126. })
  3127. /** 导入按钮操作 */
  3128. function handleImport() {
  3129. upload.title = "维修工单导入"
  3130. upload.open = true
  3131. upload.selectedFile = null
  3132. }
  3133. /** 下载模板操作 */
  3134. function importTemplate() {
  3135. proxy.download("gxt/repairOrder/importTemplate", {
  3136. }, `repairOrder_template_${new Date().getTime()}.xlsx`)
  3137. }
  3138. /**文件上传中处理 */
  3139. const handleFileUploadProgress = (event, file, fileList) => {
  3140. upload.isUploading = true
  3141. }
  3142. /** 文件选择处理 */
  3143. const handleFileChange = (file, fileList) => {
  3144. upload.selectedFile = file
  3145. }
  3146. /** 文件删除处理 */
  3147. const handleFileRemove = (file, fileList) => {
  3148. upload.selectedFile = null
  3149. }
  3150. /** 文件上传成功处理 */
  3151. const handleFileSuccess = (response, file, fileList) => {
  3152. upload.open = false
  3153. upload.isUploading = false
  3154. proxy.$refs["uploadRef"].handleRemove(file)
  3155. proxy.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导入结果", { dangerouslyUseHTMLString: true })
  3156. resetTimeOutOrder();
  3157. getList()
  3158. }
  3159. /** 提交上传文件 */
  3160. function submitFileForm() {
  3161. const file = upload.selectedFile
  3162. if (!file || file.length === 0 || !file.name.toLowerCase().endsWith('.xls') && !file.name.toLowerCase().endsWith('.xlsx')) {
  3163. proxy.$modal.msgError("请选择后缀为 “xls”或“xlsx”的文件。")
  3164. return
  3165. }
  3166. proxy.$refs["uploadRef"].submit()
  3167. }
  3168. /** 打开MIS信息选择对话框 */
  3169. function handleSelectMisInfo() {
  3170. misInfoSelectVisible.value = true
  3171. }
  3172. /** 设备MIS信息回调 */
  3173. function onMisInfoSelected(row) {
  3174. if (row) {
  3175. listRepairOrder({pageNum: 1, pageSize: 10, misOrderNo: row.misNo }).then(response => {
  3176. const gxtOrders= response.rows
  3177. if (gxtOrders.length > 0) {
  3178. proxy.$modal.msgWarning('选择工单已存在!请重新选择!')
  3179. return
  3180. }
  3181. // 使用展开运算符创建新对象以确保响应式更新
  3182. finalizeFormData.value = {
  3183. ...finalizeFormData.value,
  3184. misOrderNo: row.misNo,
  3185. realStartTime: row.realStartTime,
  3186. realEndTime: row.realEndTime
  3187. };
  3188. // finalizeFormData.value.content = row.content
  3189. // 使用从属性传入的listWorkPerson方法
  3190. if (typeof listWorkPerson === 'function') {
  3191. listWorkPerson({ misNo: row.misNo }).then(response => {
  3192. debugger
  3193. const updatedData = {
  3194. ...finalizeFormData.value,
  3195. repairOrderPersonList: response.rows
  3196. };
  3197. if (response.rows) {
  3198. const nickNames = response.rows
  3199. .map(person => person.nickName)
  3200. .join(',');
  3201. updatedData.workGroupMemberName = nickNames
  3202. }
  3203. finalizeFormData.value = updatedData;
  3204. })
  3205. }
  3206. misInfoSelectVisible.value = false
  3207. })
  3208. }
  3209. }
  3210. /** 提交作废 */
  3211. async function submitInvalidate() {
  3212. proxy.$refs["invalidateFormRef"].validate(async valid => {
  3213. if (!valid) {
  3214. return
  3215. }
  3216. try {
  3217. await invalidateRepairOrder(invalidateForm.value);
  3218. proxy.$modal.msgSuccess("作废成功");
  3219. invalidateDialogVisible.value = false;
  3220. resetTimeOutOrder();
  3221. getList();
  3222. } catch (error) {
  3223. proxy.$modal.msgError("操作失败: " + error.message);
  3224. }
  3225. });
  3226. }
  3227. const rightChecks = ref([])
  3228. function rightCheckHandler(val) {
  3229. rightChecks.value = exportFieldsSelected.value
  3230. .filter(item => val.includes(item))
  3231. console.log(rightChecks.value, "rightCheckHandler")
  3232. }
  3233. function upDown(direction) {
  3234. // 找出最小和最大索引
  3235. const indices = rightChecks.value
  3236. .map(i => exportFieldsSelected.value.indexOf(i))
  3237. .filter(i => i !== -1)
  3238. const minIndex = Math.min(...indices)
  3239. const maxIndex = Math.max(...indices)
  3240. // 边界检查
  3241. if (direction === 'up' && minIndex === 0) {
  3242. console.log('已到顶部')
  3243. return
  3244. }
  3245. if (direction === 'down' && maxIndex === exportFieldsSelected.value.length - 1) {
  3246. console.log('已到底部')
  3247. return
  3248. }
  3249. if (direction === 'up') {
  3250. rightChecks.value.map(i => {
  3251. const index = exportFieldsSelected.value.findIndex(t => t == i)
  3252. exportFieldsSelected.value.splice(index, 1);
  3253. exportFieldsSelected.value.splice(index - 1, 0, i);
  3254. })
  3255. } else {
  3256. rightChecks.value.slice().reverse().forEach(i => {
  3257. const index = exportFieldsSelected.value.findIndex(t => t == i)
  3258. if (index < exportFieldsSelected.value.length - 1) {
  3259. exportFieldsSelected.value.splice(index, 1)
  3260. exportFieldsSelected.value.splice(index + 1, 0, i)
  3261. }
  3262. })
  3263. }
  3264. }
  3265. /** 作废操作 */
  3266. function handleInvalidate(row) {
  3267. getRepairOrder(row.id).then(response => {
  3268. invalidateForm.value = { ...response.data }
  3269. invalidateDialogVisible.value = true
  3270. })
  3271. }
  3272. const formattedWorkArea = computed(() =>{
  3273. if (!viewForm.value?.workArea) return '-'
  3274. const values = viewForm.value.workArea.split(',').filter(v => v.trim())
  3275. const dictList = unref(gxt_work_area) // 关键:解包 ref
  3276. if (!Array.isArray(dictList)) {
  3277. return viewForm.value.workArea
  3278. }
  3279. const dictMap = new Map(dictList.map(item => [item.value, item.label]))
  3280. const labels = values.map(v => dictMap.get(v) || v)
  3281. return labels.join(',') || '-'
  3282. })
  3283. // 计算属性:双向绑定代理
  3284. const workPermitNumProxy = computed({
  3285. get() {
  3286. return finalizeForm.value.workPermitNum
  3287. },
  3288. set(val) {
  3289. // 1. 去掉首尾空格
  3290. let trimmed = val.trim()
  3291. // 2. 只保留允许的字符:中文、英文字母、数字、下划线
  3292. // 如果你希望更宽松(比如允许横杠 -),可调整正则
  3293. trimmed = trimmed.replace(/[^a-zA-Z0-9_\-\.]/g, '')
  3294. // 3. 截断到 20 个字符(按字符数,不是字节)
  3295. if (trimmed.length > 20) {
  3296. trimmed = trimmed.substring(0, 20)
  3297. }
  3298. // 4. 写回表单
  3299. finalizeForm.value.workPermitNum = trimmed
  3300. }
  3301. })
  3302. </script>
  3303. <style scoped>
  3304. .text-gray-500 {
  3305. color: #6b7280;
  3306. }
  3307. .mb-2 {
  3308. margin-bottom: 0.5rem;
  3309. }
  3310. .mb-3 {
  3311. margin-bottom: 0.75rem;
  3312. }
  3313. .card-header {
  3314. font-weight: bold;
  3315. font-size: 16px;
  3316. }
  3317. .info-section {
  3318. padding: 16px 0;
  3319. height: 100%;
  3320. box-sizing: border-box;
  3321. }
  3322. .section-title {
  3323. font-weight: bold;
  3324. font-size: 16px;
  3325. margin-bottom: 15px;
  3326. padding-bottom: 10px;
  3327. border-bottom: 1px solid #ebeef5;
  3328. }
  3329. .info-content {
  3330. height: calc(100% - 30px);
  3331. overflow-y: auto;
  3332. overflow-x: hidden; /* 防止横向滚动 */
  3333. padding: 0 10px; /* 添加内边距防止内容贴边 */
  3334. }
  3335. .info-item {
  3336. margin-bottom: 12px;
  3337. }
  3338. .info-item label {
  3339. display: block;
  3340. font-size: 12px;
  3341. color: #999;
  3342. margin-bottom: 4px;
  3343. }
  3344. .info-item p {
  3345. font-size: 14px;
  3346. color: #333;
  3347. margin: 0;
  3348. line-height: 1.4;
  3349. }
  3350. .flow-history {
  3351. height: 100%;
  3352. padding: 0 10px; /* 添加内边距防止内容贴边 */
  3353. }
  3354. .flow-history .el-timeline {
  3355. margin-left: 0;
  3356. padding-left: 0;
  3357. }
  3358. .flow-item {
  3359. /*padding: 10px;
  3360. border-radius: 4px;*/
  3361. }
  3362. .flow-item h4 {
  3363. margin: 0 0 5px 0;
  3364. font-size: 14px;
  3365. font-weight: bold;
  3366. }
  3367. .flow-item p {
  3368. margin: 0;
  3369. font-size: 12px;
  3370. line-height: 1.4;
  3371. color: #606266;
  3372. }
  3373. /* 修复对话框底部按钮点击区域问题 */
  3374. :deep(.el-dialog__footer) {
  3375. padding: 20px !important;
  3376. position: relative;
  3377. z-index: 10;
  3378. }
  3379. /* 确保关闭按钮有完整的点击区域 */
  3380. .dialog-footer :deep(.el-button) {
  3381. padding: 12px 20px;
  3382. min-width: 80px;
  3383. z-index: 20;
  3384. position: relative;
  3385. }
  3386. /* 表单字段间距调整 */
  3387. :deep(.el-form-item) {
  3388. margin-bottom: 18px;
  3389. }
  3390. /* 表单中的列间距调整 */
  3391. :deep(.el-col) {
  3392. padding-left: 5px;
  3393. padding-right: 5px;
  3394. }
  3395. /* 表单行间距调整 */
  3396. :deep(.el-row) {
  3397. margin-left: -5px;
  3398. margin-right: -5px;
  3399. }
  3400. /* MIS工单快速检索样式 */
  3401. .quick-select-dropdown {
  3402. position: absolute;
  3403. top: 100%;
  3404. left: 0;
  3405. right: 0;
  3406. background: white;
  3407. border: 1px solid #e4e7ed;
  3408. border-top: none;
  3409. border-radius: 0 0 4px 4px;
  3410. max-height: 200px;
  3411. overflow-y: auto;
  3412. z-index: 2000;
  3413. box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  3414. }
  3415. .quick-select-item {
  3416. padding: 8px 12px;
  3417. cursor: pointer;
  3418. border-bottom: 1px solid #f0f0f0;
  3419. display: flex;
  3420. justify-content: space-between;
  3421. align-items: center;
  3422. }
  3423. .quick-select-item:hover {
  3424. background-color: #f5f7fa;
  3425. }
  3426. .quick-select-item:last-child {
  3427. border-bottom: none;
  3428. }
  3429. .mis-no {
  3430. font-weight: bold;
  3431. color: #409eff;
  3432. flex-shrink: 0;
  3433. }
  3434. .mis-info {
  3435. display: flex;
  3436. flex-direction: column;
  3437. align-items: flex-end;
  3438. flex: 1;
  3439. margin-left: 10px;
  3440. }
  3441. .mis-info .device {
  3442. color: #606266;
  3443. font-size: 12px;
  3444. margin-bottom: 2px;
  3445. }
  3446. .mis-info .station {
  3447. color: #909399;
  3448. font-size: 11px;
  3449. }
  3450. .no-data {
  3451. padding: 15px;
  3452. text-align: center;
  3453. color: #909399;
  3454. font-size: 14px;
  3455. }
  3456. /* 确保表单项有相对定位 */
  3457. :deep(.el-form-item) {
  3458. position: relative;
  3459. }
  3460. /* 输入框样式调整 */
  3461. :deep(.el-input-group__append) {
  3462. background-color: #409eff;
  3463. border-color: #409eff;
  3464. color: white;
  3465. }
  3466. :deep(.el-input-group__append .el-button) {
  3467. color: white;
  3468. border: none;
  3469. }
  3470. :deep(.el-input-group__append .el-button:hover) {
  3471. background-color: #66b1ff;
  3472. }
  3473. /* 表单字段间距调整 */
  3474. :deep(.el-form-item) {
  3475. margin-bottom: 18px;
  3476. }
  3477. .content-text {
  3478. white-space: pre-wrap;
  3479. word-break: break-word;
  3480. line-height: 1.5;
  3481. }
  3482. /* 穿透修改组件内部输入框的对齐方式(关键) */
  3483. :deep(.input-number-left .el-input__inner) {
  3484. text-align: left !important; /* !important 覆盖组件默认的居中 */
  3485. }
  3486. </style>