wbs.vue 159 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962
  1. <template>
  2. <div class="h-full">
  3. <hc-page-split v-if="wbsTypeTabKey === 'tree'" ref="pageSplitRef">
  4. <template #left>
  5. <div class="left-box-container bg-white">
  6. <div class="hc-project-box">
  7. <div>
  8. <el-tooltip
  9. v-model:visible="collectListVisible"
  10. placement="bottom"
  11. effect="light"
  12. trigger="manual"
  13. :virtual-ref="triggerRef"
  14. popper-class="custom-tooltip-pro"
  15. >
  16. <template #content>
  17. <div class="tooltip-content">
  18. <!-- 新建文件夹按钮 -->
  19. <div class="new-folder" @click.stop="showAddInput = true">
  20. 新建文件夹
  21. <HcIcon name="add-circle" class="add-icon cursor-pointer" style="color:white;" />
  22. </div>
  23. <!-- 新建文件夹输入框 -->
  24. <div v-if="showAddInput" class="add-input-container">
  25. <el-input
  26. v-model="newFolderName"
  27. placeholder="请输入名称"
  28. class="folder-input"
  29. @keyup.enter="confirmAddFolder"
  30. />
  31. <div class="input-buttons">
  32. <HcIcon name="check" class="confirm-icon cursor-pointer" :loading="confirmAddFolderLoad" @click="confirmAddFolder" />
  33. <HcIcon name="close" class="cancel-icon cursor-pointer" @click="cancelAddFolder" />
  34. </div>
  35. </div>
  36. <!-- 文件夹列表容器(带滚动) -->
  37. <div ref="folderListContainer" v-loading="collectLoad" class="folder-list-container">
  38. <div
  39. v-for="(folder, index) in collectList"
  40. :key="folder.id"
  41. class="folder-item"
  42. style="display: flex; align-items: center; gap: 8px;"
  43. >
  44. <!-- 拖拽图标 - 作为拖拽手柄 -->
  45. <HcIcon
  46. name="drag-move-2"
  47. class="drag-handle cursor-move"
  48. style="margin-right: 4px; flex-shrink: 0;"
  49. />
  50. <!-- 编辑状态显示输入框 -->
  51. <el-input
  52. v-if="folder.isEditing"
  53. ref="editInput"
  54. v-model="folder.editableName"
  55. size="small"
  56. @keyup.enter="confirmEdit(index, folder)"
  57. />
  58. <!-- 非编辑状态显示文本 -->
  59. <span
  60. v-else
  61. class="folder-name"
  62. style="cursor: pointer;"
  63. @click="selectFolder(folder)"
  64. >
  65. {{ folder.name }}
  66. </span>
  67. <HcIcon v-if="!folder.isEditing" name="edit" class="cursor-pointer" style="color:white;" @click="startEdit(folder)" />
  68. <HcIcon v-if="folder.isEditing" name="check" class="cursor-pointer" style="color:white;" @click="confirmEdit(index, folder)" />
  69. <HcIcon
  70. name="delete-bin"
  71. class="delete-icon cursor-pointer"
  72. style="color:white;"
  73. @click.stop="deleteFolder(index, folder)"
  74. />
  75. </div>
  76. </div>
  77. </div>
  78. </template>
  79. <HcIcon name="star-half" class="mr-3 cursor-pointer" style="color:rgb(255, 125, 67);" title="文件收藏夹" @click="collectListClick" />
  80. </el-tooltip>
  81. <template v-if="classType === '1'">
  82. <HcIcon v-if="isLookHide" name="eye-off" style="color:#3F9EFF" class="cursor-pointer" title="隐藏夹" @click="lookHideList" />
  83. <HcIcon v-else name="eye" style="color:#3F9EFF" class="cursor-pointer" title="显示全部节点" @click="handleClickBack" />
  84. </template>
  85. </div>
  86. <div>
  87. <HcIcon v-loading="lookLoading" name="time" class="mr-3 cursor-pointer" style="color:#3F9EFF" title="近五天填报记录" @click="lookHistory" />
  88. <HcIcon name="article" style="color:gray" class="cursor-pointer" />
  89. </div>
  90. </div>
  91. <div class="hc-tree-box hc-tree-box1">
  92. <div class="hc-tree-back-to">
  93. <div>
  94. <el-link type="primary" @click="gobackHistory">
  95. 回到上一次填报部位
  96. </el-link>
  97. <el-link
  98. type="warning"
  99. class="ml-4"
  100. @click="wbsMapTypeTab"
  101. >
  102. 导图结构填报
  103. </el-link>
  104. </div>
  105. <div
  106. v-if="isSearchTree || folderId"
  107. class="back-button animate-pulse"
  108. @click="handleClick"
  109. >
  110. <HcIcon name="arrow-go-back" style="color:#FF7D43" class="cursor-pointer text-18px font-700" />
  111. </div>
  112. </div>
  113. <div class="hc-search-tree-val">
  114. <el-input
  115. v-model="searchTreeVal"
  116. clearable
  117. block
  118. placeholder="请输入名称关键词检索"
  119. @keyup="searchTreeKeyUp"
  120. >
  121. <template #suffix>
  122. <HcIcon
  123. name="search-2"
  124. ui="text-xl iscusor"
  125. @click="searchTreeClick"
  126. />
  127. </template>
  128. </el-input>
  129. </div>
  130. <div
  131. v-if="isShowLeft"
  132. id="hc-tree-scrollbar"
  133. v-loading="treeLoading"
  134. class="hc-tree-scrollbar"
  135. element-loading-text="获取数据中..."
  136. >
  137. <el-scrollbar
  138. v-show="isSearchTree"
  139. class="scroll-bar-right-16"
  140. >
  141. <HcDataTree
  142. :is-show-collect="true"
  143. :is-show-eye="classType === '1'"
  144. :datas="searchTreeData"
  145. :is-mark="TreeMark"
  146. :menus="ElTreeMenu"
  147. is-type
  148. :auto-expand-keys="TreeAutoExpandKeys"
  149. is-counts default-expand-all is-form-date
  150. :is-show-sync="userInfo?.role_id?.split(',').includes('1123598816738675201')"
  151. @node-tap="wbsElTreeClick"
  152. @menu-tap="ElTreeMenuClick"
  153. @collect="collectClick"
  154. @eye="eyeClick"
  155. />
  156. </el-scrollbar>
  157. <el-scrollbar
  158. v-show="!isSearchTree"
  159. class="scroll-bar-right-16"
  160. >
  161. <HcLazyTree
  162. ref="wbstree"
  163. :is-show-collect="true"
  164. :is-show-eye="classType === '1'"
  165. :is-show-sync="userInfo?.role_id?.split(',').includes('1123598816738675201')"
  166. is-form-date
  167. :auto-expand-keys="TreeAutoExpandKeys"
  168. :is-mark="TreeMark"
  169. :menus="ElTreeMenu"
  170. is-counts
  171. is-type
  172. show-checkbox
  173. check-strictly
  174. @load="treeLoadNode"
  175. @menu-tap="ElTreeMenuClick"
  176. @node-loading="ElTreeNodeLoading"
  177. @node-tap="wbsElTreeClick"
  178. @check="ElTreeNodeCheck"
  179. @collect="collectClick"
  180. @eye="eyeClick"
  181. />
  182. </el-scrollbar>
  183. </div>
  184. </div>
  185. <div class="hc-tree-foot-tip-box">
  186. <div class="dot-view green">已审批</div>
  187. <div class="dot-view black">未填报</div>
  188. <div class="dot-view orange">已填报-待审批</div>
  189. <div class="dot-view blue">已填报-未上报</div>
  190. </div>
  191. </div>
  192. </template>
  193. <hc-tab-card
  194. :tabs="authBtnTabdata"
  195. :tab-key="authBtnTabKey"
  196. @change="authBtnTabClick"
  197. >
  198. <template #extra>
  199. <div v-if="ListItemDatas.length > 0 && isTemplateType" class="mr-2 flex items-center justify-center whitespace-nowrap">
  200. <div class="font-500"> 文件题名</div>
  201. <div class="title-input h-[30px] flex items-center leading-[30px]" :style="{ width: titleInput ? '' : '100px' }">{{ titleInput }}</div>
  202. </div>
  203. <HcTooltip keys="node_base_data">
  204. <el-button
  205. v-if="isTemplateType"
  206. hc-btn
  207. type="primary"
  208. :disabled="
  209. !primaryKeyId
  210. "
  211. @click="nodeBaseDataClick"
  212. >
  213. 节点基础数据
  214. </el-button>
  215. </HcTooltip>
  216. <HcTooltip keys="data-fill-wbs-file-import">
  217. <el-button
  218. v-if="userInfo.dept_id === '1536982621165592577'"
  219. :disabled=" userInfo.dept_id !== '1536982621165592577'"
  220. hc-btn
  221. type="warning" @click="dataImportDialogClick"
  222. >
  223. 资料导入
  224. </el-button>
  225. </HcTooltip>
  226. <HcTooltip keys="wbs_views_sort_btn">
  227. <el-button
  228. v-if="nodeDataInfo?.nodeClass !== 2"
  229. :disabled="ListItemDatas.length <= 0 || (nodeDataInfo?.colorStatus !== 1 && nodeDataInfo?.colorStatus !== 2)"
  230. hc-btn
  231. type="primary"
  232. @click="sortFormClick"
  233. >
  234. 排序
  235. </el-button>
  236. </HcTooltip>
  237. <HcTooltip keys="wbs_views_node_save_btn">
  238. <el-button
  239. v-if="nodeDataInfo?.nodeClass !== 2"
  240. :loading="nodeSaveLoading"
  241. hc-btn
  242. type="primary"
  243. @click="NodeSaveClick"
  244. >
  245. 辅助保存
  246. </el-button>
  247. </HcTooltip>
  248. <HcTooltip keys="wbs_views_drawings">
  249. <el-button
  250. v-if="nodeDataInfo?.nodeClass !== 2"
  251. :disabled="
  252. nodeDataInfo?.drawingsId === -1
  253. || nodeDataInfo?.drawingsId === null
  254. "
  255. hc-btn
  256. color="#e03997"
  257. @click="viewsDrawings"
  258. >
  259. 图纸
  260. </el-button>
  261. </HcTooltip>
  262. <HcTooltip keys="wbs_preview">
  263. <el-button
  264. :disabled="NodeStatus === '1'"
  265. :loading="bussPdfsLoading"
  266. hc-btn
  267. color="#A16222"
  268. @click="bussPdfsClick"
  269. >
  270. 预览
  271. </el-button>
  272. </HcTooltip>
  273. <el-button
  274. hc-btn
  275. color="#A16222"
  276. :disabled="isCanadd"
  277. @click="attachmentModalShow"
  278. >
  279. 查看附件
  280. </el-button>
  281. <el-button
  282. hc-btn
  283. :disabled="isCanadd"
  284. color="#567722"
  285. @click="addFilelist"
  286. >
  287. 上传附件
  288. </el-button>
  289. <HcTooltip v-if="NodeStatus !== '3'" keys="wbs_report">
  290. <el-button
  291. v-if="nodeDataInfo?.nodeClass !== 2"
  292. :disabled="
  293. NodeStatus === '3' || NodeStatus === '1'
  294. "
  295. :loading="reportLoading"
  296. hc-btn
  297. color="#FF976A"
  298. style="color: white"
  299. @click="reportModalClick"
  300. >
  301. 上报
  302. </el-button>
  303. </HcTooltip>
  304. <HcTooltip v-if="NodeStatus === '3'" keys="wbs_abolish">
  305. <el-button
  306. v-if="nodeDataInfo?.nodeClass !== 2"
  307. hc-btn
  308. :laoding="abolishLoaing"
  309. color="#FF976A"
  310. style="color: white"
  311. @click="abolishOneClick"
  312. >
  313. 撤回上报流程
  314. </el-button>
  315. </HcTooltip>
  316. <HcTooltip keys="wbs_views_sync_data_btn">
  317. <el-button
  318. v-if="
  319. authBtnTabKey === '2'
  320. && nodeDataInfo?.nodeClass !== 2
  321. "
  322. hc-btn
  323. color="#37c0fe"
  324. style="color: white"
  325. :loading="syncdataloading"
  326. @click="syncdata"
  327. >
  328. 同步质检资料
  329. </el-button>
  330. <el-button
  331. v-if="nodeDataInfo?.majorDataType == 2"
  332. hc-btn
  333. color="#12C060"
  334. style="color: white"
  335. :loading="syncWorkloading"
  336. @click="syncWork"
  337. >
  338. 同步工序资料
  339. </el-button>
  340. </HcTooltip>
  341. <HcTooltip v-if="NodeStatus !== '3'" keys="wbs_save">
  342. <el-button
  343. v-if="nodeDataInfo?.nodeClass !== 2"
  344. :disabled="
  345. NodeStatus === '3'
  346. || ListItemDatas.length <= 0
  347. "
  348. :loading="tableFormSaveLoading"
  349. hc-btn
  350. color="#12C060"
  351. style="color: white; font-weight: bold"
  352. @click="tableFormSaveClick"
  353. >
  354. 保存数据
  355. </el-button>
  356. </HcTooltip>
  357. </template>
  358. <el-scrollbar
  359. v-if="ListItemDatas.length > 0"
  360. ref="ListItemScrollRef"
  361. >
  362. <CollapseForm
  363. ref="ListItemRef"
  364. :contract-info="
  365. contractInfo?.contractType === 2
  366. ? nodeDataInfo?.contractIdRelation
  367. : contractId
  368. "
  369. :tree-auto-expand-keys="TreeAutoExpandKeys"
  370. :classify="authBtnTabKey"
  371. :contract-id="contractId"
  372. :datas="ListItemDatas"
  373. :draw-type="!isDrawType"
  374. :primary-key-id="primaryKeyId"
  375. :status="NodeStatus"
  376. :tenant-id="userInfo?.tenant_id"
  377. :wbs-temp-id="
  378. projectInfo?.referenceWbsTemplateIdTrial
  379. "
  380. :wbs-type="2"
  381. :treenode-data-info="nodeDataInfo"
  382. :newlistdata="newlistdata"
  383. @offset-top="ListItemOffsetTop"
  384. @renew="getTableDataAll"
  385. @get-list="searchNodeAllTable1"
  386. />
  387. </el-scrollbar>
  388. <hc-empty v-else title="暂无表单" />
  389. </hc-tab-card>
  390. </hc-page-split>
  391. <hc-new-card
  392. v-if="wbsTypeTabKey === 'map'"
  393. id-ref="wbs-node-tree-card-target"
  394. >
  395. <template #header>
  396. <HcTooltip keys="wbs_views_division_btn">
  397. <el-button
  398. class="mr-10"
  399. hc-btn
  400. type="primary"
  401. @click="divisionClick"
  402. >
  403. <HcIcon :line="false" name="node-tree" />
  404. <span>划分变更</span>
  405. </el-button>
  406. </HcTooltip>
  407. <HcNewSwitch
  408. v-if="isDrawer"
  409. :datas="authBtnTabdata"
  410. :keys="authBtnTabKey"
  411. :round="false"
  412. size="default"
  413. @change="authBtnTabClick"
  414. />
  415. </template>
  416. <template #extra>
  417. <HcNewSwitch
  418. :datas="wbsTypeTab"
  419. :keys="wbsTypeTabKey"
  420. size="default"
  421. @change="wbsTypeTabChange"
  422. />
  423. </template>
  424. <NodeTree
  425. ref="NodeTreeRef"
  426. :accordion="NodeTreeAccordion"
  427. :auto-expand-keys="TreeAutoExpandKeys"
  428. :contract-id="contractId"
  429. :is-mark="TreeMark"
  430. :menus="ElTreeMenu"
  431. :project-id="projectId"
  432. @menu-click="NodeTreeMenuClick"
  433. @node-click="NodeTreeClick"
  434. @node-dbl-click="NodeTreeDblClick"
  435. />
  436. <template #action>
  437. <div class="hc-tree-mp-tip-box">
  438. <div class="dot-view green">已审批</div>
  439. <div class="dot-view black">未填报</div>
  440. <div class="dot-view orange">已填报-待审批</div>
  441. <div class="dot-view blue">已填报-未上报</div>
  442. </div>
  443. </template>
  444. <HcDrawer
  445. v-model="isDrawer"
  446. to-id="wbs-node-tree-card-target"
  447. is-close
  448. @close="drawerClose"
  449. >
  450. <!-- 清表列表 -->
  451. <el-scrollbar
  452. v-if="ListItemDatas.length > 0"
  453. ref="ListItemScrollRef"
  454. >
  455. <CollapseForm
  456. ref="ListItemsRef"
  457. :contract-info="
  458. contractInfo?.contractType === 2
  459. ? nodeDataInfo?.contractIdRelation
  460. : contractId
  461. "
  462. :classify="authBtnTabKey"
  463. :contract-id="contractId"
  464. :datas="ListItemDatas"
  465. :draw-type="!isDrawType"
  466. :primary-key-id="primaryKeyId"
  467. :status="NodeStatus"
  468. :tenant-id="userInfo?.tenant_id"
  469. :wbs-temp-id="projectInfo?.referenceWbsTemplateIdTrial"
  470. :wbs-type="2"
  471. @offset-top="ListItemOffsetTop"
  472. @renew="getTableDataAll"
  473. />
  474. </el-scrollbar>
  475. <hc-empty v-else text="暂无表单" />
  476. <!-- 底部按钮区域 -->
  477. <template #action>
  478. <hc-tooltip v-if="NodeStatus !== '3'" keys="wbs_save">
  479. <el-button
  480. :disabled="
  481. NodeStatus === '3' || ListItemDatas.length <= 0
  482. "
  483. :loading="tableFormSaveLoading"
  484. hc-btn
  485. type="primary"
  486. @click="tableFormSaveClick"
  487. >
  488. <HcIcon name="save" />
  489. <span>保存</span>
  490. </el-button>
  491. </hc-tooltip>
  492. <hc-tooltip v-if="NodeStatus !== '3'" keys="wbs_report">
  493. <el-button
  494. :disabled="NodeStatus === '3' || NodeStatus === '1'"
  495. :loading="reportLoading"
  496. hc-btn
  497. @click="reportModalClick"
  498. >
  499. <HcIcon name="send-plane-2" />
  500. <span>上报</span>
  501. </el-button>
  502. </hc-tooltip>
  503. <hc-tooltip keys="wbs_preview">
  504. <el-button
  505. :disabled="NodeStatus === '1'"
  506. :loading="bussPdfsLoading"
  507. hc-btn
  508. @click="bussPdfsClick"
  509. >
  510. <HcIcon name="eye" />
  511. <span>预览</span>
  512. </el-button>
  513. </hc-tooltip>
  514. <hc-tooltip v-if="NodeStatus === '3'" keys="wbs_abolish">
  515. <el-button hc-btn>
  516. <HcIcon name="arrow-go-back" />
  517. <span>撤回上报流程</span>
  518. </el-button>
  519. </hc-tooltip>
  520. <hc-tooltip keys="wbs_views_drawings">
  521. <el-button
  522. :disabled="!nodeDataInfo?.fileUrl"
  523. hc-btn
  524. @click="viewsDrawings"
  525. >
  526. <HcIcon name="image" />
  527. <span>图纸</span>
  528. </el-button>
  529. </hc-tooltip>
  530. <el-button hc-btn @click="attachmentModalShow">
  531. <HcIcon name="file" />
  532. <span>附件</span>
  533. </el-button>
  534. <el-button hc-btn @click="drawerClose">
  535. <HcIcon name="close" />
  536. <span>关闭填报页面</span>
  537. </el-button>
  538. </template>
  539. </HcDrawer>
  540. </hc-new-card>
  541. <!-- 查看图纸 -->
  542. <hc-drag-modal
  543. :is-show="drawingsShow"
  544. close-icon
  545. lefts="145"
  546. title="查看图纸"
  547. tops="100"
  548. ui="hc-image-preview-box"
  549. widths="380px"
  550. @close="drawingsClose"
  551. >
  552. <div class="hc-image-preview-view">
  553. <!-- <el-image-viewer :url-list="[nodeDataInfo.fileUrl]" /> -->
  554. <el-image :src="drawList" />
  555. </div>
  556. </hc-drag-modal>
  557. <!-- 编辑节点 -->
  558. <hc-new-dialog
  559. v-model="editNodeModal"
  560. :loading="editNodeLoading"
  561. title="编辑节点"
  562. widths="600px"
  563. @save="editNodeClick"
  564. >
  565. <el-form
  566. ref="formEditNodeRef"
  567. :model="formEditNodeModel"
  568. :rules="formEditNodeRules"
  569. label-width="auto"
  570. size="large"
  571. >
  572. <el-form-item label="节点名称" prop="title">
  573. <el-input
  574. v-model="formEditNodeModel.title"
  575. placeholder="请输入节点名称"
  576. />
  577. </el-form-item>
  578. <el-form-item label="上级节点">
  579. <el-input
  580. v-model="formEditNodeModel.parent.title"
  581. disabled
  582. />
  583. </el-form-item>
  584. <el-form-item label="节点类型">
  585. <el-select
  586. v-model="formEditNodeModel.nodeType"
  587. :disabled="formEditNodeModel.isCustom !== 1"
  588. block
  589. >
  590. <el-option
  591. v-for="item in nodeTypeData"
  592. :key="item.value"
  593. :label="item.label"
  594. :value="item.value"
  595. />
  596. </el-select>
  597. </el-form-item>
  598. <el-form-item label="时间" prop="digitizeTime">
  599. <el-date-picker
  600. v-model="formEditNodeModel.digitizeTime"
  601. class="block"
  602. format="YYYY-MM-DD"
  603. placeholder="请选择"
  604. type="date"
  605. value-format="YYYY-MM-DD"
  606. />
  607. </el-form-item>
  608. <el-form-item
  609. v-if="formEditNodeModel.nodeClass == 2"
  610. label="内业资料类型"
  611. prop="majorDataType"
  612. >
  613. <el-select
  614. v-model="formEditNodeModel.majorDataType"
  615. block
  616. >
  617. <el-option
  618. v-for="item in majorDataTypeOptions"
  619. :key="item.value"
  620. :label="item.label"
  621. :value="item.value"
  622. />
  623. </el-select>
  624. </el-form-item>
  625. <el-form-item
  626. v-if="formEditNodeModel.notExsitChild"
  627. label="标准分类"
  628. prop="className"
  629. >
  630. <el-select
  631. v-model="formEditNodeModel.className"
  632. block
  633. @change="changeStandType"
  634. >
  635. <el-option
  636. v-for="item in standardTypeOptions"
  637. :key="item.value"
  638. :label="item.label"
  639. :value="item.value"
  640. />
  641. </el-select>
  642. </el-form-item>
  643. <el-form-item
  644. v-if="formEditNodeModel.notExsitChild"
  645. label="单位名称"
  646. prop="unitName"
  647. >
  648. <el-select v-model="formEditNodeModel.unitName" block>
  649. <el-option
  650. v-for="item in unitNameOptions"
  651. :key="item.value"
  652. :label="item.dictValue"
  653. :value="item.dictKey"
  654. />
  655. </el-select>
  656. </el-form-item>
  657. <el-row v-if="formEditNodeModel.nodeClass === 2" :gutter="24">
  658. <el-col :span="12">
  659. <el-form-item prop="unitNum" label="单元个数">
  660. <el-input-number
  661. v-model="formEditNodeModel.unitNum"
  662. placeholder="请输入单元个数"
  663. :controls="false"
  664. :min="0"
  665. :precision="0"
  666. class="w-100"
  667. />
  668. </el-form-item>
  669. </el-col>
  670. <el-col :span="12">
  671. <el-form-item prop="excellentNum" label="优良个数">
  672. <el-input-number
  673. v-model="formEditNodeModel.excellentNum"
  674. placeholder="请输入优良个数"
  675. :controls="false"
  676. :min="0"
  677. :precision="0"
  678. class="w-100"
  679. />
  680. </el-form-item>
  681. </el-col>
  682. </el-row>
  683. <el-tooltip
  684. v-if="formEditNodeModel?.isReferenceNumber === 0"
  685. class="item"
  686. effect="light"
  687. content="当前合同段未开启引用标号功能,表格无法获取,请联系维护人员处理"
  688. placement="top"
  689. >
  690. <el-form-item label="划分编号">
  691. <el-input
  692. v-model="formEditNodeModel.partitionCode"
  693. placeholder="请输入划分编号"
  694. />
  695. </el-form-item>
  696. </el-tooltip>
  697. <el-form-item v-else label="划分编号">
  698. <el-input
  699. v-model="formEditNodeModel.partitionCode"
  700. placeholder="请输入划分编号"
  701. />
  702. </el-form-item>
  703. <el-form-item class="hc-position-input-icon" label="模板位置">
  704. <el-input
  705. v-model="formEditNodeModel.position"
  706. :autosize="{ minRows: 3, maxRows: 6 }"
  707. type="textarea"
  708. />
  709. <el-tooltip content="一键复制模板位置">
  710. <HcIcon
  711. name="file-copy-2"
  712. @click="
  713. copyPositionText(formEditNodeModel.position)
  714. "
  715. />
  716. </el-tooltip>
  717. </el-form-item>
  718. <el-form-item class="hc-position-input-icon mt-2" label="系统模板">
  719. <el-input
  720. v-model="formEditNodeModel.privateTemplate"
  721. :autosize="{ minRows: 3, maxRows: 6 }"
  722. type="textarea"
  723. />
  724. <el-tooltip content="一键复制系统模板">
  725. <HcIcon
  726. name="file-copy-2"
  727. @click="
  728. copyPositionText(formEditNodeModel.privateTemplate)
  729. "
  730. />
  731. </el-tooltip>
  732. </el-form-item>
  733. </el-form>
  734. </hc-new-dialog>
  735. <!-- 复制节点 -->
  736. <hc-new-dialog
  737. v-model="copyNodeModal"
  738. :loading="copyNodeLoading"
  739. :widths="copyNodeTabKey === '1' ? '600px' : '1200px'"
  740. loading-text="复制节点中,请耐心等待..."
  741. title="复制节点"
  742. >
  743. <div class="header-new-switch">
  744. <el-form
  745. ref="formCopyNodeModelRef"
  746. :model="formCopyNodeModel"
  747. label-position="left"
  748. :rules="formCopyNodeModelRules"
  749. label-width="auto"
  750. size="large"
  751. >
  752. <el-form-item
  753. label="是否复制数据"
  754. prop="isCopyData"
  755. style="margin-bottom: 0"
  756. >
  757. <!-- <el-input v-model="formCopyNodeModel.classify" placeholder="请输入节点名称"/> -->
  758. <el-radio-group v-model="isCopyData">
  759. <el-radio :value="1">是</el-radio>
  760. <el-radio :value="0">否</el-radio>
  761. </el-radio-group>
  762. </el-form-item>
  763. <el-form-item
  764. v-if="isCopyData === 1"
  765. label="所属方"
  766. prop="classify"
  767. style="margin-bottom: 0"
  768. >
  769. <!-- <el-input v-model="formCopyNodeModel.classify" placeholder="请输入节点名称"/> -->
  770. <el-checkbox-group v-model="classifyList">
  771. <el-checkbox value="施工" :disabled="authBtnTabKey == 2">施工</el-checkbox>
  772. <el-checkbox value="监理">监理</el-checkbox>
  773. </el-checkbox-group>
  774. </el-form-item>
  775. </el-form>
  776. </div>
  777. <div v-if="copyNodeTabKey === '1'" class="copy-node-form-box">
  778. <el-form
  779. ref="formCopyNodeModelRef"
  780. :model="formCopyNodeModel"
  781. :rules="formCopyNodeModelRules"
  782. label-width="auto"
  783. size="large"
  784. >
  785. <el-form-item
  786. v-if="copyNodeTabKey === '1'"
  787. label="节点名称"
  788. prop="title"
  789. style="margin-bottom: 0"
  790. >
  791. <el-input
  792. v-model="formCopyNodeModel.title"
  793. placeholder="请输入节点名称"
  794. />
  795. </el-form-item>
  796. <el-form-item
  797. v-if="copyNodeTabKey === '1'"
  798. label="划分编号"
  799. prop="partitionCode"
  800. style="margin-top: 10px"
  801. >
  802. <el-input
  803. v-model="formCopyNodeModel.partitionCode"
  804. placeholder="请输入划分编号"
  805. />
  806. </el-form-item>
  807. </el-form>
  808. </div>
  809. <div v-if="copyNodeTabKey === '3'" class="copy-node-form-box">
  810. <el-form
  811. ref="formCopyNodeModelRef"
  812. :model="formCopyNodeModel"
  813. :rules="formCopyNodeModelRules"
  814. label-width="auto"
  815. size="large"
  816. >
  817. <el-form-item
  818. label="所属方"
  819. prop="classify"
  820. style="margin-bottom: 0"
  821. >
  822. <!-- <el-input v-model="formCopyNodeModel.classify" placeholder="请输入节点名称"/> -->
  823. <el-checkbox-group v-model="classifyList">
  824. <el-checkbox value="施工">施工</el-checkbox>
  825. <el-checkbox value="监理">监理</el-checkbox>
  826. </el-checkbox-group>
  827. </el-form-item>
  828. </el-form>
  829. </div>
  830. <div v-if="copyNodeTabKey !== '1'" class="copy-node-many-box">
  831. <div class="copy-node-many-tree">
  832. <el-scrollbar>
  833. <hc-lazy-tree
  834. :auto-expand-keys="TreeAutoExpandKeys"
  835. is-type
  836. @load="treeLoadNode"
  837. @node-tap="copyNodeElTreeClick"
  838. />
  839. </el-scrollbar>
  840. </div>
  841. <div class="copy-node-many-table">
  842. <el-scrollbar>
  843. <el-table :data="copyNodeTable" border>
  844. <el-table-column
  845. label="复制到的位置"
  846. prop="title"
  847. />
  848. <el-table-column
  849. v-if="copyNodeTabKey === '2'"
  850. label="节点名称"
  851. prop="nodeName"
  852. >
  853. <template #default="{ row }">
  854. <el-form
  855. ref="copyNodeTableRef"
  856. :model="row"
  857. :rules="copyNodeTableRules"
  858. label-width="0"
  859. size="large"
  860. >
  861. <el-form-item
  862. prop="nodeName"
  863. style="margin-bottom: 0"
  864. >
  865. <el-input
  866. v-model="row.nodeName"
  867. placeholder="请输入节点名称"
  868. />
  869. </el-form-item>
  870. </el-form>
  871. </template>
  872. </el-table-column>
  873. <el-table-column
  874. v-if="copyNodeTabKey === '2'"
  875. label="划分编号"
  876. prop="partitionCode"
  877. >
  878. <template #default="{ row }">
  879. <el-form
  880. ref="copyNodeTableRef"
  881. :model="row"
  882. :rules="copyNodeTableRules"
  883. label-width="0"
  884. size="large"
  885. >
  886. <el-form-item
  887. prop="partitionCode"
  888. style="margin-bottom: 0"
  889. >
  890. <el-input
  891. v-model="row.partitionCode"
  892. placeholder="请输入划分编号"
  893. />
  894. </el-form-item>
  895. </el-form>
  896. </template>
  897. </el-table-column>
  898. <el-table-column
  899. align="center"
  900. label="操作"
  901. prop="action"
  902. width="120"
  903. >
  904. <template #default="{ _, $index }">
  905. <el-button
  906. plain
  907. type="danger"
  908. @click="copyNodeTableDel($index)"
  909. >
  910. 删除
  911. </el-button>
  912. </template>
  913. </el-table-column>
  914. </el-table>
  915. </el-scrollbar>
  916. </div>
  917. </div>
  918. <template #footer>
  919. <div class="lr-dialog-footer">
  920. <div class="left">
  921. <template
  922. v-for="(item, index) in copyNodeTab"
  923. :key="index"
  924. >
  925. <el-button
  926. v-if="item?.key === copyNodeTabKey"
  927. plain
  928. size="large"
  929. type="primary"
  930. @click="copyNodeTabChange(item?.key)"
  931. >
  932. {{ item.name }}
  933. </el-button>
  934. <el-button
  935. v-else
  936. bg
  937. size="large"
  938. text
  939. @click="copyNodeTabChange(item?.key)"
  940. >
  941. {{ item.name }}
  942. </el-button>
  943. </template>
  944. </div>
  945. <div class="right">
  946. <el-button
  947. :disabled="copyNodeLoading"
  948. size="large"
  949. @click="copyNodeModal = false"
  950. >
  951. 取消
  952. </el-button>
  953. <el-button
  954. :loading="copyNodeLoading"
  955. hc-btn
  956. type="primary"
  957. @click="copyNodeClick"
  958. >
  959. 提交
  960. </el-button>
  961. </div>
  962. </div>
  963. </template>
  964. </hc-new-dialog>
  965. <!-- 新增子节点 -->
  966. <hc-new-dialog
  967. v-model="addNodeModal"
  968. :loading="addNodeLoading"
  969. loading-text="新增节点中,请耐心等待..."
  970. title="新增子节点"
  971. widths="720px"
  972. is-table
  973. >
  974. <el-alert
  975. :closable="false"
  976. title="双击节点,可编辑节点名称,编辑完成后,请按回车或输入框消失后,再点提交"
  977. type="warning"
  978. />
  979. <HcTreeNode
  980. v-if="addTreeNodeType === '1'"
  981. :node-id="addTreeNodeId"
  982. :old-id="addTreeNodeOldId"
  983. :contract-id="contractId"
  984. :wbs-id="projectInfo.referenceWbsTemplateId"
  985. :project-id="projectId"
  986. :is-custom="isCustom"
  987. @check-change="addTreeNodeCheckChange"
  988. />
  989. <HcTreeNode
  990. v-if="addTreeNodeType === '3'"
  991. :node-id="addTreeNodeId"
  992. :old-id="addTreeNodeOldId"
  993. :contract-id="contractId"
  994. :wbs-id="projectInfo.referenceWbsTemplateId"
  995. :project-id="projectId"
  996. :is-custom="isCustom"
  997. :strictly="true"
  998. :only-children-check="true"
  999. @check-change="addTreeNodeCheckChange"
  1000. />
  1001. <HcTreeNode
  1002. v-if="addTreeNodeType === '2'"
  1003. :node-id="addTreeNodeId"
  1004. :old-id="addTreeNodeOldId"
  1005. :contract-id="contractId"
  1006. :wbs-id="projectInfo.referenceWbsTemplateId"
  1007. :project-id="projectId"
  1008. strictly
  1009. :is-custom="isCustom"
  1010. @check-change="addTreeNodeCheckChange"
  1011. />
  1012. <template #footer>
  1013. <div class="lr-dialog-footer">
  1014. <div class="left flex items-center">
  1015. <div class="mr-4">选中方式:</div>
  1016. <el-radio-group v-model="addTreeNodeType">
  1017. <el-radio value="3">当前及子节点</el-radio>
  1018. <el-radio class="ml-4" value="2">
  1019. 仅当前节点
  1020. </el-radio>
  1021. <el-radio value="1">当前及父节点</el-radio>
  1022. <!-- <el-radio value="1">当前子及节点</el-radio> -->
  1023. </el-radio-group>
  1024. </div>
  1025. <div class="right">
  1026. <el-button size="large" @click="addNodeModal = false">
  1027. 取消
  1028. </el-button>
  1029. <el-button
  1030. :loading="addNodeLoading"
  1031. hc-btn
  1032. type="primary"
  1033. @click="addNodeClick"
  1034. >
  1035. 提交
  1036. </el-button>
  1037. </div>
  1038. </div>
  1039. </template>
  1040. </hc-new-dialog>
  1041. <!-- 新增自定义节点 -->
  1042. <hc-new-dialog
  1043. v-model="addNodeModalCus"
  1044. :loading="addNodeLoadingCus"
  1045. loading-text="新增节点中,请耐心等待..."
  1046. title="新增自定义节点(水利工程)"
  1047. widths="720px"
  1048. @save="addNodeClickCur"
  1049. >
  1050. <el-form
  1051. ref="formWaterNodeRef"
  1052. :model="formWaterNodeModel"
  1053. :rules="formWaterNodeRules"
  1054. label-width="auto"
  1055. size="large"
  1056. label-position="left"
  1057. >
  1058. <el-form-item label="节点名称" prop="nodeName">
  1059. <el-input
  1060. v-model="formWaterNodeModel.nodeName"
  1061. placeholder="请输入节点名称"
  1062. />
  1063. </el-form-item>
  1064. <el-form-item label="节点类型" prop="nodeType">
  1065. <el-select v-model="formWaterNodeModel.nodeType" block>
  1066. <el-option
  1067. v-for="item in nodeTypeData"
  1068. :key="item.value"
  1069. :label="item.label"
  1070. :value="item.value"
  1071. />
  1072. </el-select>
  1073. </el-form-item>
  1074. <el-form-item label="编号" prop="number">
  1075. <el-input
  1076. v-model="formWaterNodeModel.number"
  1077. placeholder="请输入编号"
  1078. />
  1079. </el-form-item>
  1080. </el-form>
  1081. </hc-new-dialog>
  1082. <!-- 新增自定义节点-数字化文件 -->
  1083. <hc-new-dialog
  1084. v-model="addNodeModalData"
  1085. :loading="addNodeLoadingData"
  1086. loading-text="新增节点中,请耐心等待..."
  1087. title="新增自定义节点(数字化文件)"
  1088. widths="720px"
  1089. @save="addNodeClickData"
  1090. >
  1091. <el-form
  1092. ref="formDataNodeRef"
  1093. :model="formDataNodeModel"
  1094. :rules="formDataNodeRules"
  1095. label-width="auto"
  1096. size="large"
  1097. >
  1098. <el-form-item label="节点名称" prop="nodeName">
  1099. <el-input
  1100. v-model="formDataNodeModel.nodeName"
  1101. placeholder="请输入节点名称"
  1102. />
  1103. </el-form-item>
  1104. <el-form-item label="节点类型" prop="nodeType">
  1105. <el-select v-model="formDataNodeModel.nodeType" block>
  1106. <el-option
  1107. v-for="item in nodeTypeData"
  1108. :key="item.value"
  1109. :label="item.label"
  1110. :value="item.value"
  1111. />
  1112. </el-select>
  1113. </el-form-item>
  1114. <el-form-item label="是否含单元评定" prop="isClassifition">
  1115. <el-radio-group v-model="formDataNodeModel.isClassifition">
  1116. <el-radio :value="1">是</el-radio>
  1117. <el-radio :value="0">否</el-radio>
  1118. </el-radio-group>
  1119. </el-form-item>
  1120. <el-form-item label="时间" prop="digitizeTime">
  1121. <el-date-picker
  1122. v-model="formDataNodeModel.digitizeTime"
  1123. class="block"
  1124. format="YYYY-MM-DD"
  1125. placeholder="请选择"
  1126. type="date"
  1127. value-format="YYYY-MM-DD"
  1128. />
  1129. </el-form-item>
  1130. <el-form-item
  1131. label="内业资料类型"
  1132. prop="majorDataType"
  1133. >
  1134. <el-select
  1135. v-model="formDataNodeModel.majorDataType"
  1136. block
  1137. >
  1138. <el-option
  1139. v-for="item in majorDataTypeOptions"
  1140. :key="item.value"
  1141. :label="item.label"
  1142. :value="item.value"
  1143. />
  1144. </el-select>
  1145. </el-form-item>
  1146. <el-form-item
  1147. v-if="formDataNodeModel.isClassifition === 1"
  1148. label="标准分类"
  1149. prop="className"
  1150. >
  1151. <el-select
  1152. v-model="formDataNodeModel.className"
  1153. block
  1154. @change="changeStandType"
  1155. >
  1156. <el-option
  1157. v-for="item in standardTypeOptions"
  1158. :key="item.value"
  1159. :label="item.label"
  1160. :value="item.value"
  1161. />
  1162. </el-select>
  1163. </el-form-item>
  1164. <el-form-item
  1165. v-if="formDataNodeModel.isClassifition === 1"
  1166. label="单元名称"
  1167. prop="unitName"
  1168. >
  1169. <el-select v-model="formDataNodeModel.unitName" block>
  1170. <el-option
  1171. v-for="item in unitNameOptions"
  1172. :key="item.value"
  1173. :label="item.dictValue"
  1174. :value="item.dictKey"
  1175. />
  1176. </el-select>
  1177. </el-form-item>
  1178. <el-row
  1179. v-if="formDataNodeModel.isClassifition === 1"
  1180. :gutter="24"
  1181. >
  1182. <el-col :span="12">
  1183. <el-form-item prop="unitNum" label="单元个数">
  1184. <el-input-number
  1185. v-model="formDataNodeModel.unitNum"
  1186. placeholder="请输入单元个数"
  1187. :controls="false"
  1188. :min="0"
  1189. :precision="0"
  1190. class="w-100"
  1191. />
  1192. </el-form-item>
  1193. </el-col>
  1194. <el-col :span="12">
  1195. <el-form-item prop="excellentNum" label="优良个数">
  1196. <el-input-number
  1197. v-model="formDataNodeModel.excellentNum"
  1198. placeholder="请输入优良个数"
  1199. :controls="false"
  1200. :min="0"
  1201. :precision="0"
  1202. class="w-100"
  1203. />
  1204. </el-form-item>
  1205. </el-col>
  1206. </el-row>
  1207. </el-form>
  1208. </hc-new-dialog>
  1209. <!-- 调整排序 -->
  1210. <hc-new-dialog
  1211. v-model="sortNodeModal"
  1212. :loading="sortNodeLoading"
  1213. title="调整排序"
  1214. widths="700px"
  1215. @save="sortNodeClick"
  1216. >
  1217. <el-alert
  1218. :closable="false"
  1219. title="可拖动排序,也可在后面点击图标,切换排序"
  1220. type="warning"
  1221. />
  1222. <div class="sort-node-body-box list-group header">
  1223. <div class="list-group-item">
  1224. <div class="index-box">序号</div>
  1225. <div class="title-box">节点名称</div>
  1226. <div class="icon-box">排序</div>
  1227. </div>
  1228. </div>
  1229. <Draggable
  1230. :list="sortNodeData"
  1231. class="sort-node-body-box list-group"
  1232. ghost-class="ghost"
  1233. item-key="id"
  1234. @end="sortNodeDrag = false"
  1235. @start="sortNodeDrag = true"
  1236. >
  1237. <template #item="{ element, index }">
  1238. <div class="list-group-item">
  1239. <div class="index-box">{{ index + 1 }}</div>
  1240. <div class="title-box">{{ element.title }}</div>
  1241. <div class="icon-box">
  1242. <span class="icon" @click="downSortClick(index)">
  1243. <HcIcon name="arrow-down" ui="text-lg" />
  1244. </span>
  1245. <span class="icon" @click="upSortClick(index)">
  1246. <HcIcon name="arrow-up" ui="text-lg" />
  1247. </span>
  1248. </div>
  1249. </div>
  1250. </template>
  1251. </Draggable>
  1252. </hc-new-dialog>
  1253. <!-- 批量上报审批 -->
  1254. <hc-report-modal
  1255. :addition="reportAddition"
  1256. :contract-id="
  1257. contractInfo?.contractType == 2
  1258. ? nodeDataInfo?.contractIdRelation
  1259. : contractId
  1260. "
  1261. :flow-contract-id="nodeDataInfo?.contractId"
  1262. :ids="reportIds"
  1263. :table-owner="authBtnTabKey"
  1264. :classify-type="classType"
  1265. :project-id="projectId"
  1266. :show="showReportModal"
  1267. :task-name="reportTaskName"
  1268. :type-data="reportTypeData"
  1269. title="批量上报审批"
  1270. type="wbs"
  1271. url="informationWriteQuery/taskOne"
  1272. @finish="showReportFinish"
  1273. @hide="showReportModal = false"
  1274. />
  1275. <!-- 查看附件 -->
  1276. <hc-new-dialog
  1277. v-model="attachmentModal"
  1278. is-table
  1279. title="附件列表"
  1280. widths="780px"
  1281. >
  1282. <div
  1283. v-if="attachmentList.length > 0"
  1284. v-loading="attachmentListLoaing"
  1285. >
  1286. <div class="mb-1 p-2">
  1287. <span class="text-orange">按住鼠标拖动文件可进行附件列表排序</span>
  1288. </div>
  1289. <div
  1290. v-for="item in attachmentList"
  1291. :key="item.id"
  1292. class="hc-attachment-card"
  1293. :data-node-id="item.id"
  1294. >
  1295. <div class="hc-attachment-header">
  1296. {{ item?.nodeName }}
  1297. <!-- <el-button type="success" :loading="saveFileOrderLoad" style="float:right" @click="saveFileOrder">确定排序</el-button> -->
  1298. </div>
  1299. <div
  1300. :ref="setAttachmentListRef"
  1301. class="hc-attachment-content"
  1302. >
  1303. <div
  1304. v-for="item1 in item.fileList"
  1305. :key="item1.id"
  1306. class="hc-attachment-item"
  1307. >
  1308. <div class="hc-attachment-file-name">
  1309. <HcIcon name="drag-move-2" class="text-blue" />
  1310. <HcIcon name="attachment" class="ml-2" />
  1311. <div class="name">{{ item1?.name }}</div>
  1312. </div>
  1313. <div class="hc-attachment-btn-box">
  1314. <el-button
  1315. plain
  1316. size="small"
  1317. type="primary"
  1318. @click="previewFile(item1)"
  1319. >
  1320. <HcIcon name="eye" />
  1321. <span>预览</span>
  1322. </el-button>
  1323. <el-button
  1324. v-if="NodeStatus !== 3 || nodeDataInfo?.nodeClass === 2"
  1325. plain
  1326. size="small"
  1327. style="margin-left: 16px"
  1328. type="danger"
  1329. :loading="item1?.loading"
  1330. @click="delFile(item1)"
  1331. >
  1332. <HcIcon name="close" />
  1333. <span>删除</span>
  1334. </el-button>
  1335. </div>
  1336. </div>
  1337. </div>
  1338. </div>
  1339. </div>
  1340. <template #footer>
  1341. <el-button @click="attachmentModal = false">关闭</el-button>
  1342. <el-button type="primary" :loading="saveFileOrderLoad" :disabled="attachmentList.length === 0" @click="saveFileOrder">确定排序</el-button>
  1343. </template>
  1344. </hc-new-dialog>
  1345. <!-- 上传文件 -->
  1346. <hc-new-dialog
  1347. v-model="uploadModal"
  1348. :footer="false"
  1349. title="上传文件"
  1350. widths="38rem"
  1351. @close="uploadModalClose"
  1352. >
  1353. <div class="mb-4">
  1354. <span style="color: red">*</span> 选择附件类型:
  1355. <el-select
  1356. v-model="typevalue"
  1357. filterable
  1358. placeholder="请选择"
  1359. style="width: 240px"
  1360. clearable
  1361. @change="changeType"
  1362. >
  1363. <el-option
  1364. v-for="item in typeoptions"
  1365. :key="item.value"
  1366. :label="item.label"
  1367. :value="item.value"
  1368. />
  1369. </el-select>
  1370. </div>
  1371. <HcUpload
  1372. :datas="uploadData"
  1373. :file-list="fileListData"
  1374. :is-canupload="false"
  1375. action="#"
  1376. :auto-upload="false"
  1377. :typevalue="typevalue"
  1378. @change="uploadChange"
  1379. @close="uploadModalClose"
  1380. @update="uploadUpdate"
  1381. />
  1382. </hc-new-dialog>
  1383. <!-- 表单排序 -->
  1384. <hc-new-dialog
  1385. v-model="sortFormShow"
  1386. is-table
  1387. title="排序"
  1388. widths="800px"
  1389. is-footer-center
  1390. @close="sortFormClose"
  1391. >
  1392. <hc-table
  1393. ref="tableSortFormRef"
  1394. :column="tableSortFormColumn"
  1395. :datas="tableSortFormData"
  1396. is-row-drop
  1397. is-sort
  1398. quick-sort
  1399. @row-drop="sortFormDropTap"
  1400. @row-sort="rowSortFormTap"
  1401. />
  1402. <template #footer>
  1403. <el-button hc-btn @click="sortFormClose">取消</el-button>
  1404. <el-button
  1405. hc-btn
  1406. type="primary"
  1407. :loading="sortFormLoading"
  1408. @click="sortFormSubmit"
  1409. >
  1410. 提交
  1411. </el-button>
  1412. </template>
  1413. </hc-new-dialog>
  1414. <!-- 节点基础数据 -->
  1415. <hc-new-dialog
  1416. v-model="nodeBaseDataModalDialog"
  1417. title="节点基础数据"
  1418. widths="800px"
  1419. is-footer-center
  1420. :loading="nodeBaseDataLoad"
  1421. @close="nodeBaseDataModalClose"
  1422. @save="nodeBaseDataModalSave"
  1423. >
  1424. <template #header>
  1425. <div class="flex justify-between text-orange">
  1426. <span>提示: 若填写框没有内容,则没有该节点类型。编保存后,需再次保存后才能生效。</span>
  1427. <el-button type="success" size="small" @click="resetForm">刷新</el-button>
  1428. </div>
  1429. </template>
  1430. <el-form :model="autoFormData" label-width="120px" inline>
  1431. <el-form-item label="单位工程类型:" prop="unit">
  1432. <el-input v-model="autoFormData.unit" />
  1433. </el-form-item>
  1434. <el-form-item label="单位工程:" prop="subUnit">
  1435. <el-input v-model="autoFormData.subUnit" />
  1436. </el-form-item>
  1437. <el-form-item label="分部工程:" prop="division">
  1438. <el-input v-model="autoFormData.division" />
  1439. </el-form-item>
  1440. <el-form-item label="子分部工程:" prop="subDivision">
  1441. <el-input v-model="autoFormData.subDivision" />
  1442. </el-form-item>
  1443. <el-form-item label="分项工程:" prop="item">
  1444. <el-input v-model="autoFormData.item" />
  1445. </el-form-item>
  1446. <el-form-item label="子分项工程:" prop="subItem">
  1447. <el-input v-model="autoFormData.subItem" />
  1448. </el-form-item>
  1449. <el-form-item label="工序:" prop="processes">
  1450. <el-input v-model="autoFormData.processes" />
  1451. </el-form-item>
  1452. </el-form>
  1453. </hc-new-dialog>
  1454. <div
  1455. v-if="collectDialog"
  1456. class="collect-modal collectModalStyle"
  1457. :style="{
  1458. left: `${collectDialogPosition?.left}px`,
  1459. top: `${collectDialogPosition?.top}px`,
  1460. display: collectDialog ? 'block' : 'none',
  1461. }"
  1462. >
  1463. <!-- 模态框头部 -->
  1464. <div class="collect-modal-header">
  1465. <h3>添加到文件夹</h3>
  1466. <button class="close-btn" @click="collectModalClose">×</button>
  1467. </div>
  1468. <!-- 模态框内容 -->
  1469. <div class="collect-modal-body">
  1470. <el-form
  1471. v-if="collectList.length > 0"
  1472. ref="collectFormRef"
  1473. :model="collectForm"
  1474. :rules="collectRules"
  1475. >
  1476. <el-form-item label="文件夹" prop="id">
  1477. <el-select v-model="collectForm.id" v-loading="collectLoad" placeholder="请选择" clearable @change="checkCollect">
  1478. <el-option v-for="item in collectList" :key="item.id" :label="item.name" :value="item.id" />
  1479. </el-select>
  1480. </el-form-item>
  1481. </el-form>
  1482. <el-alert v-else title="请先创建文件夹" type="warning" :closable="false" />
  1483. </div>
  1484. <!-- 模态框底部 -->
  1485. <div v-if="collectList.length > 0" class="collect-modal-footer">
  1486. <el-button @click="collectModalClose">取消</el-button>
  1487. <el-button type="primary" :loading="saveCollectLoad" @click="collectModalSave">确定</el-button>
  1488. </div>
  1489. </div>
  1490. <JumpTreeDialog
  1491. v-model="moveDialogShow"
  1492. :contract-id="contractId"
  1493. :class-type="classType"
  1494. :auth-btn-tab-key="authBtnTabKey"
  1495. :primary-key-id=" primaryKeyId"
  1496. :tree-auto-expand-keys="TreeAutoExpandKeys"
  1497. @save="moveSaveClick"
  1498. />
  1499. <!-- 关联构建编码 -->
  1500. <linkData
  1501. v-model="wbsLinkModal"
  1502. @save="linkSaveClick"
  1503. @close="linkModalClose"
  1504. />
  1505. <!--
  1506. 资料导入 -->
  1507. <!-- 引入上传弹窗组件 -->
  1508. <FileUploadDialog
  1509. v-model="divisionImportDialog"
  1510. />
  1511. </div>
  1512. </template>
  1513. <script setup>
  1514. import { nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
  1515. import { useRoute, useRouter } from 'vue-router'
  1516. import { useAppStore } from '~src/store'
  1517. import { HcIsButton } from '~src/plugins/IsButtons'
  1518. import CollapseForm from './collapse-form/index.vue'
  1519. import NodeTree from './components/nodeTree/index.vue'
  1520. import HcTreeNode from './components/HcTreeNode.vue'
  1521. import { HcFirmMsg, HcUploadFileApi } from 'hc-vue3-ui'
  1522. import { getStoreValue, setStoreValue } from '~src/utils/storage'
  1523. import { getDictionaryData } from '~uti/tools'
  1524. import { getChildList } from '~api/other'
  1525. import Sortable from 'sortablejs'
  1526. import {
  1527. arrToKey,
  1528. deepClone,
  1529. formValidate,
  1530. getArrValue,
  1531. getObjVal,
  1532. getObjValue,
  1533. isNullES,
  1534. isString,
  1535. setCopyText,
  1536. } from 'js-fast-way'
  1537. import {
  1538. eVisaTaskCheckApi,
  1539. getDictionary,
  1540. getDictionaryBiz,
  1541. userConfigSave,
  1542. } from '~api/other'
  1543. import wbsApi from '~api/data-fill/wbs'
  1544. import queryApi from '~api/data-fill/query'
  1545. import nodeBaseApi from '~api/data-fill/nodebaseinfo'
  1546. import { useClick } from 'hc-vue3-ui'
  1547. import Draggable from 'vuedraggable'
  1548. import { HcDelMsg, NewDelMsg } from 'hc-vue3-ui'
  1549. import HcUpload from './components/HcUpload.vue'
  1550. import { toPdfPage } from '~uti/btn-auth'
  1551. import website from '~src/config'
  1552. import JumpTreeDialog from './components/JumpTreeDialog.vue'
  1553. import collectApi from '~api/data-fill/collect'
  1554. import linkData from './components/linkData.vue'
  1555. import FileUploadDialog from './components/dataImport.vue'
  1556. //初始变量
  1557. const router = useRouter()
  1558. const useRoutes = useRoute()
  1559. const useAppState = useAppStore()
  1560. //全局变量
  1561. const projectId = ref(useAppState.projectId)
  1562. const contractId = ref(useAppState.contractId)
  1563. const projectInfo = ref(useAppState.projectInfo)
  1564. const contractInfo = ref(useAppState.contractInfo)
  1565. const isCollapse = ref(useAppState.getCollapse)
  1566. const userInfo = ref(useAppState.getUserInfo)
  1567. const isLayout = ref(useAppState.isLayout)
  1568. const leftWidth = ref(440)
  1569. const isTemplateType = ref(useAppState.contractInfo?.templateType === 2)
  1570. //路由参数
  1571. const routerQuery = useRoutes?.query
  1572. // const typeName = routerQuery?.type || 'map'
  1573. const typeName = routerQuery?.type || 'tree'
  1574. //是否是抽屉
  1575. const isDrawType = ref(true)
  1576. //自动展开缓存
  1577. const TreeAutoExpandKeys = ref(getStoreValue('wbsTreeExpandKeys') || [])
  1578. //树搜索
  1579. const isSearchTree = ref(false)
  1580. const searchTreeHeight = ref()
  1581. const getSearchTreeData = async (type) => {
  1582. treeLoading.value = true
  1583. let response
  1584. if (type === 'history') {
  1585. response = await collectApi.saveHistory({
  1586. contractId: contractId.value || '',
  1587. tableOwner: authBtnTabKey.value,
  1588. queryValue: searchTreeVal.value,
  1589. })
  1590. } else if (type === 'hide') {
  1591. response = await collectApi.getHiddenTreeNode({
  1592. contractId: contractId.value,
  1593. tableOwner: authBtnTabKey.value,
  1594. queryValue: searchTreeVal.value,
  1595. })
  1596. } else if (type === 'folder') {
  1597. response = await collectApi.getCollectTreeNodeByQuery({
  1598. folderId:folderId.value,
  1599. contractId: contractId.value,
  1600. tableOwner: authBtnTabKey.value,
  1601. queryValue: searchTreeVal.value,
  1602. })
  1603. } else {
  1604. response = await queryApi.getTreeNodeByQueryValueAndContractId({
  1605. contractId: contractId.value,
  1606. tableOwner: authBtnTabKey.value,
  1607. queryValue: searchTreeVal.value,
  1608. })
  1609. }
  1610. const { error, code, data } = response
  1611. if (!error && code === 200) {
  1612. let treedata = getArrValue(data)
  1613. searchTreeData.value = treedata
  1614. treeLoading.value = false
  1615. } else {
  1616. treeLoading.value = false
  1617. searchTreeData.value = []
  1618. }
  1619. }
  1620. //监听
  1621. const searchTreeVal = ref('')
  1622. watch(
  1623. () => [useAppState.getCollapse, searchTreeVal.value],
  1624. ([Collapse, search]) => {
  1625. isCollapse.value = Collapse
  1626. if (search.length == 0) {
  1627. if (!isLookHide.value) {
  1628. getSearchTreeData('hide')
  1629. return
  1630. }
  1631. if (isLookHistory.value) {
  1632. getSearchTreeData('history')
  1633. return
  1634. }
  1635. isSearchTree.value = false
  1636. }
  1637. },
  1638. )
  1639. //加载树需要的classType
  1640. const classType = ref('')
  1641. watch(
  1642. () => [classType.value, useAppState.isLayout],
  1643. ([classify, isLay]) => {
  1644. isLayout.value = isLay || ''
  1645. if (classify) {
  1646. //重新加载左边树
  1647. isShowLeft.value = false
  1648. setTimeout(() => {
  1649. isShowLeft.value = true
  1650. }, 500)
  1651. }
  1652. },
  1653. )
  1654. const pageSplitRef = ref(null)
  1655. watch(() => pageSplitRef.value?.leftPanelWidth, (newWidth) => {
  1656. leftWidth.value = newWidth
  1657. setUserConfig(newWidth)
  1658. })
  1659. //渲染完成
  1660. onMounted(() => {
  1661. console.log(projectInfo.value)
  1662. treeLoading.value = typeName === 'tree'
  1663. const treeWidth = useAppState.getTreeWidth
  1664. leftWidth.value = isNullES(treeWidth) || treeWidth <= 0 ? 440 : treeWidth
  1665. setContractType(contractInfo.value?.contractType)
  1666. getDictionaryApi()
  1667. getStandardTypeOptions()
  1668. getMajorDataTypeOptions()
  1669. nextTick(() => {
  1670. pageSplitRef.value?.setLeftWidth(leftWidth.value)
  1671. })
  1672. })
  1673. //身份按钮切换数据
  1674. const authBtnTabKey = ref('1')
  1675. //变量
  1676. const wbstree = ref(null)
  1677. const isShowLeft = ref(true)
  1678. const authBtnTabClick = (val) => {
  1679. setElTreeMenu(val['key'])
  1680. if (!primaryKeyId.value) {
  1681. window?.$message?.warning('请先在左侧项目树选择一个节点')
  1682. } else if (val['key'] !== authBtnTabKey.value) {
  1683. authBtnTabKey.value = val['key']
  1684. // //重新加载左边树
  1685. // isShowLeft.value = false
  1686. // setTimeout(() => {
  1687. // isShowLeft.value = true
  1688. // }, 500)
  1689. // getTableDataAll()
  1690. // handleClick()
  1691. //重新加载左边树
  1692. isLookHistory.value = false
  1693. isLookHide.value = true
  1694. isSearchTree.value = false
  1695. searchTreeVal.value = ''
  1696. isShowLeft.value = false
  1697. setTimeout(() => {
  1698. isShowLeft.value = true
  1699. }, 500)
  1700. getTableDataAll()
  1701. }
  1702. }
  1703. //contractType, 1施工,2监理
  1704. const setContractType = (contractType) => {
  1705. if (contractType <= 0) {
  1706. authBtnTabKey.value = '1'
  1707. classType.value = '1'
  1708. } else if (contractType === 3) {
  1709. authBtnTabKey.value = '1'
  1710. classType.value = '1'
  1711. } else {
  1712. authBtnTabKey.value = contractType + ''
  1713. classType.value = contractType + ''
  1714. }
  1715. setElTreeMenu(contractType)
  1716. }
  1717. const getTableDataAll = async (key) => {
  1718. await searchNodeAllTable()
  1719. await queryNodeStatus()
  1720. if (isTemplateType.value) {
  1721. await getFileName()
  1722. await getnodeBaseData()
  1723. }
  1724. //保存后自动展开到当前表单
  1725. if (!isNullES(key)) {
  1726. console.log(key)
  1727. await nextTick(() => {
  1728. ListItemRef.value?.setCollapseKey(key)
  1729. })
  1730. }
  1731. }
  1732. //结构类型tab数据和相关处理
  1733. const wbsTypeTabKey = ref(typeName)
  1734. const wbsTypeTab = ref([
  1735. { key: 'map', name: '导图结构填报' },
  1736. { key: 'tree', name: '树形结构填报' },
  1737. ])
  1738. const authBtnTabdata = ref([
  1739. { key: '1', name: '施工质检' },
  1740. { key: '2', name: '监理质检' },
  1741. ])
  1742. const wbsTypeTabChange = (item) => {
  1743. wbsTypeTabKey.value = item?.key
  1744. ListItemDatas.value = []
  1745. isDrawer.value = false
  1746. treeLoading.value = typeName === 'tree'
  1747. setStoreValue('classifyType', classType.value)
  1748. setStoreValue('tableOwner', authBtnTabKey.value)
  1749. //路由跳转
  1750. router.push({
  1751. path: useRoutes.path,
  1752. query: {
  1753. type: item?.key,
  1754. classifyType: classType.value,
  1755. tableOwner: authBtnTabKey.value,
  1756. },
  1757. })
  1758. getSearchTreeData()
  1759. }
  1760. //切换导图结构
  1761. const wbsMapTypeTab = () => {
  1762. wbsTypeTabChange({ key: 'map', name: '导图结构填报' })
  1763. }
  1764. //设置图纸数据
  1765. const setUploadDrawingsData = async (echoParams, link) => {
  1766. const info = nodeDataInfo.value
  1767. const { error, code, data } = await wbsApi.saveContractTreeDrawings(
  1768. {
  1769. fileUrl: link,
  1770. id: echoParams['drawingsId'],
  1771. primaryKeyId: echoParams['primaryKeyId'],
  1772. },
  1773. false,
  1774. )
  1775. //处理数据
  1776. if (!error && code === 200) {
  1777. if (info['primaryKeyId'] === echoParams['primaryKeyId']) {
  1778. nodeDataInfo.value['drawingsId'] = data
  1779. nodeDataInfo.value['fileUrl'] = link
  1780. window?.$message?.success('图纸上传成功')
  1781. } else {
  1782. window?.$message?.success(
  1783. '图纸上传成功,由于您切换了其他节点,需要手动刷新才能查看到图纸',
  1784. )
  1785. }
  1786. } else {
  1787. window?.$message?.error('图纸保存失败')
  1788. }
  1789. }
  1790. const NodeTreeAccordion = ref(true)
  1791. //设置树菜单数据
  1792. const ElTreeMenu = ref([])
  1793. const TreeMark = ref(false)
  1794. const setElTreeMenu = (contractType) => {
  1795. let newArr = []
  1796. if (contractType == 1 && contractInfo.value?.contractType !== 2) {
  1797. if (HcIsButton('wbs_tree_add')) {
  1798. newArr.push({ icon: 'add-circle', label: '新增节点', key: 'add' })
  1799. newArr.push({
  1800. icon: 'add-circle',
  1801. label: '自定义节点(水利工程)',
  1802. key: 'add1',
  1803. })
  1804. newArr.push({
  1805. icon: 'add-circle',
  1806. label: '自定义节点(数字化文件)',
  1807. key: 'add2',
  1808. })
  1809. }
  1810. if (HcIsButton('wbs_tree_edit')) {
  1811. newArr.push({ icon: 'draft', label: '编辑节点', key: 'edit' })
  1812. }
  1813. if (HcIsButton('wbs_tree_copy')) {
  1814. newArr.push({
  1815. icon: 'file-copy-2',
  1816. label: '复制节点',
  1817. key: 'copy',
  1818. })
  1819. }
  1820. if (HcIsButton('wbs_tree_mark')) {
  1821. newArr.push({ icon: 'star', label: '标记为首件', key: 'mark' })
  1822. TreeMark.value = true
  1823. }
  1824. if (HcIsButton('wbs_tree_upload')) {
  1825. newArr.push({
  1826. icon: 'file-upload',
  1827. label: '上传图纸',
  1828. key: 'upload',
  1829. })
  1830. }
  1831. if (HcIsButton('wbs_tree_sort')) {
  1832. newArr.push({ icon: 'sort-asc', label: '调整排序', key: 'sort' })
  1833. }
  1834. if (HcIsButton('wbs_tree_del')) {
  1835. newArr.push({ icon: 'delete-bin', label: '删除节点', key: 'del' })
  1836. }
  1837. if (HcIsButton('wbs_views_division_btn')) {
  1838. newArr.push({
  1839. icon: 'folder-shared',
  1840. label: '工程划分',
  1841. key: 'nodetree',
  1842. })
  1843. }
  1844. if (HcIsButton('wbs_tree_jump')) {
  1845. newArr.push({
  1846. icon: 'drag-move-2',
  1847. label: '跨节点移动',
  1848. key: 'jumpTree',
  1849. })
  1850. }
  1851. if (HcIsButton('data-fill-wbs-link')) {
  1852. newArr.push({
  1853. icon: 'links',
  1854. label: '关联构建编码',
  1855. key: 'wbsLink',
  1856. })
  1857. }
  1858. } else if (contractType == 2) {
  1859. newArr = []
  1860. if (HcIsButton('wbs_tree_copy')) {
  1861. newArr.push({
  1862. icon: 'file-copy-2',
  1863. label: '复制节点',
  1864. key: 'copy',
  1865. })
  1866. }
  1867. }
  1868. ElTreeMenu.value = newArr
  1869. }
  1870. //树相关变量
  1871. const primaryKeyId = ref('')
  1872. const nodeItemInfo = ref({})
  1873. const nodeDataInfo = ref({})
  1874. const searchTreeData = ref([])
  1875. //回车
  1876. const searchTreeKeyUp = (e) => {
  1877. if (e.key === 'Enter') {
  1878. searchTreeClick()
  1879. }
  1880. }
  1881. const treeLoading = ref(true)
  1882. const searchTreeClick = async () => {
  1883. if (searchTreeVal.value) {
  1884. searchTreeHeight.value
  1885. = document.getElementById('hc-tree-scrollbar').offsetHeight
  1886. isSearchTree.value = true
  1887. //treeLoading.value = true
  1888. if ( isLookHistory.value) {
  1889. getSearchTreeData('history')
  1890. } else if (folderId.value) {
  1891. getSearchTreeData('folder')
  1892. } else if (!isLookHide.value) {
  1893. getSearchTreeData('hide')
  1894. } else {
  1895. getSearchTreeData()
  1896. }
  1897. } else {
  1898. if (!isLookHide.value) {
  1899. console.log(77777)
  1900. getSearchTreeData('hide')
  1901. return
  1902. }
  1903. if (isLookHistory.value) {
  1904. console.log(77777)
  1905. getSearchTreeData('history')
  1906. return
  1907. }
  1908. isSearchTree.value = false
  1909. }
  1910. }
  1911. //懒加载的数据
  1912. const treeLoadNode = async ({ node, item, level }, resolve) => {
  1913. let contractIdRelation = '',
  1914. parentId = '',
  1915. primaryKeyId = ''
  1916. if (level !== 0) {
  1917. const nodeData = getObjValue(item)
  1918. contractIdRelation = nodeData?.contractIdRelation || ''
  1919. parentId = contractIdRelation ? nodeData?.primaryKeyId : nodeData?.id
  1920. primaryKeyId = nodeData?.id || ''
  1921. }
  1922. // 获取数据
  1923. let data = []
  1924. if (folderId.value) {
  1925. // 如果folderId.value存在,调用collectApi.getCollectTreeNode
  1926. let pKeyId = 0
  1927. if (level !== 0) {
  1928. const nodeData = getObjValue(item)
  1929. pKeyId = nodeData?.primaryKeyId || ''
  1930. }
  1931. const res = await collectApi.getCollectTreeNode({
  1932. pKeyId,
  1933. folderId: folderId.value,
  1934. contractId: contractId.value || '',
  1935. tableOwner: authBtnTabKey.value,
  1936. queryValue: searchTreeVal.value,
  1937. })
  1938. data = res.data || [] // 假设返回的数据结构中包含data字段
  1939. } else {
  1940. // 否则,继续使用原来的queryApi.queryWbsTreeData
  1941. const { data: resData } = await queryApi.queryWbsTreeData({
  1942. contractId: contractId.value || '',
  1943. contractIdRelation,
  1944. primaryKeyId,
  1945. parentId,
  1946. classifyType: classType.value,
  1947. tableOwner: authBtnTabKey.value,
  1948. dataTime: new Date(),
  1949. })
  1950. data = resData || []
  1951. }
  1952. treeLoading.value = false
  1953. resolve(getArrValue(data))
  1954. }
  1955. //树被点击
  1956. const wbsElTreeClick = ({ node, data, keys }) => {
  1957. nodeItemInfo.value = node
  1958. nodeDataInfo.value = data
  1959. primaryKeyId.value = data?.primaryKeyId || ''
  1960. const { notExsitChild } = data
  1961. const { hasChildren } = data
  1962. if (notExsitChild || !hasChildren) {
  1963. isCanadd.value = false
  1964. getTableDataAll()
  1965. } else {
  1966. isCanadd.value = true
  1967. ListItemDatas.value = []
  1968. NodeStatus.value = '1'
  1969. }
  1970. setStoreValue('wbsTreeExpandKeys', keys)
  1971. TreeAutoExpandKeys.value = keys || []
  1972. saveHistory(keys.join(','))
  1973. // getTableDataAll()
  1974. }
  1975. //树加载完成
  1976. const ElTreeNodeLoading = () => {
  1977. treeLoading.value = false
  1978. }
  1979. //保存用户填报历史
  1980. const saveHistory = async (endNode) => {
  1981. await wbsApi.saveUserHistory({
  1982. contractId: contractId.value,
  1983. projectId: projectId.value,
  1984. endNode,
  1985. })
  1986. }
  1987. //回到上次填报历史
  1988. const gobackHistory = async () => {
  1989. isSearchTree.value = false
  1990. const { error, code, data, msg } = await wbsApi.getUserHistory({
  1991. contractId: contractId.value,
  1992. projectId: projectId.value,
  1993. })
  1994. if (!error && code === 200) {
  1995. TreeAutoExpandKeys.value = data['endNode'].split(',') || []
  1996. //重新加载左边树
  1997. isShowLeft.value = false
  1998. setTimeout(() => {
  1999. isShowLeft.value = true
  2000. }, 500)
  2001. } else {
  2002. window.$message.warning(msg)
  2003. }
  2004. }
  2005. //树菜单被点击
  2006. const ElTreeMenuClick = async ({ key, node, data, keys }) => {
  2007. nodeItemInfo.value = node
  2008. nodeDataInfo.value = data
  2009. setStoreValue('wbsTreeExpandKeys', keys)
  2010. TreeAutoExpandKeys.value = keys || []
  2011. setTreeMenuDataClick({ key, node, data })
  2012. }
  2013. //导图结构数据
  2014. const NodeTreeRef = ref(null)
  2015. //鼠标左键单击事件
  2016. const NodeTreeClick = ({ keys }) => {
  2017. setStoreValue('wbsTreeExpandKeys', keys)
  2018. TreeAutoExpandKeys.value = keys || []
  2019. }
  2020. //双击事件
  2021. const isDrawer = ref(false)
  2022. const NodeTreeDblClick = ({ node, data }) => {
  2023. nodeItemInfo.value = node
  2024. nodeDataInfo.value = data
  2025. primaryKeyId.value = data?.primaryKeyId || ''
  2026. isDrawer.value = true
  2027. getTableDataAll()
  2028. }
  2029. const drawerClose = () => {
  2030. isDrawer.value = false
  2031. ListItemDatas.value = []
  2032. }
  2033. //导图树菜单被点击
  2034. const NodeTreeMenuClick = async ({ key, node, data }) => {
  2035. nodeItemInfo.value = node
  2036. nodeDataInfo.value = data
  2037. setTreeMenuDataClick({ key, node, data })
  2038. }
  2039. const orString = ref('')
  2040. //处理菜单被点击数据
  2041. const setTreeMenuDataClick = ({ key, node, data }) => {
  2042. const tabKey = wbsTypeTabKey.value
  2043. if (key === 'mark' || key === 'cancel_mark') {
  2044. firstItemBox()
  2045. } else if (key === 'edit') {
  2046. console.log(data, 'data')
  2047. let form = {}
  2048. if (tabKey === 'tree') {
  2049. const parent = deepClone(node?.parent?.data || {})
  2050. form = { ...deepClone(data), parent: parent }
  2051. } else if (tabKey === 'map') {
  2052. const parent = deepClone(node?.parentNodes?.data || {})
  2053. form = { ...deepClone(data), parent: parent }
  2054. }
  2055. formEditNodeModel.value = form
  2056. orString.value = formEditNodeModel.value?.className
  2057. changeStandType(formEditNodeModel.value?.className)
  2058. console.log(
  2059. formEditNodeModel.value?.className,
  2060. 'formEditNodeModel.value?.className',
  2061. )
  2062. editNodeModal.value = true
  2063. //处理路径
  2064. let pathArr = []
  2065. getPathName(node, pathArr)
  2066. form.position = pathArr.join('\\')
  2067. formEditNodeModel.value = form
  2068. } else if (key === 'copy') {
  2069. if (tabKey === 'tree') {
  2070. const parent = deepClone(node?.parent?.data || {})
  2071. formCopyNodeModel.value = { ...deepClone(data), parent: parent }
  2072. } else if (tabKey === 'map') {
  2073. const parent = deepClone(node?.parentNodes?.data || {})
  2074. formCopyNodeModel.value = { ...deepClone(data), parent: parent }
  2075. }
  2076. classifyType.value = authBtnTabKey.value
  2077. copyNodeTabKey.value = '1'
  2078. copyNodeTable.value = []
  2079. copyNodeLoading.value = false
  2080. copyNodeModal.value = true
  2081. console.log(classType.value, 'classType.value')
  2082. classifyList.value = []
  2083. } else if (key === 'add') {
  2084. isCustom.value = data?.isCustom
  2085. addTreeNodeId.value = data?.primaryKeyId
  2086. addTreeNodeOldId.value = data?.oldId
  2087. addNodeLoading.value = false
  2088. if (data?.isClassifition === 1) {
  2089. window.$message.warning('该节点下不能创建子节点')
  2090. addNodeModal.value = false
  2091. return
  2092. }
  2093. {
  2094. addNodeModal.value = true
  2095. }
  2096. } else if (key === 'add1') {
  2097. addTreeNodeId.value = data?.primaryKeyId
  2098. addTreeNodeOldId.value = data?.oldId
  2099. addNodeLoading.value = false
  2100. formWaterNodeModel.value = {
  2101. nodeName: '',
  2102. nodeType: null,
  2103. }
  2104. if (data?.isClassifition === 1) {
  2105. window.$message.warning('该节点下不能创建子节点')
  2106. addNodeModalCus.value = false
  2107. return
  2108. }
  2109. {
  2110. addNodeModalCus.value = true
  2111. }
  2112. } else if (key === 'add2') {
  2113. addTreeNodeId.value = data?.primaryKeyId
  2114. addTreeNodeOldId.value = data?.oldId
  2115. addNodeLoading.value = false
  2116. formDataNodeModel.value = {
  2117. nodeName: '',
  2118. nodeType: null,
  2119. isClassifition: 0,
  2120. className: '',
  2121. unitName: '',
  2122. unitNum: 1,
  2123. excellentNum: 1,
  2124. digitizeTime: '',
  2125. }
  2126. if (data?.isClassifition === 1) {
  2127. window.$message.warning('该节点下不能创建子节点')
  2128. addNodeModalData.value = false
  2129. return
  2130. } else {
  2131. addNodeModalData.value = true
  2132. }
  2133. } else if (key === 'upload') {
  2134. const info = nodeDataInfo.value
  2135. HcUploadFileApi({
  2136. url: '/api/blade-resource/oss/endpoint/put-file',
  2137. accept: '.png,.jpg,jpeg',
  2138. accept_tip: '图片(png、jpg、jpeg)',
  2139. size: 80,
  2140. multiple: false,
  2141. echoParams: {
  2142. drawingsId: info['drawingsId'],
  2143. primaryKeyId: info['primaryKeyId'],
  2144. },
  2145. success: ({ echoParams }, { data }) => {
  2146. setUploadDrawingsData(echoParams.sourceKey, data?.link)
  2147. },
  2148. error: () => {
  2149. window.$message.error('上传失败')
  2150. },
  2151. })
  2152. } else if (key === 'del') {
  2153. console.log(data, 'data')
  2154. if (
  2155. data['colorStatus'] === 1
  2156. || data['colorStatus'] === 2
  2157. || data['colorStatus'] === null
  2158. || data['colorStatus'] === -1
  2159. ) {
  2160. delModalClick()
  2161. } else {
  2162. window?.$message?.warning('该节点已存在上报数据,不允许删除')
  2163. }
  2164. } else if (key === 'sort') {
  2165. let nodes = [],
  2166. childNodes = []
  2167. if (tabKey === 'tree') {
  2168. childNodes
  2169. = node?.parent?.childNodes || node?.parent?.children || []
  2170. } else if (tabKey === 'map') {
  2171. childNodes = node?.parentNodes?.childrenNodes || []
  2172. }
  2173. for (let i = 0; i < childNodes.length; i++) {
  2174. const res = childNodes[i]?.data
  2175. nodes.push({
  2176. id: res?.primaryKeyId,
  2177. title: res?.title,
  2178. })
  2179. }
  2180. sortNodeData.value = nodes
  2181. sortNodeModal.value = true
  2182. } else if (key === 'nodetree') {
  2183. divisionClick()
  2184. } else if (key === 'jumpTree') {
  2185. console.log('跨节点移动')
  2186. primaryKeyId.value = data.primaryKeyId
  2187. showMoveClick(node, data)
  2188. } else if (key === 'wbsLink') {
  2189. console.log('wbsLink')
  2190. wbsLinkModal.value = true
  2191. }
  2192. }
  2193. //获取节点的路径名字
  2194. const getPathName = (node, pathArr) => {
  2195. if (node.parent?.parent) {
  2196. pathArr.unshift(node.data?.title.replace(/(^\s*)|(\s*$)/g, '')) //去掉头尾空格
  2197. getPathName(node.parent, pathArr)
  2198. } else {
  2199. //根节点结束
  2200. pathArr.unshift(node.data?.title.replace(/(^\s*)|(\s*$)/g, '')) //去掉头尾空格
  2201. return pathArr
  2202. }
  2203. }
  2204. //确认标记为首件
  2205. const firstItemBox = () => {
  2206. const info = nodeDataInfo.value
  2207. window?.$messageBox?.alert(
  2208. `<div class="text-base font-bold">
  2209. <span>请确认将</span>
  2210. <span class="text-main">【${info['title']}】</span>
  2211. <span>${info['isFirst'] ? '取消' : ''}标记为首件</span>
  2212. </div>`,
  2213. '标记首件制',
  2214. {
  2215. showCancelButton: true,
  2216. dangerouslyUseHTMLString: true,
  2217. callback: (action) => {
  2218. if (action === 'confirm') {
  2219. firstItemHttp(info)
  2220. }
  2221. },
  2222. },
  2223. )
  2224. }
  2225. //首件请求
  2226. const firstItemHttp = async (info) => {
  2227. const { error, code, msg } = await wbsApi.wbsTreeFirstSave({
  2228. primaryKeyId: info['primaryKeyId'],
  2229. saveOrDeleted: info['isFirst'] ? 1 : 0,
  2230. })
  2231. //处理数据
  2232. if (!error && code === 200) {
  2233. window?.$message?.success('操作成功')
  2234. // window?.location?.reload() //刷新页面
  2235. if (folderId.value) {
  2236. isShowLeft.value = false
  2237. setTimeout(() => {
  2238. isShowLeft.value = true
  2239. selCollectMneu()
  2240. }, 500)
  2241. getTableDataAll()
  2242. } else {
  2243. window?.location?.reload() //刷新页面
  2244. }
  2245. }
  2246. }
  2247. //编辑节点
  2248. const editNodeModal = ref(false)
  2249. //获取节点类型
  2250. const nodeTypeData = ref([])
  2251. const getDictionaryApi = async () => {
  2252. const { data } = await getDictionary({
  2253. code: 'wbs_node_type',
  2254. })
  2255. //处理数据
  2256. let newArr = []
  2257. const newData = getArrValue(data)
  2258. for (let i = 0; i < newData.length; i++) {
  2259. newArr.push({
  2260. label: newData[i]['dictValue'],
  2261. value: Number(newData[i]['dictKey']),
  2262. })
  2263. }
  2264. nodeTypeData.value = newArr
  2265. }
  2266. const formEditNodeRef = ref(null)
  2267. const formEditNodeModel = ref({
  2268. title: '',
  2269. parent: {
  2270. title: '',
  2271. },
  2272. nodeType: null,
  2273. partitionCode: '',
  2274. position: '',
  2275. notExsitChild: '',
  2276. })
  2277. const formEditNodeRules = {
  2278. title: {
  2279. required: true,
  2280. trigger: 'blur',
  2281. message: '请输入节点名称',
  2282. },
  2283. }
  2284. const editNodeLoading = ref(false)
  2285. //保存编辑节点数据
  2286. const editNodeClick = async () => {
  2287. const validate = await formValidate(formEditNodeRef.value)
  2288. if (validate) {
  2289. //发起请求
  2290. editNodeLoading.value = true
  2291. const {
  2292. primaryKeyId,
  2293. title,
  2294. partitionCode,
  2295. className,
  2296. unitName,
  2297. excellentNum,
  2298. unitNum,
  2299. digitizeTime,
  2300. majorDataType,
  2301. nodeType,
  2302. privateTemplate,
  2303. } = formEditNodeModel.value
  2304. const { error, code, msg } = await wbsApi.wbsTreeUpdateNode({
  2305. nodeName: title || '',
  2306. pKeyId: primaryKeyId || '',
  2307. partitionCode: partitionCode || '',
  2308. className,
  2309. unitName,
  2310. unitNum,
  2311. excellentNum,
  2312. digitizeTime,
  2313. majorDataType,
  2314. nodeType,
  2315. privateTemplate,
  2316. })
  2317. //处理数据
  2318. editNodeLoading.value = false
  2319. if (!error && code === 200) {
  2320. window?.$message?.success('修改成功')
  2321. nodeDataInfo.value['title'] = title || ''
  2322. nodeDataInfo.value['partitionCode'] = partitionCode || ''
  2323. editNodeModal.value = false
  2324. // window?.location?.reload() //刷新页面
  2325. if (folderId.value) {
  2326. isShowLeft.value = false
  2327. setTimeout(() => {
  2328. isShowLeft.value = true
  2329. selCollectMneu()
  2330. }, 500)
  2331. getTableDataAll()
  2332. } else {
  2333. window?.location?.reload() //刷新页面
  2334. }
  2335. }
  2336. }
  2337. }
  2338. //复制节点
  2339. const copyNodeModal = ref(false)
  2340. //复制节点类型tab数据和相关处理
  2341. const copyNodeTabKey = ref('')
  2342. const copyNodeTab = ref([
  2343. { key: '1', name: '单份复制' },
  2344. { key: '2', name: '多份复制' },
  2345. //{key: '3', name: '复制数据'}
  2346. ])
  2347. const copyNodeTabChange = (key) => {
  2348. if (key !== copyNodeTabKey.value) {
  2349. copyNodeTabKey.value = key
  2350. copyNodeTable.value = []
  2351. copyNodeLoading.value = false
  2352. }
  2353. }
  2354. //复制节点变量
  2355. const copyNodeLoading = ref(false)
  2356. const formCopyNodeModel = ref({})
  2357. const classifyList = ref([])
  2358. const copyNodeTable = ref([])
  2359. const isCopyData = ref(0)
  2360. //复制树被点击
  2361. const copyNodeElTreeClick = ({ data, node }) => {
  2362. const TabKey = copyNodeTabKey.value
  2363. const { title, type, partitionCode } = formCopyNodeModel.value
  2364. console.log(formCopyNodeModel.value, 'formCopyNodeModel.value')
  2365. console.log(data, '点击data')
  2366. if (TabKey === '2') {
  2367. // setCopyNodeTable(data, title, partitionCode)
  2368. //1 单位工程,2 分部工程,3 子分部工程,4 分项工程, 5 子分项工程,6 工序
  2369. // //不能复制到本身节点下
  2370. // //只能往上一级点击,不能跨层级点击
  2371. // //已上报的工序节点不能点击选择
  2372. // //如果选择的是父级节点,那不能复制到子级节点
  2373. const { hasChildren } = data
  2374. if (hasChildren === 0) {
  2375. if (
  2376. data['colorStatus'] === 2
  2377. || data['colorStatus'] == 1
  2378. || data['colorStatus'] === null
  2379. || data['colorStatus'] === -1
  2380. ) {
  2381. //已上报的工序不能点击
  2382. if (data['id'] !== formCopyNodeModel.value.id) {
  2383. //不能复制到本身节点下
  2384. //只能往上一级点击,不能跨层级点击
  2385. //如果选择的是父级节点,那不能复制到子级节点
  2386. if (
  2387. type === 6
  2388. && (data['type'] === 4
  2389. || data['type'] === 5
  2390. || data['type'] == 6)
  2391. ) {
  2392. setCopyNodeTable(data, title)
  2393. }
  2394. if (type === 5 && data['type'] === 4) {
  2395. setCopyNodeTable(data, title, partitionCode)
  2396. }
  2397. if (
  2398. type === 4
  2399. && (data['type'] === 2 || data['type'] === 3)
  2400. ) {
  2401. setCopyNodeTable(data, title, partitionCode)
  2402. }
  2403. if (type === 3 && data['type'] === 2) {
  2404. setCopyNodeTable(data, title, partitionCode)
  2405. }
  2406. if (type === 2 && data['type'] === 1) {
  2407. setCopyNodeTable(data, title, partitionCode)
  2408. }
  2409. if (type === 1 && data['type'] === 1) {
  2410. setCopyNodeTable(data, title, partitionCode)
  2411. }
  2412. }
  2413. } else {
  2414. window?.$message?.warning('该节点已存在上报数据,不允许复制')
  2415. }
  2416. } else {
  2417. if (data['id'] !== formCopyNodeModel.value.id) {
  2418. //不能复制到本身节点下
  2419. //只能往上一级点击,不能跨层级点击
  2420. //如果选择的是父级节点,那不能复制到子级节点
  2421. if (
  2422. type === 6
  2423. && (data['type'] === 4
  2424. || data['type'] === 5
  2425. || data['type'] == 6)
  2426. ) {
  2427. setCopyNodeTable(data, title)
  2428. }
  2429. if (type === 5 && data['type'] === 4) {
  2430. setCopyNodeTable(data, title, partitionCode)
  2431. }
  2432. if (type === 4 && (data['type'] === 2 || data['type'] === 3)) {
  2433. setCopyNodeTable(data, title, partitionCode)
  2434. }
  2435. if (type === 3 && data['type'] === 2) {
  2436. setCopyNodeTable(data, title, partitionCode)
  2437. }
  2438. if (type === 2 && data['type'] === 1) {
  2439. setCopyNodeTable(data, title, partitionCode)
  2440. }
  2441. if (type === 1 && data['type'] === 1) {
  2442. setCopyNodeTable(data, title, partitionCode)
  2443. }
  2444. }
  2445. }
  2446. } else if (TabKey === '3') {
  2447. console.log(1111111)
  2448. setCopyNodeTable(data, data?.title)
  2449. }
  2450. }
  2451. const setCopyNodeTable = (data, title) => {
  2452. copyNodeTable.value.push({
  2453. title: data?.title || '',
  2454. nodeName: title || '',
  2455. primaryKeyId: data?.primaryKeyId || '',
  2456. parentId: data?.parentId || '',
  2457. id: data?.id || '',
  2458. })
  2459. }
  2460. //节点表单
  2461. const formCopyNodeModelRef = ref(null)
  2462. const formCopyNodeModelRules = {
  2463. title: {
  2464. required: true,
  2465. trigger: 'blur',
  2466. message: '请输入节点名称',
  2467. },
  2468. }
  2469. //表格节点表单
  2470. const copyNodeTableRef = ref(null)
  2471. const copyNodeTableRules = {
  2472. nodeName: {
  2473. required: true,
  2474. trigger: 'blur',
  2475. message: '请输入节点名称',
  2476. },
  2477. }
  2478. //删除选中的节点
  2479. const copyNodeTableDel = (index) => {
  2480. copyNodeTable.value.splice(index, 1)
  2481. }
  2482. const classifyType = ref(authBtnTabKey.value)
  2483. //复制节点
  2484. const copyNodeClick = async () => {
  2485. const type = copyNodeTabKey.value
  2486. const form = formCopyNodeModel.value
  2487. const table = copyNodeTable.value
  2488. let classify = ''
  2489. let arr = []
  2490. if (classifyList.value.length > 0) {
  2491. classifyList.value.forEach((item) => {
  2492. if (item === '施工') {
  2493. arr.push(1)
  2494. } else if (item === '监理') {
  2495. arr.push(2)
  2496. }
  2497. })
  2498. classify = arr.join(',')
  2499. }
  2500. //isSameNode 是否同节点 1=同节点,0=跨节点
  2501. if (table.length > 0) {
  2502. table.forEach((ele) => {
  2503. if (
  2504. ele.parentId === formCopyNodeModel.value.parentId
  2505. || ele.id === formCopyNodeModel.value.parentId
  2506. ) {
  2507. ele.isSameNode = 1
  2508. } else {
  2509. ele.isSameNode = 0
  2510. }
  2511. })
  2512. }
  2513. if (isCopyData.value === 1) {
  2514. if (classify) {
  2515. //效验数据
  2516. if (type === '1') {
  2517. const validate = await formValidate(formCopyNodeModelRef.value)
  2518. if (validate)
  2519. await copyContractTreeNode(type, form, [], classify)
  2520. } else if (type === '2') {
  2521. if (table.length > 0) {
  2522. const validate = await formValidate(copyNodeTableRef.value)
  2523. if (validate)
  2524. await copyContractTreeNode(type, form, table, classify)
  2525. } else {
  2526. window?.$message?.warning('请先在左侧选择要复制到的节点')
  2527. }
  2528. }
  2529. } else {
  2530. window?.$message?.warning('请选择所属方')
  2531. }
  2532. } else {
  2533. if (type === '1') {
  2534. const validate = await formValidate(formCopyNodeModelRef.value)
  2535. if (validate) await copyContractTreeNode(type, form, [], classify)
  2536. } else if (type === '2') {
  2537. if (table.length > 0) {
  2538. const validate = await formValidate(copyNodeTableRef.value)
  2539. if (validate)
  2540. await copyContractTreeNode(type, form, table, classify)
  2541. } else {
  2542. window?.$message?.warning('请先在左侧选择要复制到的节点')
  2543. }
  2544. }
  2545. }
  2546. }
  2547. //单个复制、多份复制请求
  2548. const copyContractTreeNode = async (type, form, table, classify) => {
  2549. copyNodeLoading.value = true
  2550. if (type === '1') {
  2551. const { error, code, msg } = await wbsApi.copyContractTreeNode({
  2552. copyType: type,
  2553. needCopyNodeName: form?.title || '',
  2554. partitionCode: form?.partitionCode || '',
  2555. needCopyPrimaryKeyId: form?.primaryKeyId || '',
  2556. parentPrimaryKeyId: form?.parent?.primaryKeyId || '',
  2557. copyBatchToPaths: table,
  2558. classifyType: classify,
  2559. isCopyData: isCopyData.value,
  2560. })
  2561. //判断状态
  2562. copyNodeLoading.value = false
  2563. if (!error && code === 200) {
  2564. window?.$message?.success('复制成功')
  2565. copyNodeModal.value = false
  2566. window?.location?.reload() //刷新页面
  2567. }
  2568. } else {
  2569. const { error, code, msg } = await wbsApi.copyContractTreeNode({
  2570. copyType: type,
  2571. needCopyNodeName: form?.title || '',
  2572. needCopyPrimaryKeyId: form?.primaryKeyId || '',
  2573. parentPrimaryKeyId: form?.parent?.primaryKeyId || '',
  2574. copyBatchToPaths: table,
  2575. classifyType: classify,
  2576. isCopyData: isCopyData.value,
  2577. })
  2578. //判断状态
  2579. copyNodeLoading.value = false
  2580. if (!error && code === 200) {
  2581. window?.$message?.success('复制成功')
  2582. copyNodeModal.value = false
  2583. window?.location?.reload() //刷新页面
  2584. }
  2585. }
  2586. }
  2587. //新增节点
  2588. const addNodeModal = ref(false)
  2589. const addTreeNodeId = ref('')
  2590. const addTreeNodeOldId = ref('')
  2591. //const addTreeNodeType = ref('1')
  2592. const addTreeNodeType = ref('1')
  2593. const isCustom = ref(null)
  2594. //新增自定义节点
  2595. const addNodeModalCus = ref(false)
  2596. const addNodeLoadingCus = ref(false)
  2597. //水利工程
  2598. const formWaterNodeRef = ref(null)
  2599. const formWaterNodeModel = ref({
  2600. nodeName: '',
  2601. nodeType: null,
  2602. })
  2603. const formWaterNodeRules = {
  2604. nodeName: {
  2605. required: true,
  2606. trigger: 'blur',
  2607. message: '请输入节点名称',
  2608. },
  2609. nodeType: {
  2610. required: true,
  2611. trigger: 'blur',
  2612. message: '请选择节点类型',
  2613. },
  2614. }
  2615. //新增自定义节点-数字化文件
  2616. const addNodeModalData = ref(false)
  2617. const addNodeLoadingData = ref(false)
  2618. const formDataNodeRef = ref(null)
  2619. const formDataNodeModel = ref({
  2620. nodeName: '',
  2621. nodeType: null,
  2622. isClassifition: 0,
  2623. className: '',
  2624. unitName: '',
  2625. unitNum: 1,
  2626. excellentNum: 1,
  2627. majorDataType: '',
  2628. digitizeTime: '',
  2629. })
  2630. const majorDataTypeOptions = ref([])
  2631. const getMajorDataTypeOptions = async () => {
  2632. majorDataTypeOptions.value = await getDictionaryData('major_data_type', false)
  2633. }
  2634. const standardTypeOptions = ref([])
  2635. const getStandardTypeOptions = async () => {
  2636. const { data } = await getDictionary({
  2637. code: 'classification',
  2638. })
  2639. standardTypeOptions.value = await getDictionaryData(
  2640. 'classification',
  2641. false,
  2642. )
  2643. standardTypeOptions.value.forEach((element) => {
  2644. // element.parentId=
  2645. data.forEach((ele) => {
  2646. if (ele.dictKey == element.value) {
  2647. element.id = ele.id
  2648. }
  2649. })
  2650. })
  2651. // 定义要过滤的 dictKey 值
  2652. const targetKeys = [1, 2, 3, 4, 5]
  2653. // 过滤数组
  2654. standardTypeOptions.value = standardTypeOptions.value.filter((item) =>
  2655. targetKeys.includes(item.value),
  2656. )
  2657. }
  2658. const unitNameOptions = ref([])
  2659. const changeStandType = async (val) => {
  2660. if (val !== orString.value) {
  2661. formEditNodeModel.value.unitName = ''
  2662. }
  2663. formDataNodeModel.value.unitName = ''
  2664. let parentId = ''
  2665. standardTypeOptions.value.forEach((item) => {
  2666. if (item.value == val) {
  2667. parentId = item.id
  2668. }
  2669. })
  2670. const { data } = await getChildList({ current: 1, size: 10000, parentId })
  2671. unitNameOptions.value = data
  2672. unitNameOptions.value = unitNameOptions.value.filter(
  2673. (item) => item.dictKey != -1,
  2674. )
  2675. unitNameOptions.value.forEach((ele) => {
  2676. ele.dictKey = Number(ele.dictKey)
  2677. })
  2678. }
  2679. const formDataNodeRules = {
  2680. nodeName: {
  2681. required: true,
  2682. trigger: 'blur',
  2683. message: '请输入节点名称',
  2684. },
  2685. nodeType: {
  2686. required: true,
  2687. trigger: 'blur',
  2688. message: '请选择节点类型',
  2689. },
  2690. isClassifition: {
  2691. required: true,
  2692. trigger: 'blur',
  2693. message: '请选择是否含单元评定',
  2694. },
  2695. className: {
  2696. required: true,
  2697. trigger: 'blur',
  2698. message: '请选择标准分类',
  2699. },
  2700. unitName: {
  2701. required: true,
  2702. trigger: 'blur',
  2703. message: '请选择单位名称',
  2704. },
  2705. excellentNum: {
  2706. required: true,
  2707. trigger: 'blur',
  2708. message: '请输入优良个数',
  2709. },
  2710. unitNum: {
  2711. required: true,
  2712. trigger: 'blur',
  2713. message: '请输入单元个数',
  2714. },
  2715. digitizeTime: {
  2716. required: true,
  2717. trigger: 'blur',
  2718. message: '请选择时间',
  2719. },
  2720. majorDataType:{
  2721. required: true,
  2722. trigger: 'blur',
  2723. message: '请选择内业资料类型',
  2724. },
  2725. }
  2726. const addNodeClickData = async () => {
  2727. const validate = await formValidate(formDataNodeRef.value)
  2728. if (!validate) return
  2729. //发起请求
  2730. addNodeClickData.value = true
  2731. const { error, code, msg } = await wbsApi.saveCustomAddContractNode({
  2732. nodeName: formDataNodeModel.value.nodeName,
  2733. nodeType: formDataNodeModel.value?.nodeType || '',
  2734. partitionCode: nodeDataInfo.value?.partitionCode || '',
  2735. primaryKeyId: nodeDataInfo.value?.primaryKeyId || '',
  2736. nodeClass: 2, //数字化文件
  2737. isClassifition: formDataNodeModel.value?.isClassifition || 0,
  2738. className: formDataNodeModel.value?.className || '',
  2739. unitName: Number(formDataNodeModel.value?.unitName) || '',
  2740. excellentNum: formDataNodeModel.value?.excellentNum || 0,
  2741. digitizeTime: formDataNodeModel.value?.digitizeTime || '',
  2742. unitNum: formDataNodeModel.value?.unitNum || 0,
  2743. majorDataType: formDataNodeModel.value?.majorDataType || '',
  2744. templateType:useAppState.contractInfo?.templateType,
  2745. })
  2746. //判断状态
  2747. addNodeClickData.value = false
  2748. if (!error && code === 200) {
  2749. window?.$message?.success('新增成功')
  2750. addNodeModalData.value = false
  2751. window?.location?.reload() //刷新页面
  2752. }
  2753. }
  2754. //选中的节点
  2755. const allSelectedList = ref([])
  2756. const halfSelectedList = ref([])
  2757. const addTreeNodeCheckChange = (nodes) => {
  2758. let NodesArr = [],
  2759. halfArr = []
  2760. //全选数据
  2761. const keys = nodes.checkedNodes || []
  2762. for (let i = 0; i < keys.length; i++) {
  2763. NodesArr.push({
  2764. nodeName: keys[i].nodeName,
  2765. primaryKeyId: keys[i].pKeyId,
  2766. isPeer: keys[i].isPeer || 2,
  2767. })
  2768. }
  2769. allSelectedList.value = NodesArr
  2770. //半选数据
  2771. const halfNodes = nodes.halfCheckedNodes || []
  2772. for (let i = 0; i < halfNodes.length; i++) {
  2773. halfArr.push({
  2774. nodeName: halfNodes[i].nodeName,
  2775. primaryKeyId: halfNodes[i].pKeyId,
  2776. isPeer: halfNodes[i].isPeer || 2,
  2777. })
  2778. }
  2779. halfSelectedList.value = halfArr
  2780. }
  2781. //新增节点
  2782. const addNodeLoading = ref(false)
  2783. const addNodeClick = async () => {
  2784. const keys = allSelectedList.value || []
  2785. if (keys.length <= 0) {
  2786. window?.$message?.warning('请先选择节点')
  2787. } else {
  2788. //发起请求
  2789. addNodeLoading.value = true
  2790. const primaryKeyId = nodeDataInfo.value?.primaryKeyId || ''
  2791. const { error, code } = await wbsApi.saveContractTreeNode({
  2792. projectId: projectId.value,
  2793. contractId: contractId.value,
  2794. saveType: addTreeNodeType.value,
  2795. allSelectedList: allSelectedList.value,
  2796. halfSelectedList: halfSelectedList.value,
  2797. currentNodePrimaryKeyId: primaryKeyId,
  2798. templateType:useAppState.contractInfo?.templateType,
  2799. })
  2800. //判断状态
  2801. addNodeLoading.value = false
  2802. if (!error && code === 200) {
  2803. window?.$message?.success('新增成功')
  2804. addNodeModal.value = false
  2805. window?.location?.reload() //刷新页面
  2806. }
  2807. }
  2808. }
  2809. const addNodeClickCur = async () => {
  2810. const validate = await formValidate(formWaterNodeRef.value)
  2811. if (!validate) return
  2812. //发起请求
  2813. addNodeLoadingCus.value = true
  2814. const { error, code, msg } = await wbsApi.saveCustomAddContractNode({
  2815. nodeName: formWaterNodeModel.value.nodeName,
  2816. nodeType: formWaterNodeModel.value?.nodeType || '',
  2817. newPartitionCode:formWaterNodeModel.value?.number || '',
  2818. partitionCode: nodeDataInfo.value?.partitionCode || '',
  2819. primaryKeyId: nodeDataInfo.value?.primaryKeyId || '',
  2820. nodeClass: 1, //1水利化工程,2数字化文件
  2821. templateType:useAppState.contractInfo?.templateType,
  2822. })
  2823. //判断状态
  2824. addNodeLoadingCus.value = false
  2825. if (!error && code === 200) {
  2826. window?.$message?.success('新增成功')
  2827. addNodeModalCus.value = false
  2828. window?.location?.reload() //刷新页面
  2829. } else {
  2830. window?.$message?.error(msg || '操作失败')
  2831. }
  2832. }
  2833. //删除节点
  2834. const delModalClick = async () => {
  2835. const { code, msg } = await wbsApi.removeContractTreeNodeJudge({
  2836. ids: nodeDataInfo.value?.primaryKeyId || '',
  2837. })
  2838. if (code === 200) {
  2839. HcDelMsg(async (resolve) => {
  2840. await removeContractTreeNode()
  2841. resolve() //关闭弹窗的回调
  2842. })
  2843. } else {
  2844. NewDelMsg({ text: msg }, async (resolve) => {
  2845. await removeContractTreeNode()
  2846. resolve() //关闭弹窗的回调
  2847. })
  2848. }
  2849. }
  2850. const removeContractTreeNode = async () => {
  2851. const loadingInstance = window.$loading.service({
  2852. fullscreen: true,
  2853. text: '删除节点中,请耐心等待...',
  2854. background: 'rgba(0, 0, 0, 0.7)',
  2855. })
  2856. const { error, code, msg } = await wbsApi.removeContractTreeNode({
  2857. ids: nodeDataInfo.value?.primaryKeyId || '',
  2858. })
  2859. //处理结果
  2860. loadingInstance.close()
  2861. if (!error && code === 200) {
  2862. window?.$message?.success('删除成功')
  2863. // window?.location?.reload() //刷新页面
  2864. if (folderId.value) {
  2865. isShowLeft.value = false
  2866. setTimeout(() => {
  2867. isShowLeft.value = true
  2868. selCollectMneu()
  2869. }, 500)
  2870. getTableDataAll()
  2871. } else {
  2872. window?.location?.reload() //刷新页面
  2873. }
  2874. } else {
  2875. window.$message.error(msg)
  2876. }
  2877. }
  2878. //调整排序
  2879. const sortNodeModal = ref(false)
  2880. const sortNodeLoading = ref(false)
  2881. const sortNodeData = ref([])
  2882. const sortNodeDrag = ref(false)
  2883. //向下
  2884. const downSortClick = (index) => {
  2885. const indexs = index + 1
  2886. const data = sortNodeData.value || []
  2887. if (indexs !== data.length) {
  2888. const tmp = data.splice(indexs, 1)
  2889. sortNodeData.value.splice(index, 0, tmp[0])
  2890. } else {
  2891. window?.$message?.warning('已经处于置底,无法下移')
  2892. }
  2893. }
  2894. //向上
  2895. const upSortClick = (index) => {
  2896. const data = sortNodeData.value || []
  2897. if (index !== 0) {
  2898. const tmp = data.splice(index - 1, 1)
  2899. sortNodeData.value.splice(index, 0, tmp[0])
  2900. } else {
  2901. window?.$message?.warning('已经处于置顶,无法上移')
  2902. }
  2903. }
  2904. //确认排序
  2905. const sortNodeClick = async () => {
  2906. const sortList = []
  2907. const nodes = sortNodeData.value || []
  2908. nodes.forEach((item) => {
  2909. sortList.push(item?.id)
  2910. })
  2911. //发起请求
  2912. sortNodeLoading.value = true
  2913. const { error, code, msg } = await wbsApi.diySortTreeNode({ sortList })
  2914. sortNodeLoading.value = false
  2915. //判断状态
  2916. if (!error && code === 200) {
  2917. window?.$message?.success('保存成功')
  2918. sortNodeModal.value = false
  2919. window?.location?.reload() //刷新页面
  2920. } else {
  2921. window.$message.error(msg)
  2922. }
  2923. }
  2924. //查看图纸
  2925. const drawList = ref('')
  2926. const drawingsShow = ref(false)
  2927. const viewsDrawings = () => {
  2928. const { primaryKeyId, drawingsId } = nodeDataInfo.value
  2929. if (!primaryKeyId) {
  2930. window?.$message?.warning('请先选择树节点')
  2931. } else if (drawingsId === -1 || drawingsId === null) {
  2932. window?.$message?.warning('该节点暂未上传图纸')
  2933. } else {
  2934. drawingsShow.value = true
  2935. getDrawList(drawingsId)
  2936. }
  2937. }
  2938. const drawingsClose = (res) => {
  2939. drawingsShow.value = res
  2940. }
  2941. const getDrawList = async (primaryKeyId) => {
  2942. const { error, code, data } = await wbsApi.getTreeDrawings({
  2943. primaryKeyId,
  2944. })
  2945. //判断状态
  2946. if (!error && code === 200) {
  2947. drawList.value = data
  2948. } else {
  2949. drawList.value = data
  2950. }
  2951. }
  2952. //设置滚动条位置
  2953. const ListItemScrollRef = ref(null)
  2954. const ListItemOffsetTop = (offsetTop) => {
  2955. if (offsetTop > 0) {
  2956. setTimeout(() => {
  2957. ListItemScrollRef.value?.setScrollTop(offsetTop)
  2958. }, 350)
  2959. } else {
  2960. ListItemScrollRef.value?.setScrollTop(offsetTop)
  2961. }
  2962. }
  2963. //获取数据列表
  2964. const ListItemDatas = ref([])
  2965. const ListItemLoading = ref(false)
  2966. const searchNodeAllTable = async () => {
  2967. ListItemLoading.value = true
  2968. ListItemDatas.value = []
  2969. const info = nodeDataInfo.value
  2970. const { data } = await wbsApi.searchNodeAllTable({
  2971. projectId: projectId.value,
  2972. contractId: contractId.value,
  2973. primaryKeyId: info['primaryKeyId'],
  2974. type: authBtnTabKey.value,
  2975. })
  2976. ListItemDatas.value = getArrValue(data)
  2977. ListItemLoading.value = false
  2978. }
  2979. //获取文件题名
  2980. const getFileName = async () => {
  2981. if (!nodeDataInfo.value?.primaryKeyId) {
  2982. titleInput.value = ''
  2983. return
  2984. }
  2985. const info = nodeDataInfo.value
  2986. const { error, code, data } = await wbsApi.getDICengNodeName({
  2987. pKeyId: info['primaryKeyId'],
  2988. classify: authBtnTabKey.value,
  2989. contractId: contractId.value,
  2990. })
  2991. //判断状态
  2992. if (!error && code === 200) {
  2993. titleInput.value = data
  2994. } else {
  2995. titleInput.value = data
  2996. }
  2997. }
  2998. const newlistdata = ref([])
  2999. const searchNodeAllTable1 = async () => {
  3000. console.log('重新获取表单列表')
  3001. const info = nodeDataInfo.value
  3002. const { data } = await wbsApi.searchNodeAllTable({
  3003. projectId: projectId.value,
  3004. contractId: contractId.value,
  3005. primaryKeyId: info['primaryKeyId'],
  3006. type: authBtnTabKey.value,
  3007. })
  3008. newlistdata.value = getArrValue(data)
  3009. }
  3010. //查询状态
  3011. const NodeStatus = ref('1')
  3012. const queryNodeStatus = async () => {
  3013. const info = nodeDataInfo.value
  3014. if (!info['primaryKeyId']) {
  3015. return
  3016. }
  3017. if (contractInfo.value?.contractType == 1) {
  3018. const { error, code, data } = await wbsApi.queryNodeStatus({
  3019. primaryKeyId: info['primaryKeyId'],
  3020. //classify:1
  3021. classify: authBtnTabKey.value,
  3022. })
  3023. //1 未填报,2待上报,3已上报
  3024. if (!error && code === 200) {
  3025. NodeStatus.value = data ?? '1'
  3026. } else {
  3027. NodeStatus.value = '1'
  3028. }
  3029. } else {
  3030. const { error, code, data } = await wbsApi.queryNodeStatusJl({
  3031. // primaryKeyId: info['contractIdRelation'] ? info['id'] : info['primaryKeyId'],
  3032. primaryKeyId: info['primaryKeyId'],
  3033. //classify: 1
  3034. classify: authBtnTabKey.value,
  3035. })
  3036. //1 未填报,2待上报,3已上报
  3037. if (!error && code === 200) {
  3038. NodeStatus.value = data ?? '1'
  3039. } else {
  3040. NodeStatus.value = '1'
  3041. }
  3042. }
  3043. }
  3044. //批量上报
  3045. const reportIds = ref('')
  3046. const reportTaskName = ref('')
  3047. const reportAddition = ref({})
  3048. const showReportModal = ref(false)
  3049. const reportLoading = ref(false)
  3050. const reportTypeData = ref([])
  3051. const reportModalClick = async () => {
  3052. const info = nodeDataInfo.value
  3053. const rows = ListItemDatas.value
  3054. if (rows.length > 0) {
  3055. reportLoading.value = true
  3056. const taskCheck = await eVisaTaskCheckApi({
  3057. projectId: projectId.value,
  3058. contractId:
  3059. contractInfo.value?.contractType == 2
  3060. ? info?.contractIdRelation
  3061. : contractId.value,
  3062. // contractId: contractId.value
  3063. })
  3064. //处理数据
  3065. let newArr = []
  3066. for (let i = 0; i < rows.length; i++) {
  3067. newArr.push(rows[i]['isTypePrivatePid'])
  3068. }
  3069. reportTypeData.value = newArr
  3070. reportLoading.value = false
  3071. if (taskCheck) {
  3072. //初始弹出弹窗,防呆
  3073. reportIds.value = info['primaryKeyId']
  3074. reportAddition.value = {
  3075. classify: authBtnTabKey.value,
  3076. contractIdRelation: info['contractIdRelation'],
  3077. }
  3078. showReportModal.value = true
  3079. //请求文件题名
  3080. const { data } = await wbsApi.queryDocumentTitle({
  3081. primaryKeyId: info['primaryKeyId'],
  3082. classify: authBtnTabKey.value,
  3083. })
  3084. reportTaskName.value = isString(data) ? data : ''
  3085. }
  3086. } else {
  3087. window.$message?.warning('暂无相关数据')
  3088. }
  3089. }
  3090. //上报完成
  3091. const showReportFinish = () => {
  3092. showReportModal.value = false
  3093. getTableDataAll()
  3094. window?.location?.reload() //刷新页面
  3095. }
  3096. //表单变量
  3097. const ListItemRef = ref(null)
  3098. const ListItemsRef = ref(null)
  3099. //保存
  3100. const tableFormSaveLoading = ref(false)
  3101. const tableFormSaveClick = async () => {
  3102. //获取数据
  3103. let FormData = [],
  3104. FormRegExpJson = {}
  3105. if (isDrawer.value) {
  3106. FormData = await ListItemsRef.value?.getFormData()
  3107. FormRegExpJson = await ListItemsRef.value?.getFormRegExpJson()
  3108. } else {
  3109. FormData = await ListItemRef.value?.getFormData()
  3110. FormRegExpJson = await ListItemRef.value?.getFormRegExpJson()
  3111. }
  3112. //效验数据
  3113. if (getObjVal(FormRegExpJson)) {
  3114. setFormRegExpJson(FormRegExpJson)
  3115. } else if (FormData.length > 0) {
  3116. console.log('保存')
  3117. tableFormSaveLoading.value = true
  3118. console.log('FormData', FormData)
  3119. const { error, code, msg, data } = await wbsApi.saveExcelBussData({
  3120. dataInfo: { orderList: FormData },
  3121. })
  3122. tableFormSaveLoading.value = false
  3123. if (!error && code === 200) {
  3124. window?.$message?.success('保存成功')
  3125. // await bussPdfsClick()
  3126. const activeKey = ListItemRef.value?.getActiveKey()
  3127. getTableDataAll(activeKey)
  3128. } else {
  3129. window?.$message?.error(msg || '操作失败')
  3130. }
  3131. } else {
  3132. console.log('预览')
  3133. // await bussPdfsClick()
  3134. }
  3135. }
  3136. //效验数据
  3137. const setFormRegExpJson = (FormRegExpJson) => {
  3138. let nodeName = '',
  3139. itemId = ''
  3140. Object.keys(FormRegExpJson).forEach((key) => {
  3141. const name = FormRegExpJson[key]?.nodeName ?? ''
  3142. if (name) {
  3143. if (nodeName) {
  3144. nodeName += ',' + name
  3145. } else {
  3146. nodeName = name
  3147. itemId = FormRegExpJson[key]?.itemId
  3148. }
  3149. }
  3150. })
  3151. //const activeKey = ListItemRef.value?.getActiveKey()
  3152. //弹出提示
  3153. const val
  3154. = '<div style="font-size: 16px;">请先完善 <span style="color:#1ECC95;">'
  3155. + nodeName
  3156. + '</span> 的数据内容</div>'
  3157. window?.$messageBox?.alert(val, '表单完善提醒', {
  3158. confirmButtonText: '确定',
  3159. dangerouslyUseHTMLString: true,
  3160. callback: (action) => {
  3161. if (action === 'confirm') {
  3162. ListItemRef.value?.setActiveKey(itemId)
  3163. ListItemOffsetTop(0)
  3164. setTimeout(() => {
  3165. const offsetTop
  3166. = document.getElementById(itemId)?.offsetTop
  3167. ListItemOffsetTop(offsetTop)
  3168. }, 350)
  3169. }
  3170. },
  3171. })
  3172. }
  3173. //多表预览
  3174. const bussPdfsLoading = ref(false)
  3175. const bussPdfsClick = async () => {
  3176. const info = nodeDataInfo.value
  3177. bussPdfsLoading.value = true
  3178. const { error, code, data } = await wbsApi.getBussPdfs({
  3179. nodeId: info?.primaryKeyId || '',
  3180. classify: authBtnTabKey.value,
  3181. projectId: projectId.value,
  3182. // contractId: contractId.value
  3183. contractId:
  3184. contractInfo.value?.contractType == 2
  3185. ? info?.contractIdRelation
  3186. : contractId.value,
  3187. })
  3188. tableFormSaveLoading.value = false
  3189. bussPdfsLoading.value = false
  3190. if (!error && code === 200) {
  3191. toPdfPage(data)
  3192. //window.open(data, '_blank')
  3193. } else {
  3194. window.$message?.warning('获取PDF失败')
  3195. }
  3196. }
  3197. //撤回上报流程
  3198. const abolishLoaing = ref(false)
  3199. const abolishOneClick = () => {
  3200. window?.$messageBox?.alert('请谨慎考虑后,是否确定撤回?', '撤回上报', {
  3201. showCancelButton: true,
  3202. confirmButtonText: '确定撤回',
  3203. cancelButtonText: '取消',
  3204. callback: (action) => {
  3205. if (action === 'confirm') {
  3206. abolishOneSave()
  3207. }
  3208. },
  3209. })
  3210. }
  3211. //撤回请求
  3212. const abolishOneSave = async () => {
  3213. const info = nodeDataInfo.value
  3214. abolishLoaing.value = true
  3215. const { error, code } = await wbsApi.abolishOne({
  3216. primaryKeyId: info?.primaryKeyId || '',
  3217. classify: authBtnTabKey.value,
  3218. projectId: projectId.value,
  3219. contractId: contractId.value,
  3220. })
  3221. abolishLoaing.value = false
  3222. if (!error && code === 200) {
  3223. window.$message?.success('撤回成功')
  3224. getTableDataAll()
  3225. window?.location?.reload() //刷新页面
  3226. }
  3227. }
  3228. //附件列表
  3229. const attachmentModal = ref(false)
  3230. const attachmentModalShow = () => {
  3231. attachmentModal.value = true
  3232. getAttachmentList()
  3233. // nextTick(()=>{
  3234. // initSortable()
  3235. // })
  3236. }
  3237. const attachmentListLoaing = ref(false)
  3238. const attachmentList = ref([])
  3239. const getAttachmentList = async () => {
  3240. attachmentListLoaing.value = true
  3241. const info = nodeDataInfo.value
  3242. const { error, code, data } = await wbsApi.tablesAndFile({
  3243. primaryKeyId: info?.primaryKeyId || '',
  3244. type: authBtnTabKey.value,
  3245. contractId: contractId.value,
  3246. projectId: projectId.value,
  3247. classify: authBtnTabKey.value,
  3248. })
  3249. attachmentListLoaing.value = false
  3250. if (!error && code === 200) {
  3251. attachmentList.value = getArrValue(data)
  3252. } else {
  3253. attachmentList.value = []
  3254. }
  3255. }
  3256. // 新增拖拽相关代码
  3257. const attachmentListRefs = ref([])
  3258. const sortableInstances = ref([])
  3259. const setAttachmentListRef = (el) => {
  3260. if (el) {
  3261. attachmentListRefs.value.push(el)
  3262. }
  3263. }
  3264. // 初始化拖拽排序
  3265. const initSortable = () => {
  3266. nextTick(() => {
  3267. attachmentList.value.forEach((item) => {
  3268. // 更可靠的DOM查找方式
  3269. const container = document.querySelector(`.hc-attachment-card[data-node-id="${item.id}"] .hc-attachment-content`)
  3270. if (container && !sortableInstances.value[item.id]) {
  3271. sortableInstances.value[item.id] = Sortable.create(container, {
  3272. animation: 150,
  3273. handle: '.hc-attachment-file-name',
  3274. onEnd: (evt) => {
  3275. // 确保能正确找到对应的item
  3276. const currentItem = attachmentList.value.find(i => i.id === item.id)
  3277. if (!currentItem) return
  3278. const newFileList = [...currentItem.fileList]
  3279. const [movedItem] = newFileList.splice(evt.oldIndex, 1)
  3280. newFileList.splice(evt.newIndex, 0, movedItem)
  3281. // 使用Vue的响应式更新
  3282. currentItem.fileList = newFileList
  3283. },
  3284. })
  3285. }
  3286. })
  3287. })
  3288. }
  3289. // 销毁 Sortable 实例
  3290. const destroySortableInstances = () => {
  3291. sortableInstances.value.forEach(instance => {
  3292. instance.destroy()
  3293. })
  3294. sortableInstances.value = [] // 清空引用数组
  3295. }
  3296. // 监听 attachmentModal 的变化
  3297. watch(attachmentModal, (newVal) => {
  3298. if (!newVal) {
  3299. destroySortableInstances() // 关闭弹窗时销毁 Sortable 实例
  3300. } else {
  3301. initSortable() // 打开弹窗时初始化 Sortable
  3302. }
  3303. })
  3304. onUnmounted(() => {
  3305. destroySortableInstances()
  3306. if (sortableInstance) {
  3307. sortableInstance.destroy()
  3308. sortableInstance = null
  3309. }
  3310. })
  3311. // 保存文件顺序到后端
  3312. const saveFileOrderLoad = ref(false)
  3313. const saveFileOrder = async () => {
  3314. saveFileOrderLoad.value = true
  3315. const { error, code, msg } = await wbsApi.sortPdf( attachmentList.value)
  3316. saveFileOrderLoad.value = false
  3317. if (!error && code === 200) {
  3318. window?.$message?.success(msg)
  3319. getAttachmentList()
  3320. initSortable()
  3321. }
  3322. }
  3323. // 监听attachmentList变化时初始化拖拽
  3324. watch(() => attachmentList.value, () => {
  3325. nextTick(()=>{
  3326. initSortable()
  3327. })
  3328. }, { deep: true })
  3329. //预览
  3330. const previewFile = (item) => {
  3331. toPdfPage(item['domainPdfUrl'])
  3332. //window.open(item['domainPdfUrl'], '_blank')
  3333. }
  3334. //删除
  3335. const delFile = async (item) => {
  3336. const { isTrial, id, tabId } = item
  3337. item.loading = true
  3338. let response
  3339. if (isTrial) {
  3340. response = await wbsApi.clearTrialAssociation({
  3341. nodeId:tabId,
  3342. recordId:id,
  3343. })
  3344. } else {
  3345. response = await wbsApi.removeBussFile({
  3346. ids: item.id,
  3347. })
  3348. }
  3349. const { error, code, msg } = response
  3350. item.loading = false
  3351. if (!error && code === 200) {
  3352. window?.$message?.success('删除成功')
  3353. getAttachmentList()
  3354. getTableDataAll()
  3355. return true
  3356. } else {
  3357. window.$message.error(msg)
  3358. return false
  3359. }
  3360. }
  3361. //划分变更
  3362. const divisionClick = () => {
  3363. router.push({
  3364. path: '/data-fill/division',
  3365. })
  3366. }
  3367. //树展开和收起
  3368. const isWbsTreeShow = ref(true)
  3369. const setWbsTreeShow = () => {
  3370. isWbsTreeShow.value = !isWbsTreeShow.value
  3371. }
  3372. //拷贝内容
  3373. const copyPositionText = (val) => {
  3374. if (val) {
  3375. //navigator.clipboard.writeText(val);
  3376. setCopyText(val)
  3377. .then(() => {
  3378. window.$message?.success('复制成功')
  3379. })
  3380. .catch(() => {
  3381. window.$message?.error('复制失败,请手动复制')
  3382. })
  3383. } else {
  3384. window.$message?.warning('没有可复制的数据')
  3385. }
  3386. }
  3387. //左右拖动,改变树形结构宽度
  3388. const isMouseTree = ref(false)
  3389. const onmousedown = () => {
  3390. let leftNum = 0
  3391. if (isLayout.value === 'no') {
  3392. leftNum = 0
  3393. } else {
  3394. leftNum = isCollapse.value ? 142 : 272
  3395. }
  3396. isMouseTree.value = true
  3397. document.onmousemove = async (ve) => {
  3398. let diffVal = ve.clientX - leftNum
  3399. if (diffVal >= 310 && diffVal <= 900) {
  3400. leftWidth.value = diffVal
  3401. }
  3402. }
  3403. document.onmouseup = () => {
  3404. document.onmousemove = null
  3405. document.onmouseup = null
  3406. isMouseTree.value = false
  3407. }
  3408. }
  3409. //更新配置
  3410. watch(
  3411. () => leftWidth.value,
  3412. (diffVal) => {
  3413. setUserConfig(diffVal)
  3414. },
  3415. )
  3416. const setUserConfig = async (data) => {
  3417. if (data > 0) {
  3418. await useClick()
  3419. useAppState.setTreeWidth(data)
  3420. await userConfigSave({ treeWidth: data })
  3421. }
  3422. }
  3423. //同步质检资料
  3424. const syncdataloading = ref(false)
  3425. const syncdata = async () => {
  3426. ListItemRef.value?.setActiveKey('')
  3427. const info = nodeDataInfo.value
  3428. syncdataloading.value = true
  3429. const { error, code, msg } = await wbsApi.syncTbadata({
  3430. pKeyId: info?.primaryKeyId || '',
  3431. })
  3432. syncdataloading.value = false
  3433. if (!error && code === 200) {
  3434. window.$message?.success(msg)
  3435. getTableDataAll()
  3436. // window?.location?.reload() //刷新页面
  3437. }
  3438. }
  3439. //同步工序资料
  3440. const syncWorkloading = ref(false)
  3441. const syncWork = async () => {
  3442. ListItemRef.value?.setActiveKey('')
  3443. const info = nodeDataInfo.value
  3444. syncdataloading.value = true
  3445. const { error, code, msg } = await wbsApi.syncWorkDate({
  3446. nodeId: info?.primaryKeyId || '',
  3447. })
  3448. syncdataloading.value = false
  3449. if (!error && code === 200) {
  3450. window.$message?.success(msg)
  3451. getTableDataAll()
  3452. // window?.location?.reload() //刷新页面
  3453. }
  3454. }
  3455. //附件添加
  3456. const typeoptions = ref([
  3457. {
  3458. value: '1',
  3459. label: '模板1',
  3460. },
  3461. {
  3462. value: '2',
  3463. label: '模板2',
  3464. },
  3465. ])
  3466. const getFileTypeApi = async () => {
  3467. const { data } = await getDictionaryBiz({
  3468. code: 'table_file_type',
  3469. })
  3470. //处理数据
  3471. let newArr = []
  3472. const newData = getArrValue(data)
  3473. for (let i = 0; i < newData.length; i++) {
  3474. newArr.push({
  3475. label: newData[i]['dictValue'],
  3476. value: Number(newData[i]['dictKey']),
  3477. })
  3478. }
  3479. typeoptions.value = newArr
  3480. }
  3481. const typevalue = ref('')
  3482. const isCanadd = ref(true)
  3483. const uploadModal = ref(false)
  3484. const fileListData = ref([])
  3485. const uploadData = ref({})
  3486. const uploadModalClose = () => {
  3487. uploadModal.value = false
  3488. typevalue.value = ''
  3489. }
  3490. //获取附件添加列表
  3491. const getBussFileList = async (pkeyId) => {
  3492. const { error, code, data } = await wbsApi.selectTableFileListByTen({
  3493. pkeyid: pkeyId,
  3494. classify: authBtnTabKey.value,
  3495. })
  3496. if (!error && code === 200) {
  3497. fileListData.value = getArrValue(data)
  3498. } else {
  3499. fileListData.value = []
  3500. }
  3501. }
  3502. const addFilelist = async () => {
  3503. getBussFileList(primaryKeyId.value)
  3504. uploadModal.value = true
  3505. await getFileTypeApi()
  3506. //上传的配置
  3507. uploadData.value = {
  3508. classify: authBtnTabKey.value,
  3509. nodeId: primaryKeyId.value,
  3510. type: typevalue.value,
  3511. contractId: contractId.value,
  3512. }
  3513. }
  3514. const changeType = (val) => {
  3515. uploadData.value.type = val
  3516. }
  3517. //上传文件
  3518. const uploadChange = async ({ type }) => {
  3519. if (type === 'success') {
  3520. getBussFileList(primaryKeyId.value)
  3521. } else if (type === 'del') {
  3522. getBussFileList(primaryKeyId.value)
  3523. }
  3524. }
  3525. const uploadUpdate = (list)=>{
  3526. fileListData.value = list
  3527. }
  3528. //树节点被选中
  3529. const treeSelectNode = ref([])
  3530. const treeSelectdata = ref([])
  3531. const ElTreeNodeCheck = (_, { checkedKeys, checkedNodes }) => {
  3532. console.log(checkedNodes, 'checkedNodes')
  3533. treeSelectNode.value = getArrValue(checkedKeys)
  3534. treeSelectdata.value = getArrValue(checkedNodes)
  3535. }
  3536. const loadMenu = ({ node, item, level }, resolve) => {
  3537. setElTreeMenu(contractInfo.value?.contractType)
  3538. let menusArr = ElTreeMenu.value
  3539. console.log(menusArr, 'menusArr')
  3540. if (level === 1) {
  3541. // menusArr = [
  3542. // {
  3543. // icon: 'add-circle',
  3544. // label: '自定义节点(水利工程)',
  3545. // key: 'add1',
  3546. // },
  3547. // {
  3548. // icon: 'add-circle',
  3549. // label: '自定义节点(数字化文件)',
  3550. // key: 'add2',
  3551. // },
  3552. // ]
  3553. resolve(menusArr)
  3554. } else {
  3555. resolve(menusArr)
  3556. }
  3557. }
  3558. //批量保存
  3559. const nodeSaveLoading = ref(false)
  3560. const NodeSaveClick = async () => {
  3561. const keys = treeSelectNode.value
  3562. const rows = treeSelectdata.value
  3563. if (rows.length <= 0 || keys.length <= 0) {
  3564. window?.$message?.warning('请先在左侧项目树选择节点')
  3565. return
  3566. }
  3567. //判断是否满足条件
  3568. let result = false
  3569. if (!website.localModel) {
  3570. result = rows.every(({ colorStatus }) => {
  3571. return colorStatus === 1 || colorStatus === 2
  3572. })
  3573. } else {
  3574. //183 甬台温
  3575. result = rows.every(({ colorStatus }) => {
  3576. return colorStatus === 1 || colorStatus === 2 || colorStatus === 4
  3577. })
  3578. }
  3579. if (!result) {
  3580. window?.$message?.warning('只能选择未上报的节点进行辅助保存')
  3581. return
  3582. }
  3583. //发起请求
  3584. nodeSaveLoading.value = true
  3585. const { error, code, msg } = await wbsApi.save_nodeId(
  3586. {
  3587. projectId: projectId.value,
  3588. contractId: contractId.value,
  3589. classify: authBtnTabKey.value,
  3590. nodeIds: keys.join(),
  3591. },
  3592. false,
  3593. )
  3594. nodeSaveLoading.value = false
  3595. if (!error && code === 200) {
  3596. window?.$message?.success('批量保存成功')
  3597. window?.location?.reload() //刷新页面
  3598. }
  3599. }
  3600. //排序
  3601. const tableSortFormRef = ref(null)
  3602. const sortFormShow = ref(false)
  3603. const tableSortFormColumn = [{ key: 'nodeName', name: '名称' }]
  3604. const tableSortFormData = ref([])
  3605. const sortFormClick = () => {
  3606. sortFormShow.value = true
  3607. tableSortFormData.value = deepClone(ListItemDatas.value)
  3608. }
  3609. // 行拖拽
  3610. const sortFormDropTap = (rows) => {
  3611. tableSortFormData.value = [] // 先清空,否则排序会异常
  3612. nextTick(() => {
  3613. tableSortFormRef.value?.setData(rows)
  3614. })
  3615. }
  3616. // 点击排序
  3617. const rowSortFormTap = (rows) => {
  3618. tableSortFormData.value = [] // 先清空,否则排序会异常
  3619. nextTick(() => {
  3620. tableSortFormData.value = rows
  3621. })
  3622. }
  3623. //关闭排序
  3624. const sortFormClose = () => {
  3625. sortFormShow.value = false
  3626. sortFormLoading.value = false
  3627. tableSortFormData.value = []
  3628. }
  3629. //提交排序
  3630. const sortFormLoading = ref(false)
  3631. const sortFormSubmit = async () => {
  3632. const treeId = primaryKeyId.value
  3633. if (isNullES(treeId)) {
  3634. window?.$message?.warning('请先在左侧项目树选择一个节点')
  3635. return
  3636. }
  3637. const rows = tableSortFormData.value
  3638. const ids = arrToKey(rows, 'pkeyId')
  3639. //发起请求
  3640. sortFormLoading.value = true
  3641. const { error, code, msg } = await wbsApi.formTableSort(
  3642. {
  3643. projectId: projectId.value,
  3644. contractId: contractId.value,
  3645. classify: authBtnTabKey.value,
  3646. nodeIds: treeId,
  3647. ids: ids,
  3648. },
  3649. false,
  3650. )
  3651. sortFormLoading.value = false
  3652. if (!error && code === 200) {
  3653. window?.$message?.success('操作成功')
  3654. window?.location?.reload() //刷新页面
  3655. }
  3656. }
  3657. //文件题名
  3658. const titleInput = ref('')
  3659. //节点基础数据
  3660. const nodeBaseDataModalDialog = ref(false)
  3661. const nodeBaseDataClick = async ()=>{
  3662. await nextTick()
  3663. await getnodeBaseData()
  3664. nodeBaseDataModalDialog.value = true
  3665. }
  3666. const nodeBaseDataLoad = ref(false)
  3667. const getnodeBaseData = async ()=>{
  3668. const { error, code, msg, data } = await nodeBaseApi.getNodeData(
  3669. {
  3670. pKeyId: primaryKeyId.value,
  3671. classify: authBtnTabKey.value,
  3672. },
  3673. )
  3674. if (!error && code === 200) {
  3675. autoFormData.value = getObjValue(data)
  3676. }
  3677. }
  3678. const getOrSaveNodeBaseInfo = async ()=>{
  3679. const { error, code, msg, data } = await nodeBaseApi.getOrSaveNodeBaseInfo(
  3680. {
  3681. pKeyId: primaryKeyId.value,
  3682. },
  3683. )
  3684. if (!error && code === 200) {
  3685. console.log(data, 'data')
  3686. autoFormData.value = getObjValue(data)
  3687. autoFormData.value.unit = data.unit === null ? '' : data.unit || ''
  3688. autoFormData.value.subUnit = data.subUnit === null ? '' : data.subUnit || ''
  3689. autoFormData.value.division = data.division === null ? '' : data.division || ''
  3690. autoFormData.value.subDivision = data.subDivision === null ? '' : data.subDivision || ''
  3691. autoFormData.value.subItem = data.subItem === null ? '' : data.subItem || ''
  3692. autoFormData.value.item = data.item === null ? '' : data.item || ''
  3693. autoFormData.value.processes = data.processes === null ? '' : data.processes || ''
  3694. window?.$message?.success(msg)
  3695. }
  3696. }
  3697. const nodeBaseDataModalClose = ()=>{
  3698. nodeBaseDataModalDialog.value = false
  3699. }
  3700. const autoFormData = ref(
  3701. {
  3702. unit: '',
  3703. subUnit: '',
  3704. division: '',
  3705. subDivision: '',
  3706. subItem: '',
  3707. item: '',
  3708. processes: '',
  3709. },
  3710. )
  3711. const resetForm = ()=>{
  3712. getOrSaveNodeBaseInfo()
  3713. }
  3714. const nodeBaseDataModalSave = async ()=>{
  3715. if (autoFormData.value?.isDisable === 1) {
  3716. window?.$message?.warning('待审批和已审批不能修改基础数据')
  3717. return
  3718. }
  3719. nodeBaseDataLoad.value = true
  3720. const { error, code, msg } = await nodeBaseApi.save(
  3721. {
  3722. nodeId: primaryKeyId.value,
  3723. ...autoFormData.value,
  3724. },
  3725. )
  3726. nodeBaseDataLoad.value = false
  3727. if (!error && code === 200) {
  3728. window?.$message?.success(msg || '操作成功')
  3729. nodeBaseDataModalDialog.value = false
  3730. //刷新页面
  3731. // setTimeout(() => {
  3732. // window?.location?.reload()
  3733. // }, 1000)
  3734. const activeKey = ListItemRef.value?.getActiveKey()
  3735. getTableDataAll(activeKey)
  3736. }
  3737. }
  3738. const showMoveClick = async (node, data)=>{
  3739. await nextTick()
  3740. moveDialogShow.value = true
  3741. }
  3742. const moveDialogShow = ref(false)
  3743. /**
  3744. * 关闭移动对话框
  3745. *
  3746. * 当点击保存按钮时,调用此方法关闭移动对话框。
  3747. */
  3748. const moveSaveClick = ()=>{
  3749. moveDialogShow.value = false
  3750. // 刷新页面
  3751. window?.location?.reload()
  3752. }
  3753. // 收藏夹
  3754. // 控制tooltip显示状态
  3755. const collectListVisible = ref(false)
  3756. const collectListClick = async ()=>{
  3757. await nextTick()
  3758. getCollectList()
  3759. // 点击时显示收藏夹列表
  3760. collectListVisible.value = true
  3761. }
  3762. // 触发元素引用
  3763. const triggerRef = ref(null)
  3764. // 显示添加输入框
  3765. const showAddInput = ref(false)
  3766. // 新文件夹名称
  3767. const newFolderName = ref('')
  3768. // 文件夹列表
  3769. // 最多显示5个文件夹
  3770. const confirmAddFolderLoad = ref(false)
  3771. // 确认添加文件夹
  3772. const confirmAddFolder = async () => {
  3773. if (!newFolderName.value.trim()) return window?.$message?.error('请输入文件夹名称')
  3774. confirmAddFolderLoad.value = true
  3775. const { error, code, msg } = await collectApi.saveOrUpdateFolder(
  3776. {
  3777. nodeId: primaryKeyId.value,
  3778. contractId: contractId.value,
  3779. name: newFolderName.value.trim(),
  3780. type:1,
  3781. },
  3782. false,
  3783. )
  3784. confirmAddFolderLoad.value = false
  3785. if (!error && code === 200) {
  3786. window?.$message?.success(msg)
  3787. newFolderName.value = ''
  3788. showAddInput.value = false
  3789. getCollectList().then(() => {
  3790. // 数据更新后重新初始化拖拽
  3791. nextTick(() => {
  3792. initSortableCollect()
  3793. })
  3794. })
  3795. }
  3796. }
  3797. // 取消添加文件夹
  3798. const cancelAddFolder = async (id) => {
  3799. newFolderName.value = ''
  3800. showAddInput.value = false
  3801. }
  3802. // 删除文件夹的接口调用
  3803. const removeCollect = async (id) => {
  3804. const { error, code, msg } = await collectApi.deleteFolder({ id })
  3805. if (!error && code === 200) {
  3806. window?.$message?.success(msg)
  3807. // 等待数据更新完成
  3808. getCollectList().then(() => {
  3809. // 数据更新后重新初始化拖拽
  3810. nextTick(() => {
  3811. initSortableCollect()
  3812. })
  3813. })
  3814. }
  3815. }
  3816. // 删除文件夹的交互逻辑
  3817. const deleteFolder = async (index, item) => {
  3818. HcDelMsg(async (resolve) => {
  3819. // 等待删除接口和数据更新完成
  3820. await removeCollect(item.id)
  3821. resolve() // 关闭弹窗
  3822. collectListVisible.value = true
  3823. // 关键:等待Vue完成DOM更新后,再初始化拖拽
  3824. })
  3825. }
  3826. // 控制缩放状态的变量
  3827. const isScaling = ref(false)
  3828. // 点击事件处理函数
  3829. const handleClick = () => {
  3830. // 触发缩放效果
  3831. isScaling.value = true
  3832. // 缩放动画结束后重置状态
  3833. setTimeout(() => {
  3834. isScaling.value = false
  3835. }, 300) // 与CSS过渡时间保持一致
  3836. //重新加载左边树
  3837. folderId.value = ''
  3838. isLookHistory.value = false
  3839. isLookHide.value = true
  3840. isSearchTree.value = false
  3841. searchTreeVal.value = ''
  3842. isShowLeft.value = false
  3843. setTimeout(() => {
  3844. isShowLeft.value = true
  3845. setElTreeMenu(authBtnTabKey.value)
  3846. }, 500)
  3847. getTableDataAll()
  3848. }
  3849. //收藏
  3850. const collectTreeData = ref({})
  3851. const collectDialogPosition = ref(null)
  3852. const collectClick = async (data, position)=>{
  3853. collectTreeData.value = data
  3854. collectDialogPosition.value = position
  3855. if (data.isCollect === 0) {
  3856. collectDialog.value = true
  3857. const hasMatch = collectList.value.some(item => item.id === collectForm.value.id)
  3858. if (!hasMatch) {
  3859. collectForm.value.id = ''
  3860. collectForm.value.name = ''
  3861. }
  3862. await nextTick()
  3863. // 获取元素
  3864. const modal = document.querySelector('.collectModalStyle')
  3865. // 动态设置位置
  3866. if (modal && collectDialogPosition) {
  3867. modal.style.left = collectDialogPosition.value.left
  3868. modal.style.top = collectDialogPosition.value.top
  3869. modal.style.position = 'fixed'
  3870. modal.style.transform = 'translateY(0) translateX(0)' // 重置transform,防止位置偏移
  3871. }
  3872. getCollectList()
  3873. } else {
  3874. console.log('取消收藏')
  3875. collectModalCancel()
  3876. }
  3877. }
  3878. const collectModalCancel = async ()=>{
  3879. const { error, code, msg } = await collectApi.collect(
  3880. {
  3881. id:'',
  3882. nodeId: collectTreeData.value.primaryKeyId,
  3883. contractId: contractId.value,
  3884. name: '',
  3885. type:0,
  3886. },
  3887. false,
  3888. )
  3889. if (!error && code === 200) {
  3890. // window?.$message?.success(msg)
  3891. collectTreeData.value.isCollect = 0
  3892. }
  3893. }
  3894. const collectDialog = ref(false)
  3895. const collectLoad = ref(false)
  3896. const collectModalClose = ()=>{
  3897. collectDialog.value = false
  3898. }
  3899. const checkCollect = (val)=>{
  3900. collectList.value.forEach(item => {
  3901. if (item.id === val) {
  3902. collectForm.value.name = item.name
  3903. }
  3904. })
  3905. }
  3906. const saveCollectLoad = ref(false)
  3907. const collectModalSave = async ()=>{
  3908. const validate = await formValidate(collectFormRef.value)
  3909. if (!validate) return
  3910. saveCollectLoad.value = true
  3911. const { error, code, msg } = await collectApi.collect(
  3912. {
  3913. id:collectForm.value.id,
  3914. nodeId: collectTreeData.value.primaryKeyId,
  3915. contractId: contractId.value,
  3916. name: collectForm.value.name,
  3917. type:1,
  3918. },
  3919. false,
  3920. )
  3921. saveCollectLoad.value = false
  3922. if (!error && code === 200) {
  3923. window?.$message?.success(msg)
  3924. collectTreeData.value.isCollect = 1
  3925. collectDialog.value = false
  3926. }
  3927. }
  3928. const collectFormRef = ref(null)
  3929. const collectForm = ref({
  3930. name:'',
  3931. id:'',
  3932. })
  3933. const collectRules = ref({
  3934. id: [
  3935. {
  3936. required: true,
  3937. message: '请选择收藏夹',
  3938. trigger: 'change',
  3939. },
  3940. ],
  3941. })
  3942. const collectList = ref([])
  3943. const editInput = ref(null)
  3944. // 文件夹列表容器的引用
  3945. const folderListContainer = ref(null)
  3946. // Sortable实例
  3947. let sortableInstance = null
  3948. // 初始化拖拽排序功能
  3949. // 改进初始化拖拽排序功能,先销毁再创建
  3950. const initSortableCollect = () => {
  3951. // 先销毁可能存在的实例
  3952. destroySortable()
  3953. // 确保容器已挂载
  3954. if (folderListContainer.value) {
  3955. sortableInstance = new Sortable(folderListContainer.value, {
  3956. animation: 150,
  3957. handle: '.folder-item',
  3958. ghostClass: 'sortable-ghost',
  3959. onEnd: handleSortEnd,
  3960. })
  3961. }
  3962. }
  3963. // 处理拖拽结束事件
  3964. const handleSortEnd = async (evt) => {
  3965. // 保存原始顺序,用于出错时恢复
  3966. const originalList = [...collectList.value]
  3967. // 从原位置移除并插入到新位置
  3968. const [movedItem] = collectList.value.splice(evt.oldIndex, 1)
  3969. collectList.value.splice(evt.newIndex, 0, movedItem)
  3970. // 调用API保存新的排序
  3971. const folderIds = arrToKey(collectList.value, 'id')
  3972. const { error, code, msg } = await collectApi.sortFolder({
  3973. ids: folderIds,
  3974. })
  3975. if (!error && code === 200) {
  3976. window?.$message?.success(msg)
  3977. getCollectList()
  3978. } else {
  3979. // 出错时恢复原始顺序
  3980. collectList.value = originalList
  3981. }
  3982. }
  3983. // 添加销毁Sortable实例的函数
  3984. const destroySortable = () => {
  3985. if (sortableInstance) {
  3986. sortableInstance.destroy()
  3987. sortableInstance = null
  3988. }
  3989. }
  3990. // 监听collectList变化,数据加载完成后初始化拖拽
  3991. watch(collectList, (newVal) => {
  3992. if (newVal.length > 0) {
  3993. // 延迟初始化,确保DOM已更新
  3994. nextTick(() => {
  3995. initSortableCollect()
  3996. })
  3997. }
  3998. })
  3999. const getCollectList = async ()=>{
  4000. collectLoad.value = true
  4001. const { error, code, msg, data } = await collectApi.folderList(
  4002. {
  4003. contractId: contractId.value,
  4004. },
  4005. )
  4006. collectLoad.value = false
  4007. if (!error && code === 200) {
  4008. collectList.value = getArrValue(data)
  4009. collectList.value = getArrValue(data).map(folder => ({
  4010. ...folder,
  4011. isEditing: false, // 是否处于编辑状态
  4012. editableName: folder.name, // 编辑框绑定的值
  4013. originalName: folder.name, // 原始名称,用于取消编辑时恢复
  4014. }))
  4015. } else {
  4016. collectList.value = []
  4017. }
  4018. // setTimeout(initSortableCollect, 0)
  4019. }
  4020. // 开始编辑文件夹名称
  4021. const startEdit = (folder) => {
  4022. collectList.value.forEach((ele)=>{
  4023. ele.isEditing = false
  4024. })
  4025. // 记录原始名称用于取消编辑时恢复
  4026. folder.originalName = folder.name
  4027. // 设置编辑状态并初始化编辑框的值
  4028. folder.isEditing = true
  4029. folder.editableName = folder.name
  4030. // 确保输入框渲染后自动聚焦
  4031. nextTick(() => {
  4032. const input = document.querySelector(`.folder-item:nth-child(${collectList.value.indexOf(folder) + 1}) .el-input__inner`)
  4033. if (input) input.focus()
  4034. })
  4035. }
  4036. // 确认编辑
  4037. // 修改确认编辑函数,添加重新初始化拖拽
  4038. const confirmEdit = async (index, folder) => {
  4039. if (!folder.editableName.trim()) {
  4040. window.$message.warning('文件夹名称不能为空')
  4041. return
  4042. }
  4043. const { error, code, msg } = await collectApi.saveOrUpdateFolder({
  4044. nodeId: primaryKeyId.value,
  4045. contractId: contractId.value,
  4046. name: folder.editableName.trim(),
  4047. type: 1,
  4048. id: folder.id,
  4049. })
  4050. if (!error && code === 200) {
  4051. window.$message.success(msg)
  4052. folder.isEditing = false
  4053. getCollectList().then(() => {
  4054. // 数据更新后重新初始化拖拽
  4055. nextTick(() => {
  4056. initSortableCollect()
  4057. })
  4058. })
  4059. }
  4060. }
  4061. const folderId = ref(null)
  4062. const selectFolder = async (folder) => {
  4063. collectListVisible.value = false
  4064. folderId.value = folder.id
  4065. // isSearchTree.value = true
  4066. // getSearchTreeData('folder')
  4067. //重新加载左边树
  4068. isShowLeft.value = false
  4069. setTimeout(() => {
  4070. isSearchTree.value = false
  4071. isLookHide.value = true
  4072. isLookHistory.value = false
  4073. isShowLeft.value = true
  4074. selCollectMneu()
  4075. }, 500)
  4076. }
  4077. const selCollectMneu = ()=>{
  4078. let newArr = []
  4079. if (folderId.value) {
  4080. if (HcIsButton('wbs_tree_edit')) {
  4081. newArr.push({ icon: 'draft', label: '编辑节点', key: 'edit' })
  4082. }
  4083. if (HcIsButton('wbs_tree_del')) {
  4084. newArr.push({ icon: 'delete-bin', label: '删除节点', key: 'del' })
  4085. }
  4086. if (HcIsButton('wbs_tree_upload')) {
  4087. newArr.push({
  4088. icon: 'file-upload',
  4089. label: '上传图纸',
  4090. key: 'upload',
  4091. })
  4092. }
  4093. if (HcIsButton('wbs_tree_mark')) {
  4094. newArr.push({ icon: 'star', label: '标记为首件', key: 'mark' })
  4095. TreeMark.value = true
  4096. }
  4097. ElTreeMenu.value = newArr
  4098. }
  4099. }
  4100. // 输入框失焦处理
  4101. const handleEditBlur = (folder) => {
  4102. }
  4103. // 获取文件夹列表的方法需要修改,为每个文件夹添加编辑相关属性
  4104. //查看最近操作的节点
  4105. const lookLoading = ref(false)
  4106. const isLookHistory = ref(false)
  4107. const lookHistory = ()=>{
  4108. isLookHistory.value = true
  4109. isSearchTree.value = true
  4110. folderId.value = ''
  4111. setElTreeMenu(authBtnTabKey.value)
  4112. getSearchTreeData('history')
  4113. }
  4114. //隐藏节点
  4115. //隐藏节点
  4116. const eyeClick = (data)=>{
  4117. nodeDataInfo.value = data
  4118. hideTreeNode(data)
  4119. }
  4120. const hideSaveLoading = ref(false)
  4121. const hideTreeNode = (data) => {
  4122. if ([3, 4].includes(data.colorStatus)) {
  4123. window.$message.warning('已审批”、“已填报-待审批”的节点不允许隐藏;')
  4124. return
  4125. }
  4126. HcFirmMsg( {
  4127. title: data.isBussShow === 2 ? '确定要显示此节点吗?' : '确定要隐藏此节点吗?',
  4128. text: '请确认要执行此操作吗?',
  4129. }, async (resolve) => {
  4130. hideSaveLoading.value = true
  4131. //发起请求
  4132. hideSaveLoading.value = true
  4133. const { error, code, msg } = await wbsApi.updateNodeStates(
  4134. {
  4135. ids: data['primaryKeyId'],
  4136. // status: 2,
  4137. status:data.isBussShow == 2 ? 0 : 2, //2隐藏 0显示
  4138. },
  4139. false,
  4140. )
  4141. hideSaveLoading.value = false
  4142. if (!error && code === 200) {
  4143. data.isBussShow = data.isBussShow == 2 ? 0 : 2
  4144. }
  4145. resolve()
  4146. })
  4147. }
  4148. const isLookHide = ref(true)
  4149. const handleClickBack = ()=>{
  4150. //重新加载左边树
  4151. folderId.value = null
  4152. isLookHide.value = true
  4153. isLookHistory.value = false
  4154. isSearchTree.value = false
  4155. searchTreeVal.value = ''
  4156. isShowLeft.value = false
  4157. setTimeout(() => {
  4158. isShowLeft.value = true
  4159. setElTreeMenu(authBtnTabKey.value)
  4160. }, 500)
  4161. getTableDataAll()
  4162. }
  4163. const lookHideList = ()=>{
  4164. isLookHide.value = false
  4165. isSearchTree.value = true
  4166. folderId.value = ''
  4167. setElTreeMenu(authBtnTabKey.value)
  4168. getSearchTreeData('hide')
  4169. }
  4170. //关联构建编码
  4171. const wbsLinkModal = ref(false)
  4172. const linkSaveClick = ()=>{
  4173. // wbsLinkModal.value = true
  4174. }
  4175. const linkModalClose = ()=>{
  4176. wbsLinkModal.value = false
  4177. }
  4178. //资料导入
  4179. const divisionImportDialog = ref(false)
  4180. const currentPkeyId = ref('')
  4181. const dataImportDialogClick = ()=>{
  4182. divisionImportDialog.value = true
  4183. }
  4184. const handleUploadSuccess = ()=>{
  4185. }
  4186. const handleUploadError = ()=>{
  4187. }
  4188. </script>
  4189. <style lang="scss" scoped>
  4190. @import "../../styles/data-fill/wbs.scss";
  4191. .hc-project-box{
  4192. display: flex;
  4193. justify-content: space-between;
  4194. align-items: center;
  4195. font-size:20px;
  4196. }
  4197. .title-input{
  4198. height: 30px;
  4199. padding: 10px;
  4200. border: 1px solid #dcdfe6;
  4201. background-color: #dcdfe6;
  4202. line-height: 13px;
  4203. border-radius: 5px;
  4204. font-weight: 500;
  4205. margin-left: 4px;
  4206. max-width: 300px;
  4207. overflow-x: auto;
  4208. overflow-y: hidden;
  4209. }
  4210. .hc-add-node-modal-foot-box {
  4211. position: relative;
  4212. display: flex;
  4213. align-items: center;
  4214. .left-box {
  4215. position: relative;
  4216. flex: 1;
  4217. display: flex;
  4218. align-items: center;
  4219. }
  4220. .right-box {
  4221. position: relative;
  4222. }
  4223. }
  4224. .hc-expansion-contraction-tree {
  4225. position: absolute;
  4226. left: -13px;
  4227. top: 0;
  4228. width: 10px;
  4229. height: 100%;
  4230. user-select: none;
  4231. cursor: pointer;
  4232. display: flex;
  4233. justify-content: center;
  4234. align-items: center;
  4235. color: #8c9099;
  4236. font-size: 22px;
  4237. border-radius: 5px;
  4238. transition: background 0.2s;
  4239. background: rgba(255, 255, 255, 0);
  4240. &:hover {
  4241. background: #f1f5f8;
  4242. color: var(--el-color-primary);
  4243. }
  4244. }
  4245. .hc-table-form-action-tip {
  4246. position: absolute;
  4247. bottom: 77px;
  4248. width: 100%;
  4249. }
  4250. .data-fill-wbs-hide-btn {
  4251. background: #fff;
  4252. color: #ffffff;
  4253. }
  4254. html.dark .data-fill-wbs-hide-btn {
  4255. background: #141414;
  4256. color: #141414;
  4257. }
  4258. html.theme-dark {
  4259. .bg-svg-xml {
  4260. background-color: initial;
  4261. background-image: initial;
  4262. }
  4263. .hc-layout-box
  4264. .hc-layout-content-box
  4265. .hc-card-max-h-box.node-tree
  4266. .hc-tree-foot-tip-box {
  4267. border-top: 1px solid #303030;
  4268. }
  4269. }
  4270. </style>
  4271. <style lang="scss">
  4272. .hc-tree-box1 .el-tree-node {
  4273. .el-checkbox {
  4274. margin-right: 0;
  4275. .el-checkbox__inner {
  4276. display: none;
  4277. }
  4278. }
  4279. .is-leaf + .el-checkbox {
  4280. margin-right: 8px;
  4281. .el-checkbox__inner {
  4282. display: inline-block;
  4283. }
  4284. }
  4285. }
  4286. .data-fill-wbs-content {
  4287. position: relative;
  4288. height: 100%;
  4289. .n-drawer-container {
  4290. margin: -20px -24px;
  4291. }
  4292. .n-drawer.n-drawer--top-placement {
  4293. height: auto !important;
  4294. background-color: initial;
  4295. pointer-events: none;
  4296. bottom: 0;
  4297. }
  4298. .drawer-data-fill-content-box {
  4299. position: relative;
  4300. height: 100%;
  4301. padding: 24px;
  4302. .n-card {
  4303. pointer-events: auto;
  4304. height: 100%;
  4305. overflow: auto;
  4306. }
  4307. .data-fill-content {
  4308. position: relative;
  4309. height: 100%;
  4310. overflow-y: auto;
  4311. scroll-behavior: smooth;
  4312. .data-fill-list-box .data-fill-list-item-content {
  4313. height: calc(100vh - 470px);
  4314. .data-fill-table-form-box {
  4315. height: 100%;
  4316. }
  4317. }
  4318. }
  4319. .data-fill-foot {
  4320. position: relative;
  4321. text-align: center;
  4322. }
  4323. }
  4324. }
  4325. .n-card.hc-card-overflow-box .n-card__content {
  4326. padding: 24px;
  4327. }
  4328. .n-card.hc-custom-card > .n-card-header {
  4329. padding: 15px 24px;
  4330. }
  4331. .n-card.hc-custom-card.copy {
  4332. width: 1200px;
  4333. max-height: 90vh;
  4334. overflow: auto;
  4335. .n-card-header .n-card-header__close {
  4336. display: none;
  4337. }
  4338. &.one {
  4339. width: 600px;
  4340. }
  4341. &.many {
  4342. width: 1200px;
  4343. }
  4344. }
  4345. .img-preview-box {
  4346. position: relative;
  4347. height: 100%;
  4348. width: 100%;
  4349. }
  4350. .hc-layout-content-box {
  4351. position: relative;
  4352. }
  4353. .iscusor {
  4354. cursor: pointer;
  4355. }
  4356. .hc-table-form-action-tip .hc-alert {
  4357. background-color: #f1f5f8;
  4358. display: inline;
  4359. vertical-align: middle;
  4360. box-shadow: -2px 0 10px 0 rgba(32, 37, 50, 0.03),
  4361. 0 10px 21px 20px rgba(32, 37, 50, 0.03);
  4362. }
  4363. .copy-node-form-box {
  4364. margin-top: 24px;
  4365. padding-top: 24px;
  4366. border-top: 1px solid #efeff5;
  4367. }
  4368. .hc-position-input-icon {
  4369. position: relative;
  4370. margin-bottom: 0;
  4371. .el-form-item__content {
  4372. position: relative;
  4373. .el-textarea .el-textarea__inner {
  4374. padding-right: 30px;
  4375. }
  4376. .hc-icon-i {
  4377. position: absolute;
  4378. right: 10px;
  4379. bottom: 0;
  4380. font-size: 20px;
  4381. cursor: pointer;
  4382. color: #0081ff;
  4383. opacity: 1;
  4384. transition: opacity 0.2s;
  4385. &:hover {
  4386. opacity: 0.5;
  4387. }
  4388. }
  4389. }
  4390. }
  4391. </style>
  4392. <style lang="scss" scoped>
  4393. /* 由小变大的脉动动画效果 */
  4394. .animate-pulse {
  4395. /* 保持动画持续运行 */
  4396. animation: pulse 1.5s ease-in-out infinite;
  4397. /* 确保图标变换时不会超出容器 */
  4398. transform-origin: center;
  4399. }
  4400. @keyframes pulse {
  4401. 0%, 100% {
  4402. /* 原始大小 */
  4403. transform: scale(1);
  4404. }
  4405. 50% {
  4406. /* 放大到1.2倍 */
  4407. transform: scale(1.2);
  4408. }
  4409. }
  4410. .hc-tree-back-to{
  4411. display: flex;
  4412. justify-content: space-between;
  4413. }
  4414. /* 新增拖拽排序相关样式 */
  4415. .sortable-ghost {
  4416. opacity: 0.5;
  4417. background: #f5f5f5;
  4418. justify-content: center;
  4419. }
  4420. .hc-attachment-item {
  4421. transition: all 0.3s;
  4422. cursor: move;
  4423. display: flex;
  4424. justify-content: space-between;
  4425. align-items: center;
  4426. padding: 12px;
  4427. margin-bottom: 8px;
  4428. background: #fff;
  4429. border-radius: 4px;
  4430. border: 1px solid #ebeef5;
  4431. &:hover {
  4432. box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  4433. }
  4434. }
  4435. .hc-attachment-content {
  4436. min-height: 20px;
  4437. }
  4438. /* 原有样式保持不变 */
  4439. .hc-attachment-card {
  4440. margin-bottom: 16px;
  4441. .hc-attachment-header {
  4442. font-weight: bold;
  4443. margin-bottom: 8px;
  4444. padding-left: 8px;
  4445. border-left: 3px solid #409eff;
  4446. }
  4447. .hc-attachment-file-name {
  4448. display: flex;
  4449. align-items: center;
  4450. .name {
  4451. margin-left: 8px;
  4452. }
  4453. }
  4454. .hc-attachment-btn-box {
  4455. display: flex;
  4456. }
  4457. }
  4458. </style>
  4459. <style>
  4460. .custom-tooltip-pro {
  4461. background-color: #7691E0 !important;
  4462. color: white !important;
  4463. border: none !important;
  4464. max-width: 300px !important; /* 最大宽度 */
  4465. padding: 10px !important;
  4466. font-size: 14px;
  4467. }
  4468. .tooltip-content {
  4469. width: 100%;
  4470. }
  4471. .new-folder {
  4472. display: flex;
  4473. justify-content: space-between;
  4474. align-items: center;
  4475. padding: 8px 5px;
  4476. margin-bottom: 5px;
  4477. border-bottom: 1px solid rgba(255, 255, 255, 0.3);
  4478. cursor: pointer;
  4479. }
  4480. .add-icon {
  4481. font-size: 18px;
  4482. }
  4483. .add-input-container {
  4484. display: flex;
  4485. align-items: center;
  4486. gap: 8px;
  4487. padding: 8px 5px;
  4488. margin-bottom: 8px;
  4489. background: white;
  4490. }
  4491. .folder-input {
  4492. flex: 1;
  4493. background-color: rgba(255, 255, 255, 1);
  4494. border: none;
  4495. border-radius: 4px;
  4496. }
  4497. .input-buttons {
  4498. display: flex;
  4499. gap: 8px;
  4500. }
  4501. .confirm-icon {
  4502. color: #4CAF50;
  4503. font-size: 18px;
  4504. }
  4505. .cancel-icon {
  4506. color: #f44336;
  4507. font-size: 18px;
  4508. }
  4509. .folder-list-container {
  4510. max-height: 200px; /* 最大高度 */
  4511. overflow-y: auto; /* 超出滚动 */
  4512. overflow-x: hidden;
  4513. }
  4514. .folder-item {
  4515. display: flex;
  4516. justify-content: space-between;
  4517. align-items: center;
  4518. padding: 8px 5px;
  4519. white-space: nowrap;
  4520. text-overflow: ellipsis;
  4521. overflow: hidden;
  4522. }
  4523. .folder-name {
  4524. margin-right: 15px; /* 名称与删除图标间距 */
  4525. flex: 1;
  4526. overflow: hidden;
  4527. text-overflow: ellipsis;
  4528. }
  4529. .delete-icon {
  4530. font-size: 18px;
  4531. flex-shrink: 0; /* 防止图标被压缩 */
  4532. }
  4533. /* 滚动条样式优化 */
  4534. .folder-list-container::-webkit-scrollbar {
  4535. width: 6px;
  4536. }
  4537. .folder-list-container::-webkit-scrollbar-thumb {
  4538. background-color: rgba(255, 255, 255, 0.3);
  4539. border-radius: 3px;
  4540. }
  4541. </style>
  4542. <style scoped>
  4543. .collect-modal {
  4544. position: fixed;
  4545. width: 20rem;
  4546. background: #fff;
  4547. border-radius: 4px;
  4548. box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  4549. z-index: 1000;
  4550. transform: translateY(0) translateX(0);
  4551. }
  4552. .collect-modal-header {
  4553. padding: 15px 20px;
  4554. border-bottom: 1px solid #e5e5e5;
  4555. display: flex;
  4556. justify-content: space-between;
  4557. align-items: center;
  4558. }
  4559. .collect-modal-header h3 {
  4560. margin: 0;
  4561. font-size: 16px;
  4562. font-weight: 500;
  4563. }
  4564. .close-btn {
  4565. background: transparent;
  4566. border: none;
  4567. font-size: 18px;
  4568. cursor: pointer;
  4569. color: #909399;
  4570. }
  4571. .collect-modal-body {
  4572. padding: 20px;
  4573. }
  4574. .collect-modal-footer {
  4575. padding: 10px 20px 15px;
  4576. border-top: 1px solid #e5e5e5;
  4577. display: flex;
  4578. justify-content: center;
  4579. gap: 10px;
  4580. }
  4581. </style>