wbs.vue 159 KB

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