wbs.vue 159 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924
  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="施工">施工</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. }
  1856. ElTreeMenu.value = newArr
  1857. }
  1858. //树相关变量
  1859. const primaryKeyId = ref('')
  1860. const nodeItemInfo = ref({})
  1861. const nodeDataInfo = ref({})
  1862. const searchTreeData = ref([])
  1863. //回车
  1864. const searchTreeKeyUp = (e) => {
  1865. if (e.key === 'Enter') {
  1866. searchTreeClick()
  1867. }
  1868. }
  1869. const treeLoading = ref(true)
  1870. const searchTreeClick = async () => {
  1871. if (searchTreeVal.value) {
  1872. searchTreeHeight.value
  1873. = document.getElementById('hc-tree-scrollbar').offsetHeight
  1874. isSearchTree.value = true
  1875. //treeLoading.value = true
  1876. if ( isLookHistory.value) {
  1877. getSearchTreeData('history')
  1878. } else if (folderId.value) {
  1879. getSearchTreeData('folder')
  1880. } else if (!isLookHide.value) {
  1881. getSearchTreeData('hide')
  1882. } else {
  1883. getSearchTreeData()
  1884. }
  1885. } else {
  1886. if (!isLookHide.value) {
  1887. console.log(77777)
  1888. getSearchTreeData('hide')
  1889. return
  1890. }
  1891. if (isLookHistory.value) {
  1892. console.log(77777)
  1893. getSearchTreeData('history')
  1894. return
  1895. }
  1896. isSearchTree.value = false
  1897. }
  1898. }
  1899. //懒加载的数据
  1900. const treeLoadNode = async ({ node, item, level }, resolve) => {
  1901. let contractIdRelation = '',
  1902. parentId = '',
  1903. primaryKeyId = ''
  1904. if (level !== 0) {
  1905. const nodeData = getObjValue(item)
  1906. contractIdRelation = nodeData?.contractIdRelation || ''
  1907. parentId = contractIdRelation ? nodeData?.primaryKeyId : nodeData?.id
  1908. primaryKeyId = nodeData?.id || ''
  1909. }
  1910. // 获取数据
  1911. let data = []
  1912. if (folderId.value) {
  1913. // 如果folderId.value存在,调用collectApi.getCollectTreeNode
  1914. let pKeyId = 0
  1915. if (level !== 0) {
  1916. const nodeData = getObjValue(item)
  1917. pKeyId = nodeData?.primaryKeyId || ''
  1918. }
  1919. const res = await collectApi.getCollectTreeNode({
  1920. pKeyId,
  1921. folderId: folderId.value,
  1922. contractId: contractId.value || '',
  1923. tableOwner: authBtnTabKey.value,
  1924. queryValue: searchTreeVal.value,
  1925. })
  1926. data = res.data || [] // 假设返回的数据结构中包含data字段
  1927. } else {
  1928. // 否则,继续使用原来的queryApi.queryWbsTreeData
  1929. const { data: resData } = await queryApi.queryWbsTreeData({
  1930. contractId: contractId.value || '',
  1931. contractIdRelation,
  1932. primaryKeyId,
  1933. parentId,
  1934. classifyType: classType.value,
  1935. tableOwner: authBtnTabKey.value,
  1936. dataTime: new Date(),
  1937. })
  1938. data = resData || []
  1939. }
  1940. treeLoading.value = false
  1941. resolve(getArrValue(data))
  1942. }
  1943. //树被点击
  1944. const wbsElTreeClick = ({ node, data, keys }) => {
  1945. nodeItemInfo.value = node
  1946. nodeDataInfo.value = data
  1947. primaryKeyId.value = data?.primaryKeyId || ''
  1948. const { notExsitChild } = data
  1949. const { hasChildren } = data
  1950. if (notExsitChild || !hasChildren) {
  1951. isCanadd.value = false
  1952. getTableDataAll()
  1953. } else {
  1954. isCanadd.value = true
  1955. ListItemDatas.value = []
  1956. NodeStatus.value = '1'
  1957. }
  1958. setStoreValue('wbsTreeExpandKeys', keys)
  1959. TreeAutoExpandKeys.value = keys || []
  1960. saveHistory(keys.join(','))
  1961. // getTableDataAll()
  1962. }
  1963. //树加载完成
  1964. const ElTreeNodeLoading = () => {
  1965. treeLoading.value = false
  1966. }
  1967. //保存用户填报历史
  1968. const saveHistory = async (endNode) => {
  1969. await wbsApi.saveUserHistory({
  1970. contractId: contractId.value,
  1971. projectId: projectId.value,
  1972. endNode,
  1973. })
  1974. }
  1975. //回到上次填报历史
  1976. const gobackHistory = async () => {
  1977. isSearchTree.value = false
  1978. const { error, code, data, msg } = await wbsApi.getUserHistory({
  1979. contractId: contractId.value,
  1980. projectId: projectId.value,
  1981. })
  1982. if (!error && code === 200) {
  1983. TreeAutoExpandKeys.value = data['endNode'].split(',') || []
  1984. //重新加载左边树
  1985. isShowLeft.value = false
  1986. setTimeout(() => {
  1987. isShowLeft.value = true
  1988. }, 500)
  1989. } else {
  1990. window.$message.warning(msg)
  1991. }
  1992. }
  1993. //树菜单被点击
  1994. const ElTreeMenuClick = async ({ key, node, data, keys }) => {
  1995. nodeItemInfo.value = node
  1996. nodeDataInfo.value = data
  1997. setStoreValue('wbsTreeExpandKeys', keys)
  1998. TreeAutoExpandKeys.value = keys || []
  1999. setTreeMenuDataClick({ key, node, data })
  2000. }
  2001. //导图结构数据
  2002. const NodeTreeRef = ref(null)
  2003. //鼠标左键单击事件
  2004. const NodeTreeClick = ({ keys }) => {
  2005. setStoreValue('wbsTreeExpandKeys', keys)
  2006. TreeAutoExpandKeys.value = keys || []
  2007. }
  2008. //双击事件
  2009. const isDrawer = ref(false)
  2010. const NodeTreeDblClick = ({ node, data }) => {
  2011. nodeItemInfo.value = node
  2012. nodeDataInfo.value = data
  2013. primaryKeyId.value = data?.primaryKeyId || ''
  2014. isDrawer.value = true
  2015. getTableDataAll()
  2016. }
  2017. const drawerClose = () => {
  2018. isDrawer.value = false
  2019. ListItemDatas.value = []
  2020. }
  2021. //导图树菜单被点击
  2022. const NodeTreeMenuClick = async ({ key, node, data }) => {
  2023. nodeItemInfo.value = node
  2024. nodeDataInfo.value = data
  2025. setTreeMenuDataClick({ key, node, data })
  2026. }
  2027. const orString = ref('')
  2028. //处理菜单被点击数据
  2029. const setTreeMenuDataClick = ({ key, node, data }) => {
  2030. const tabKey = wbsTypeTabKey.value
  2031. if (key === 'mark' || key === 'cancel_mark') {
  2032. firstItemBox()
  2033. } else if (key === 'edit') {
  2034. console.log(data, 'data')
  2035. let form = {}
  2036. if (tabKey === 'tree') {
  2037. const parent = deepClone(node?.parent?.data || {})
  2038. form = { ...deepClone(data), parent: parent }
  2039. } else if (tabKey === 'map') {
  2040. const parent = deepClone(node?.parentNodes?.data || {})
  2041. form = { ...deepClone(data), parent: parent }
  2042. }
  2043. formEditNodeModel.value = form
  2044. orString.value = formEditNodeModel.value?.className
  2045. changeStandType(formEditNodeModel.value?.className)
  2046. console.log(
  2047. formEditNodeModel.value?.className,
  2048. 'formEditNodeModel.value?.className',
  2049. )
  2050. editNodeModal.value = true
  2051. //处理路径
  2052. let pathArr = []
  2053. getPathName(node, pathArr)
  2054. form.position = pathArr.join('\\')
  2055. formEditNodeModel.value = form
  2056. } else if (key === 'copy') {
  2057. if (tabKey === 'tree') {
  2058. const parent = deepClone(node?.parent?.data || {})
  2059. formCopyNodeModel.value = { ...deepClone(data), parent: parent }
  2060. } else if (tabKey === 'map') {
  2061. const parent = deepClone(node?.parentNodes?.data || {})
  2062. formCopyNodeModel.value = { ...deepClone(data), parent: parent }
  2063. }
  2064. classifyType.value = authBtnTabKey.value
  2065. copyNodeTabKey.value = '1'
  2066. copyNodeTable.value = []
  2067. copyNodeLoading.value = false
  2068. copyNodeModal.value = true
  2069. classifyList.value = []
  2070. } else if (key === 'add') {
  2071. const { childNodes } = node
  2072. console.log(childNodes, 'childNodes')
  2073. isCustom.value = data?.isCustom
  2074. addTreeNodeId.value = data?.primaryKeyId
  2075. addTreeNodeOldId.value = data?.oldId
  2076. addNodeLoading.value = false
  2077. if (data?.isClassifition === 1) {
  2078. window.$message.warning('该节点下不能创建子节点')
  2079. addNodeModal.value = false
  2080. return
  2081. }
  2082. {
  2083. addNodeModal.value = true
  2084. }
  2085. } else if (key === 'add1') {
  2086. addTreeNodeId.value = data?.primaryKeyId
  2087. addTreeNodeOldId.value = data?.oldId
  2088. addNodeLoading.value = false
  2089. formWaterNodeModel.value = {
  2090. nodeName: '',
  2091. nodeType: null,
  2092. }
  2093. if (data?.isClassifition === 1) {
  2094. window.$message.warning('该节点下不能创建子节点')
  2095. addNodeModalCus.value = false
  2096. return
  2097. }
  2098. {
  2099. addNodeModalCus.value = true
  2100. }
  2101. } else if (key === 'add2') {
  2102. addTreeNodeId.value = data?.primaryKeyId
  2103. addTreeNodeOldId.value = data?.oldId
  2104. addNodeLoading.value = false
  2105. formDataNodeModel.value = {
  2106. nodeName: '',
  2107. nodeType: null,
  2108. isClassifition: 0,
  2109. className: '',
  2110. unitName: '',
  2111. unitNum: 1,
  2112. excellentNum: 1,
  2113. digitizeTime: '',
  2114. }
  2115. if (data?.isClassifition === 1) {
  2116. window.$message.warning('该节点下不能创建子节点')
  2117. addNodeModalData.value = false
  2118. return
  2119. } else {
  2120. addNodeModalData.value = true
  2121. }
  2122. } else if (key === 'upload') {
  2123. const info = nodeDataInfo.value
  2124. HcUploadFileApi({
  2125. url: '/api/blade-resource/oss/endpoint/put-file',
  2126. accept: '.png,.jpg,jpeg',
  2127. accept_tip: '图片(png、jpg、jpeg)',
  2128. size: 80,
  2129. multiple: false,
  2130. echoParams: {
  2131. drawingsId: info['drawingsId'],
  2132. primaryKeyId: info['primaryKeyId'],
  2133. },
  2134. success: ({ echoParams }, { data }) => {
  2135. setUploadDrawingsData(echoParams.sourceKey, data?.link)
  2136. },
  2137. error: () => {
  2138. window.$message.error('上传失败')
  2139. },
  2140. })
  2141. } else if (key === 'del') {
  2142. console.log(data, 'data')
  2143. if (
  2144. data['colorStatus'] === 1
  2145. || data['colorStatus'] === 2
  2146. || data['colorStatus'] === null
  2147. || data['colorStatus'] === -1
  2148. ) {
  2149. delModalClick()
  2150. } else {
  2151. window?.$message?.warning('该节点已存在上报数据,不允许删除')
  2152. }
  2153. } else if (key === 'sort') {
  2154. let nodes = [],
  2155. childNodes = []
  2156. if (tabKey === 'tree') {
  2157. childNodes
  2158. = node?.parent?.childNodes || node?.parent?.children || []
  2159. } else if (tabKey === 'map') {
  2160. childNodes = node?.parentNodes?.childrenNodes || []
  2161. }
  2162. for (let i = 0; i < childNodes.length; i++) {
  2163. const res = childNodes[i]?.data
  2164. nodes.push({
  2165. id: res?.primaryKeyId,
  2166. title: res?.title,
  2167. })
  2168. }
  2169. sortNodeData.value = nodes
  2170. sortNodeModal.value = true
  2171. } else if (key === 'nodetree') {
  2172. divisionClick()
  2173. } else if (key === 'jumpTree') {
  2174. console.log('跨节点移动')
  2175. primaryKeyId.value = data.primaryKeyId
  2176. showMoveClick(node, data)
  2177. }
  2178. }
  2179. //获取节点的路径名字
  2180. const getPathName = (node, pathArr) => {
  2181. if (node.parent?.parent) {
  2182. pathArr.unshift(node.data?.title.replace(/(^\s*)|(\s*$)/g, '')) //去掉头尾空格
  2183. getPathName(node.parent, pathArr)
  2184. } else {
  2185. //根节点结束
  2186. pathArr.unshift(node.data?.title.replace(/(^\s*)|(\s*$)/g, '')) //去掉头尾空格
  2187. return pathArr
  2188. }
  2189. }
  2190. //确认标记为首件
  2191. const firstItemBox = () => {
  2192. const info = nodeDataInfo.value
  2193. window?.$messageBox?.alert(
  2194. `<div class="text-base font-bold">
  2195. <span>请确认将</span>
  2196. <span class="text-main">【${info['title']}】</span>
  2197. <span>${info['isFirst'] ? '取消' : ''}标记为首件</span>
  2198. </div>`,
  2199. '标记首件制',
  2200. {
  2201. showCancelButton: true,
  2202. dangerouslyUseHTMLString: true,
  2203. callback: (action) => {
  2204. if (action === 'confirm') {
  2205. firstItemHttp(info)
  2206. }
  2207. },
  2208. },
  2209. )
  2210. }
  2211. //首件请求
  2212. const firstItemHttp = async (info) => {
  2213. const { error, code, msg } = await wbsApi.wbsTreeFirstSave({
  2214. primaryKeyId: info['primaryKeyId'],
  2215. saveOrDeleted: info['isFirst'] ? 1 : 0,
  2216. })
  2217. //处理数据
  2218. if (!error && code === 200) {
  2219. window?.$message?.success('操作成功')
  2220. // window?.location?.reload() //刷新页面
  2221. if (folderId.value) {
  2222. isShowLeft.value = false
  2223. setTimeout(() => {
  2224. isShowLeft.value = true
  2225. selCollectMneu()
  2226. }, 500)
  2227. getTableDataAll()
  2228. } else {
  2229. window?.location?.reload() //刷新页面
  2230. }
  2231. }
  2232. }
  2233. //编辑节点
  2234. const editNodeModal = ref(false)
  2235. //获取节点类型
  2236. const nodeTypeData = ref([])
  2237. const getDictionaryApi = async () => {
  2238. const { data } = await getDictionary({
  2239. code: 'wbs_node_type',
  2240. })
  2241. //处理数据
  2242. let newArr = []
  2243. const newData = getArrValue(data)
  2244. for (let i = 0; i < newData.length; i++) {
  2245. newArr.push({
  2246. label: newData[i]['dictValue'],
  2247. value: Number(newData[i]['dictKey']),
  2248. })
  2249. }
  2250. nodeTypeData.value = newArr
  2251. }
  2252. const formEditNodeRef = ref(null)
  2253. const formEditNodeModel = ref({
  2254. title: '',
  2255. parent: {
  2256. title: '',
  2257. },
  2258. nodeType: null,
  2259. partitionCode: '',
  2260. position: '',
  2261. notExsitChild: '',
  2262. })
  2263. const formEditNodeRules = {
  2264. title: {
  2265. required: true,
  2266. trigger: 'blur',
  2267. message: '请输入节点名称',
  2268. },
  2269. }
  2270. const editNodeLoading = ref(false)
  2271. //保存编辑节点数据
  2272. const editNodeClick = async () => {
  2273. const validate = await formValidate(formEditNodeRef.value)
  2274. if (validate) {
  2275. //发起请求
  2276. editNodeLoading.value = true
  2277. const {
  2278. primaryKeyId,
  2279. title,
  2280. partitionCode,
  2281. className,
  2282. unitName,
  2283. excellentNum,
  2284. unitNum,
  2285. digitizeTime,
  2286. majorDataType,
  2287. nodeType,
  2288. privateTemplate,
  2289. } = formEditNodeModel.value
  2290. const { error, code, msg } = await wbsApi.wbsTreeUpdateNode({
  2291. nodeName: title || '',
  2292. pKeyId: primaryKeyId || '',
  2293. partitionCode: partitionCode || '',
  2294. className,
  2295. unitName,
  2296. unitNum,
  2297. excellentNum,
  2298. digitizeTime,
  2299. majorDataType,
  2300. nodeType,
  2301. privateTemplate,
  2302. })
  2303. //处理数据
  2304. editNodeLoading.value = false
  2305. if (!error && code === 200) {
  2306. window?.$message?.success('修改成功')
  2307. nodeDataInfo.value['title'] = title || ''
  2308. nodeDataInfo.value['partitionCode'] = partitionCode || ''
  2309. editNodeModal.value = false
  2310. // window?.location?.reload() //刷新页面
  2311. if (folderId.value) {
  2312. isShowLeft.value = false
  2313. setTimeout(() => {
  2314. isShowLeft.value = true
  2315. selCollectMneu()
  2316. }, 500)
  2317. getTableDataAll()
  2318. } else {
  2319. window?.location?.reload() //刷新页面
  2320. }
  2321. }
  2322. }
  2323. }
  2324. //复制节点
  2325. const copyNodeModal = ref(false)
  2326. //复制节点类型tab数据和相关处理
  2327. const copyNodeTabKey = ref('')
  2328. const copyNodeTab = ref([
  2329. { key: '1', name: '单份复制' },
  2330. { key: '2', name: '多份复制' },
  2331. //{key: '3', name: '复制数据'}
  2332. ])
  2333. const copyNodeTabChange = (key) => {
  2334. if (key !== copyNodeTabKey.value) {
  2335. copyNodeTabKey.value = key
  2336. copyNodeTable.value = []
  2337. copyNodeLoading.value = false
  2338. }
  2339. }
  2340. //复制节点变量
  2341. const copyNodeLoading = ref(false)
  2342. const formCopyNodeModel = ref({})
  2343. const classifyList = ref([])
  2344. const copyNodeTable = ref([])
  2345. const isCopyData = ref(0)
  2346. //复制树被点击
  2347. const copyNodeElTreeClick = ({ data, node }) => {
  2348. const TabKey = copyNodeTabKey.value
  2349. const { title, type, partitionCode } = formCopyNodeModel.value
  2350. console.log(formCopyNodeModel.value, 'formCopyNodeModel.value')
  2351. console.log(data, '点击data')
  2352. if (TabKey === '2') {
  2353. // setCopyNodeTable(data, title, partitionCode)
  2354. //1 单位工程,2 分部工程,3 子分部工程,4 分项工程, 5 子分项工程,6 工序
  2355. // //不能复制到本身节点下
  2356. // //只能往上一级点击,不能跨层级点击
  2357. // //已上报的工序节点不能点击选择
  2358. // //如果选择的是父级节点,那不能复制到子级节点
  2359. const { hasChildren } = data
  2360. if (hasChildren === 0) {
  2361. if (
  2362. data['colorStatus'] === 2
  2363. || data['colorStatus'] == 1
  2364. || data['colorStatus'] === null
  2365. || data['colorStatus'] === -1
  2366. ) {
  2367. //已上报的工序不能点击
  2368. if (data['id'] !== formCopyNodeModel.value.id) {
  2369. //不能复制到本身节点下
  2370. //只能往上一级点击,不能跨层级点击
  2371. //如果选择的是父级节点,那不能复制到子级节点
  2372. if (
  2373. type === 6
  2374. && (data['type'] === 4
  2375. || data['type'] === 5
  2376. || data['type'] == 6)
  2377. ) {
  2378. setCopyNodeTable(data, title)
  2379. }
  2380. if (type === 5 && data['type'] === 4) {
  2381. setCopyNodeTable(data, title, partitionCode)
  2382. }
  2383. if (
  2384. type === 4
  2385. && (data['type'] === 2 || data['type'] === 3)
  2386. ) {
  2387. setCopyNodeTable(data, title, partitionCode)
  2388. }
  2389. if (type === 3 && data['type'] === 2) {
  2390. setCopyNodeTable(data, title, partitionCode)
  2391. }
  2392. if (type === 2 && data['type'] === 1) {
  2393. setCopyNodeTable(data, title, partitionCode)
  2394. }
  2395. if (type === 1 && data['type'] === 1) {
  2396. setCopyNodeTable(data, title, partitionCode)
  2397. }
  2398. }
  2399. } else {
  2400. window?.$message?.warning('该节点已存在上报数据,不允许复制')
  2401. }
  2402. } else {
  2403. if (data['id'] !== formCopyNodeModel.value.id) {
  2404. //不能复制到本身节点下
  2405. //只能往上一级点击,不能跨层级点击
  2406. //如果选择的是父级节点,那不能复制到子级节点
  2407. if (
  2408. type === 6
  2409. && (data['type'] === 4
  2410. || data['type'] === 5
  2411. || data['type'] == 6)
  2412. ) {
  2413. setCopyNodeTable(data, title)
  2414. }
  2415. if (type === 5 && data['type'] === 4) {
  2416. setCopyNodeTable(data, title, partitionCode)
  2417. }
  2418. if (type === 4 && (data['type'] === 2 || data['type'] === 3)) {
  2419. setCopyNodeTable(data, title, partitionCode)
  2420. }
  2421. if (type === 3 && data['type'] === 2) {
  2422. setCopyNodeTable(data, title, partitionCode)
  2423. }
  2424. if (type === 2 && data['type'] === 1) {
  2425. setCopyNodeTable(data, title, partitionCode)
  2426. }
  2427. if (type === 1 && data['type'] === 1) {
  2428. setCopyNodeTable(data, title, partitionCode)
  2429. }
  2430. }
  2431. }
  2432. } else if (TabKey === '3') {
  2433. console.log(1111111)
  2434. setCopyNodeTable(data, data?.title)
  2435. }
  2436. }
  2437. const setCopyNodeTable = (data, title) => {
  2438. copyNodeTable.value.push({
  2439. title: data?.title || '',
  2440. nodeName: title || '',
  2441. primaryKeyId: data?.primaryKeyId || '',
  2442. parentId: data?.parentId || '',
  2443. id: data?.id || '',
  2444. })
  2445. }
  2446. //节点表单
  2447. const formCopyNodeModelRef = ref(null)
  2448. const formCopyNodeModelRules = {
  2449. title: {
  2450. required: true,
  2451. trigger: 'blur',
  2452. message: '请输入节点名称',
  2453. },
  2454. }
  2455. //表格节点表单
  2456. const copyNodeTableRef = ref(null)
  2457. const copyNodeTableRules = {
  2458. nodeName: {
  2459. required: true,
  2460. trigger: 'blur',
  2461. message: '请输入节点名称',
  2462. },
  2463. }
  2464. //删除选中的节点
  2465. const copyNodeTableDel = (index) => {
  2466. copyNodeTable.value.splice(index, 1)
  2467. }
  2468. const classifyType = ref(authBtnTabKey.value)
  2469. //复制节点
  2470. const copyNodeClick = async () => {
  2471. const type = copyNodeTabKey.value
  2472. const form = formCopyNodeModel.value
  2473. const table = copyNodeTable.value
  2474. let classify = ''
  2475. let arr = []
  2476. if (classifyList.value.length > 0) {
  2477. classifyList.value.forEach((item) => {
  2478. if (item === '施工') {
  2479. arr.push(1)
  2480. } else if (item === '监理') {
  2481. arr.push(2)
  2482. }
  2483. })
  2484. classify = arr.join(',')
  2485. }
  2486. //isSameNode 是否同节点 1=同节点,0=跨节点
  2487. if (table.length > 0) {
  2488. table.forEach((ele) => {
  2489. if (
  2490. ele.parentId === formCopyNodeModel.value.parentId
  2491. || ele.id === formCopyNodeModel.value.parentId
  2492. ) {
  2493. ele.isSameNode = 1
  2494. } else {
  2495. ele.isSameNode = 0
  2496. }
  2497. })
  2498. }
  2499. if (isCopyData.value === 1) {
  2500. if (classify) {
  2501. //效验数据
  2502. if (type === '1') {
  2503. const validate = await formValidate(formCopyNodeModelRef.value)
  2504. if (validate)
  2505. await copyContractTreeNode(type, form, [], classify)
  2506. } else if (type === '2') {
  2507. if (table.length > 0) {
  2508. const validate = await formValidate(copyNodeTableRef.value)
  2509. if (validate)
  2510. await copyContractTreeNode(type, form, table, classify)
  2511. } else {
  2512. window?.$message?.warning('请先在左侧选择要复制到的节点')
  2513. }
  2514. }
  2515. } else {
  2516. window?.$message?.warning('请选择所属方')
  2517. }
  2518. } else {
  2519. if (type === '1') {
  2520. const validate = await formValidate(formCopyNodeModelRef.value)
  2521. if (validate) await copyContractTreeNode(type, form, [], classify)
  2522. } else if (type === '2') {
  2523. if (table.length > 0) {
  2524. const validate = await formValidate(copyNodeTableRef.value)
  2525. if (validate)
  2526. await copyContractTreeNode(type, form, table, classify)
  2527. } else {
  2528. window?.$message?.warning('请先在左侧选择要复制到的节点')
  2529. }
  2530. }
  2531. }
  2532. }
  2533. //单个复制、多份复制请求
  2534. const copyContractTreeNode = async (type, form, table, classify) => {
  2535. copyNodeLoading.value = true
  2536. if (type === '1') {
  2537. const { error, code, msg } = await wbsApi.copyContractTreeNode({
  2538. copyType: type,
  2539. needCopyNodeName: form?.title || '',
  2540. partitionCode: form?.partitionCode || '',
  2541. needCopyPrimaryKeyId: form?.primaryKeyId || '',
  2542. parentPrimaryKeyId: form?.parent?.primaryKeyId || '',
  2543. copyBatchToPaths: table,
  2544. classifyType: classify,
  2545. isCopyData: isCopyData.value,
  2546. })
  2547. //判断状态
  2548. copyNodeLoading.value = false
  2549. if (!error && code === 200) {
  2550. window?.$message?.success('复制成功')
  2551. copyNodeModal.value = false
  2552. window?.location?.reload() //刷新页面
  2553. }
  2554. } else {
  2555. const { error, code, msg } = await wbsApi.copyContractTreeNode({
  2556. copyType: type,
  2557. needCopyNodeName: form?.title || '',
  2558. needCopyPrimaryKeyId: form?.primaryKeyId || '',
  2559. parentPrimaryKeyId: form?.parent?.primaryKeyId || '',
  2560. copyBatchToPaths: table,
  2561. classifyType: classify,
  2562. isCopyData: isCopyData.value,
  2563. })
  2564. //判断状态
  2565. copyNodeLoading.value = false
  2566. if (!error && code === 200) {
  2567. window?.$message?.success('复制成功')
  2568. copyNodeModal.value = false
  2569. window?.location?.reload() //刷新页面
  2570. }
  2571. }
  2572. }
  2573. //新增节点
  2574. const addNodeModal = ref(false)
  2575. const addTreeNodeId = ref('')
  2576. const addTreeNodeOldId = ref('')
  2577. //const addTreeNodeType = ref('1')
  2578. const addTreeNodeType = ref('1')
  2579. const isCustom = ref(null)
  2580. //新增自定义节点
  2581. const addNodeModalCus = ref(false)
  2582. const addNodeLoadingCus = ref(false)
  2583. //水利工程
  2584. const formWaterNodeRef = ref(null)
  2585. const formWaterNodeModel = ref({
  2586. nodeName: '',
  2587. nodeType: null,
  2588. })
  2589. const formWaterNodeRules = {
  2590. nodeName: {
  2591. required: true,
  2592. trigger: 'blur',
  2593. message: '请输入节点名称',
  2594. },
  2595. nodeType: {
  2596. required: true,
  2597. trigger: 'blur',
  2598. message: '请选择节点类型',
  2599. },
  2600. }
  2601. //新增自定义节点-数字化文件
  2602. const addNodeModalData = ref(false)
  2603. const addNodeLoadingData = ref(false)
  2604. const formDataNodeRef = ref(null)
  2605. const formDataNodeModel = ref({
  2606. nodeName: '',
  2607. nodeType: null,
  2608. isClassifition: 0,
  2609. className: '',
  2610. unitName: '',
  2611. unitNum: 1,
  2612. excellentNum: 1,
  2613. majorDataType: '',
  2614. digitizeTime: '',
  2615. })
  2616. const majorDataTypeOptions = ref([])
  2617. const getMajorDataTypeOptions = async () => {
  2618. majorDataTypeOptions.value = await getDictionaryData('major_data_type', false)
  2619. }
  2620. const standardTypeOptions = ref([])
  2621. const getStandardTypeOptions = async () => {
  2622. const { data } = await getDictionary({
  2623. code: 'classification',
  2624. })
  2625. standardTypeOptions.value = await getDictionaryData(
  2626. 'classification',
  2627. false,
  2628. )
  2629. standardTypeOptions.value.forEach((element) => {
  2630. // element.parentId=
  2631. data.forEach((ele) => {
  2632. if (ele.dictKey == element.value) {
  2633. element.id = ele.id
  2634. }
  2635. })
  2636. })
  2637. // 定义要过滤的 dictKey 值
  2638. const targetKeys = [1, 2, 3, 4, 5]
  2639. // 过滤数组
  2640. standardTypeOptions.value = standardTypeOptions.value.filter((item) =>
  2641. targetKeys.includes(item.value),
  2642. )
  2643. }
  2644. const unitNameOptions = ref([])
  2645. const changeStandType = async (val) => {
  2646. if (val !== orString.value) {
  2647. formEditNodeModel.value.unitName = ''
  2648. }
  2649. formDataNodeModel.value.unitName = ''
  2650. let parentId = ''
  2651. standardTypeOptions.value.forEach((item) => {
  2652. if (item.value == val) {
  2653. parentId = item.id
  2654. }
  2655. })
  2656. const { data } = await getChildList({ current: 1, size: 10000, parentId })
  2657. unitNameOptions.value = data
  2658. unitNameOptions.value = unitNameOptions.value.filter(
  2659. (item) => item.dictKey != -1,
  2660. )
  2661. unitNameOptions.value.forEach((ele) => {
  2662. ele.dictKey = Number(ele.dictKey)
  2663. })
  2664. }
  2665. const formDataNodeRules = {
  2666. nodeName: {
  2667. required: true,
  2668. trigger: 'blur',
  2669. message: '请输入节点名称',
  2670. },
  2671. nodeType: {
  2672. required: true,
  2673. trigger: 'blur',
  2674. message: '请选择节点类型',
  2675. },
  2676. isClassifition: {
  2677. required: true,
  2678. trigger: 'blur',
  2679. message: '请选择是否含单元评定',
  2680. },
  2681. className: {
  2682. required: true,
  2683. trigger: 'blur',
  2684. message: '请选择标准分类',
  2685. },
  2686. unitName: {
  2687. required: true,
  2688. trigger: 'blur',
  2689. message: '请选择单位名称',
  2690. },
  2691. excellentNum: {
  2692. required: true,
  2693. trigger: 'blur',
  2694. message: '请输入优良个数',
  2695. },
  2696. unitNum: {
  2697. required: true,
  2698. trigger: 'blur',
  2699. message: '请输入单元个数',
  2700. },
  2701. digitizeTime: {
  2702. required: true,
  2703. trigger: 'blur',
  2704. message: '请选择时间',
  2705. },
  2706. majorDataType:{
  2707. required: true,
  2708. trigger: 'blur',
  2709. message: '请选择内业资料类型',
  2710. },
  2711. }
  2712. const addNodeClickData = async () => {
  2713. const validate = await formValidate(formDataNodeRef.value)
  2714. if (!validate) return
  2715. //发起请求
  2716. addNodeClickData.value = true
  2717. const { error, code, msg } = await wbsApi.saveCustomAddContractNode({
  2718. nodeName: formDataNodeModel.value.nodeName,
  2719. nodeType: formDataNodeModel.value?.nodeType || '',
  2720. partitionCode: nodeDataInfo.value?.partitionCode || '',
  2721. primaryKeyId: nodeDataInfo.value?.primaryKeyId || '',
  2722. nodeClass: 2, //数字化文件
  2723. isClassifition: formDataNodeModel.value?.isClassifition || 0,
  2724. className: formDataNodeModel.value?.className || '',
  2725. unitName: Number(formDataNodeModel.value?.unitName) || '',
  2726. excellentNum: formDataNodeModel.value?.excellentNum || 0,
  2727. digitizeTime: formDataNodeModel.value?.digitizeTime || '',
  2728. unitNum: formDataNodeModel.value?.unitNum || 0,
  2729. majorDataType: formDataNodeModel.value?.majorDataType || '',
  2730. templateType:useAppState.contractInfo?.templateType,
  2731. })
  2732. //判断状态
  2733. addNodeClickData.value = false
  2734. if (!error && code === 200) {
  2735. window?.$message?.success('新增成功')
  2736. addNodeModalData.value = false
  2737. window?.location?.reload() //刷新页面
  2738. }
  2739. }
  2740. //选中的节点
  2741. const allSelectedList = ref([])
  2742. const halfSelectedList = ref([])
  2743. const addTreeNodeCheckChange = (nodes) => {
  2744. let NodesArr = [],
  2745. halfArr = []
  2746. //全选数据
  2747. const keys = nodes.checkedNodes || []
  2748. for (let i = 0; i < keys.length; i++) {
  2749. NodesArr.push({
  2750. nodeName: keys[i].nodeName,
  2751. primaryKeyId: keys[i].pKeyId,
  2752. isPeer: keys[i].isPeer || 2,
  2753. })
  2754. }
  2755. allSelectedList.value = NodesArr
  2756. //半选数据
  2757. const halfNodes = nodes.halfCheckedNodes || []
  2758. for (let i = 0; i < halfNodes.length; i++) {
  2759. halfArr.push({
  2760. nodeName: halfNodes[i].nodeName,
  2761. primaryKeyId: halfNodes[i].pKeyId,
  2762. isPeer: halfNodes[i].isPeer || 2,
  2763. })
  2764. }
  2765. halfSelectedList.value = halfArr
  2766. }
  2767. //新增节点
  2768. const addNodeLoading = ref(false)
  2769. const addNodeClick = async () => {
  2770. const keys = allSelectedList.value || []
  2771. if (keys.length <= 0) {
  2772. window?.$message?.warning('请先选择节点')
  2773. } else {
  2774. //发起请求
  2775. addNodeLoading.value = true
  2776. const primaryKeyId = nodeDataInfo.value?.primaryKeyId || ''
  2777. const { error, code } = await wbsApi.saveContractTreeNode({
  2778. projectId: projectId.value,
  2779. contractId: contractId.value,
  2780. saveType: addTreeNodeType.value,
  2781. allSelectedList: allSelectedList.value,
  2782. halfSelectedList: halfSelectedList.value,
  2783. currentNodePrimaryKeyId: primaryKeyId,
  2784. templateType:useAppState.contractInfo?.templateType,
  2785. })
  2786. //判断状态
  2787. addNodeLoading.value = false
  2788. if (!error && code === 200) {
  2789. window?.$message?.success('新增成功')
  2790. addNodeModal.value = false
  2791. window?.location?.reload() //刷新页面
  2792. }
  2793. }
  2794. }
  2795. const addNodeClickCur = async () => {
  2796. const validate = await formValidate(formWaterNodeRef.value)
  2797. if (!validate) return
  2798. //发起请求
  2799. addNodeLoadingCus.value = true
  2800. const { error, code, msg } = await wbsApi.saveCustomAddContractNode({
  2801. nodeName: formWaterNodeModel.value.nodeName,
  2802. nodeType: formWaterNodeModel.value?.nodeType || '',
  2803. newPartitionCode:formWaterNodeModel.value?.number || '',
  2804. partitionCode: nodeDataInfo.value?.partitionCode || '',
  2805. primaryKeyId: nodeDataInfo.value?.primaryKeyId || '',
  2806. nodeClass: 1, //1水利化工程,2数字化文件
  2807. templateType:useAppState.contractInfo?.templateType,
  2808. })
  2809. //判断状态
  2810. addNodeLoadingCus.value = false
  2811. if (!error && code === 200) {
  2812. window?.$message?.success('新增成功')
  2813. addNodeModalCus.value = false
  2814. window?.location?.reload() //刷新页面
  2815. } else {
  2816. window?.$message?.error(msg || '操作失败')
  2817. }
  2818. }
  2819. //删除节点
  2820. const delModalClick = async () => {
  2821. const { code, msg } = await wbsApi.removeContractTreeNodeJudge({
  2822. ids: nodeDataInfo.value?.primaryKeyId || '',
  2823. })
  2824. if (code === 200) {
  2825. HcDelMsg(async (resolve) => {
  2826. await removeContractTreeNode()
  2827. resolve() //关闭弹窗的回调
  2828. })
  2829. } else {
  2830. NewDelMsg({ text: msg }, async (resolve) => {
  2831. await removeContractTreeNode()
  2832. resolve() //关闭弹窗的回调
  2833. })
  2834. }
  2835. }
  2836. const removeContractTreeNode = async () => {
  2837. const loadingInstance = window.$loading.service({
  2838. fullscreen: true,
  2839. text: '删除节点中,请耐心等待...',
  2840. background: 'rgba(0, 0, 0, 0.7)',
  2841. })
  2842. const { error, code, msg } = await wbsApi.removeContractTreeNode({
  2843. ids: nodeDataInfo.value?.primaryKeyId || '',
  2844. })
  2845. //处理结果
  2846. loadingInstance.close()
  2847. if (!error && code === 200) {
  2848. window?.$message?.success('删除成功')
  2849. // window?.location?.reload() //刷新页面
  2850. if (folderId.value) {
  2851. isShowLeft.value = false
  2852. setTimeout(() => {
  2853. isShowLeft.value = true
  2854. selCollectMneu()
  2855. }, 500)
  2856. getTableDataAll()
  2857. } else {
  2858. window?.location?.reload() //刷新页面
  2859. }
  2860. } else {
  2861. window.$message.error(msg)
  2862. }
  2863. }
  2864. //调整排序
  2865. const sortNodeModal = ref(false)
  2866. const sortNodeLoading = ref(false)
  2867. const sortNodeData = ref([])
  2868. const sortNodeDrag = ref(false)
  2869. //向下
  2870. const downSortClick = (index) => {
  2871. const indexs = index + 1
  2872. const data = sortNodeData.value || []
  2873. if (indexs !== data.length) {
  2874. const tmp = data.splice(indexs, 1)
  2875. sortNodeData.value.splice(index, 0, tmp[0])
  2876. } else {
  2877. window?.$message?.warning('已经处于置底,无法下移')
  2878. }
  2879. }
  2880. //向上
  2881. const upSortClick = (index) => {
  2882. const data = sortNodeData.value || []
  2883. if (index !== 0) {
  2884. const tmp = data.splice(index - 1, 1)
  2885. sortNodeData.value.splice(index, 0, tmp[0])
  2886. } else {
  2887. window?.$message?.warning('已经处于置顶,无法上移')
  2888. }
  2889. }
  2890. //确认排序
  2891. const sortNodeClick = async () => {
  2892. const sortList = []
  2893. const nodes = sortNodeData.value || []
  2894. nodes.forEach((item) => {
  2895. sortList.push(item?.id)
  2896. })
  2897. //发起请求
  2898. sortNodeLoading.value = true
  2899. const { error, code, msg } = await wbsApi.diySortTreeNode({ sortList })
  2900. sortNodeLoading.value = false
  2901. //判断状态
  2902. if (!error && code === 200) {
  2903. window?.$message?.success('保存成功')
  2904. sortNodeModal.value = false
  2905. window?.location?.reload() //刷新页面
  2906. } else {
  2907. window.$message.error(msg)
  2908. }
  2909. }
  2910. //查看图纸
  2911. const drawList = ref('')
  2912. const drawingsShow = ref(false)
  2913. const viewsDrawings = () => {
  2914. const { primaryKeyId, drawingsId } = nodeDataInfo.value
  2915. if (!primaryKeyId) {
  2916. window?.$message?.warning('请先选择树节点')
  2917. } else if (drawingsId === -1 || drawingsId === null) {
  2918. window?.$message?.warning('该节点暂未上传图纸')
  2919. } else {
  2920. drawingsShow.value = true
  2921. getDrawList(drawingsId)
  2922. }
  2923. }
  2924. const drawingsClose = (res) => {
  2925. drawingsShow.value = res
  2926. }
  2927. const getDrawList = async (primaryKeyId) => {
  2928. const { error, code, data } = await wbsApi.getTreeDrawings({
  2929. primaryKeyId,
  2930. })
  2931. //判断状态
  2932. if (!error && code === 200) {
  2933. drawList.value = data
  2934. } else {
  2935. drawList.value = data
  2936. }
  2937. }
  2938. //设置滚动条位置
  2939. const ListItemScrollRef = ref(null)
  2940. const ListItemOffsetTop = (offsetTop) => {
  2941. if (offsetTop > 0) {
  2942. setTimeout(() => {
  2943. ListItemScrollRef.value?.setScrollTop(offsetTop)
  2944. }, 350)
  2945. } else {
  2946. ListItemScrollRef.value?.setScrollTop(offsetTop)
  2947. }
  2948. }
  2949. //获取数据列表
  2950. const ListItemDatas = ref([])
  2951. const ListItemLoading = ref(false)
  2952. const searchNodeAllTable = async () => {
  2953. ListItemLoading.value = true
  2954. ListItemDatas.value = []
  2955. const info = nodeDataInfo.value
  2956. const { data } = await wbsApi.searchNodeAllTable({
  2957. projectId: projectId.value,
  2958. contractId: contractId.value,
  2959. primaryKeyId: info['primaryKeyId'],
  2960. type: authBtnTabKey.value,
  2961. })
  2962. ListItemDatas.value = getArrValue(data)
  2963. ListItemLoading.value = false
  2964. }
  2965. //获取文件题名
  2966. const getFileName = async () => {
  2967. if (!nodeDataInfo.value?.primaryKeyId) {
  2968. titleInput.value = ''
  2969. return
  2970. }
  2971. const info = nodeDataInfo.value
  2972. const { error, code, data } = await wbsApi.getDICengNodeName({
  2973. pKeyId: info['primaryKeyId'],
  2974. classify: authBtnTabKey.value,
  2975. contractId: contractId.value,
  2976. })
  2977. //判断状态
  2978. if (!error && code === 200) {
  2979. titleInput.value = data
  2980. } else {
  2981. titleInput.value = data
  2982. }
  2983. }
  2984. const newlistdata = ref([])
  2985. const searchNodeAllTable1 = async () => {
  2986. console.log('重新获取表单列表')
  2987. const info = nodeDataInfo.value
  2988. const { data } = await wbsApi.searchNodeAllTable({
  2989. projectId: projectId.value,
  2990. contractId: contractId.value,
  2991. primaryKeyId: info['primaryKeyId'],
  2992. type: authBtnTabKey.value,
  2993. })
  2994. newlistdata.value = getArrValue(data)
  2995. }
  2996. //查询状态
  2997. const NodeStatus = ref('1')
  2998. const queryNodeStatus = async () => {
  2999. const info = nodeDataInfo.value
  3000. if (!info['primaryKeyId']) {
  3001. return
  3002. }
  3003. if (contractInfo.value?.contractType == 1) {
  3004. const { error, code, data } = await wbsApi.queryNodeStatus({
  3005. primaryKeyId: info['primaryKeyId'],
  3006. //classify:1
  3007. classify: authBtnTabKey.value,
  3008. })
  3009. //1 未填报,2待上报,3已上报
  3010. if (!error && code === 200) {
  3011. NodeStatus.value = data ?? '1'
  3012. } else {
  3013. NodeStatus.value = '1'
  3014. }
  3015. } else {
  3016. const { error, code, data } = await wbsApi.queryNodeStatusJl({
  3017. // primaryKeyId: info['contractIdRelation'] ? info['id'] : info['primaryKeyId'],
  3018. primaryKeyId: info['primaryKeyId'],
  3019. //classify: 1
  3020. classify: authBtnTabKey.value,
  3021. })
  3022. //1 未填报,2待上报,3已上报
  3023. if (!error && code === 200) {
  3024. NodeStatus.value = data ?? '1'
  3025. } else {
  3026. NodeStatus.value = '1'
  3027. }
  3028. }
  3029. }
  3030. //批量上报
  3031. const reportIds = ref('')
  3032. const reportTaskName = ref('')
  3033. const reportAddition = ref({})
  3034. const showReportModal = ref(false)
  3035. const reportLoading = ref(false)
  3036. const reportTypeData = ref([])
  3037. const reportModalClick = async () => {
  3038. const info = nodeDataInfo.value
  3039. const rows = ListItemDatas.value
  3040. if (rows.length > 0) {
  3041. reportLoading.value = true
  3042. const taskCheck = await eVisaTaskCheckApi({
  3043. projectId: projectId.value,
  3044. contractId:
  3045. contractInfo.value?.contractType == 2
  3046. ? info?.contractIdRelation
  3047. : contractId.value,
  3048. // contractId: contractId.value
  3049. })
  3050. //处理数据
  3051. let newArr = []
  3052. for (let i = 0; i < rows.length; i++) {
  3053. newArr.push(rows[i]['isTypePrivatePid'])
  3054. }
  3055. reportTypeData.value = newArr
  3056. reportLoading.value = false
  3057. if (taskCheck) {
  3058. //初始弹出弹窗,防呆
  3059. reportIds.value = info['primaryKeyId']
  3060. reportAddition.value = {
  3061. classify: authBtnTabKey.value,
  3062. contractIdRelation: info['contractIdRelation'],
  3063. }
  3064. showReportModal.value = true
  3065. //请求文件题名
  3066. const { data } = await wbsApi.queryDocumentTitle({
  3067. primaryKeyId: info['primaryKeyId'],
  3068. classify: authBtnTabKey.value,
  3069. })
  3070. reportTaskName.value = isString(data) ? data : ''
  3071. }
  3072. } else {
  3073. window.$message?.warning('暂无相关数据')
  3074. }
  3075. }
  3076. //上报完成
  3077. const showReportFinish = () => {
  3078. showReportModal.value = false
  3079. getTableDataAll()
  3080. window?.location?.reload() //刷新页面
  3081. }
  3082. //表单变量
  3083. const ListItemRef = ref(null)
  3084. const ListItemsRef = ref(null)
  3085. //保存
  3086. const tableFormSaveLoading = ref(false)
  3087. const tableFormSaveClick = async () => {
  3088. //获取数据
  3089. let FormData = [],
  3090. FormRegExpJson = {}
  3091. if (isDrawer.value) {
  3092. FormData = await ListItemsRef.value?.getFormData()
  3093. FormRegExpJson = await ListItemsRef.value?.getFormRegExpJson()
  3094. } else {
  3095. FormData = await ListItemRef.value?.getFormData()
  3096. FormRegExpJson = await ListItemRef.value?.getFormRegExpJson()
  3097. }
  3098. //效验数据
  3099. if (getObjVal(FormRegExpJson)) {
  3100. setFormRegExpJson(FormRegExpJson)
  3101. } else if (FormData.length > 0) {
  3102. console.log('保存')
  3103. tableFormSaveLoading.value = true
  3104. console.log('FormData', FormData)
  3105. const { error, code, msg, data } = await wbsApi.saveExcelBussData({
  3106. dataInfo: { orderList: FormData },
  3107. })
  3108. tableFormSaveLoading.value = false
  3109. if (!error && code === 200) {
  3110. window?.$message?.success('保存成功')
  3111. // await bussPdfsClick()
  3112. const activeKey = ListItemRef.value?.getActiveKey()
  3113. getTableDataAll(activeKey)
  3114. } else {
  3115. window?.$message?.error(msg || '操作失败')
  3116. }
  3117. } else {
  3118. console.log('预览')
  3119. // await bussPdfsClick()
  3120. }
  3121. }
  3122. //效验数据
  3123. const setFormRegExpJson = (FormRegExpJson) => {
  3124. let nodeName = '',
  3125. itemId = ''
  3126. Object.keys(FormRegExpJson).forEach((key) => {
  3127. const name = FormRegExpJson[key]?.nodeName ?? ''
  3128. if (name) {
  3129. if (nodeName) {
  3130. nodeName += ',' + name
  3131. } else {
  3132. nodeName = name
  3133. itemId = FormRegExpJson[key]?.itemId
  3134. }
  3135. }
  3136. })
  3137. //const activeKey = ListItemRef.value?.getActiveKey()
  3138. //弹出提示
  3139. const val
  3140. = '<div style="font-size: 16px;">请先完善 <span style="color:#1ECC95;">'
  3141. + nodeName
  3142. + '</span> 的数据内容</div>'
  3143. window?.$messageBox?.alert(val, '表单完善提醒', {
  3144. confirmButtonText: '确定',
  3145. dangerouslyUseHTMLString: true,
  3146. callback: (action) => {
  3147. if (action === 'confirm') {
  3148. ListItemRef.value?.setActiveKey(itemId)
  3149. ListItemOffsetTop(0)
  3150. setTimeout(() => {
  3151. const offsetTop
  3152. = document.getElementById(itemId)?.offsetTop
  3153. ListItemOffsetTop(offsetTop)
  3154. }, 350)
  3155. }
  3156. },
  3157. })
  3158. }
  3159. //多表预览
  3160. const bussPdfsLoading = ref(false)
  3161. const bussPdfsClick = async () => {
  3162. const info = nodeDataInfo.value
  3163. bussPdfsLoading.value = true
  3164. const { error, code, data } = await wbsApi.getBussPdfs({
  3165. nodeId: info?.primaryKeyId || '',
  3166. classify: authBtnTabKey.value,
  3167. projectId: projectId.value,
  3168. // contractId: contractId.value
  3169. contractId:
  3170. contractInfo.value?.contractType == 2
  3171. ? info?.contractIdRelation
  3172. : contractId.value,
  3173. })
  3174. tableFormSaveLoading.value = false
  3175. bussPdfsLoading.value = false
  3176. if (!error && code === 200) {
  3177. toPdfPage(data)
  3178. //window.open(data, '_blank')
  3179. } else {
  3180. window.$message?.warning('获取PDF失败')
  3181. }
  3182. }
  3183. //撤回上报流程
  3184. const abolishLoaing = ref(false)
  3185. const abolishOneClick = () => {
  3186. window?.$messageBox?.alert('请谨慎考虑后,是否确定撤回?', '撤回上报', {
  3187. showCancelButton: true,
  3188. confirmButtonText: '确定撤回',
  3189. cancelButtonText: '取消',
  3190. callback: (action) => {
  3191. if (action === 'confirm') {
  3192. abolishOneSave()
  3193. }
  3194. },
  3195. })
  3196. }
  3197. //撤回请求
  3198. const abolishOneSave = async () => {
  3199. const info = nodeDataInfo.value
  3200. abolishLoaing.value = true
  3201. const { error, code } = await wbsApi.abolishOne({
  3202. primaryKeyId: info?.primaryKeyId || '',
  3203. classify: authBtnTabKey.value,
  3204. projectId: projectId.value,
  3205. contractId: contractId.value,
  3206. })
  3207. abolishLoaing.value = false
  3208. if (!error && code === 200) {
  3209. window.$message?.success('撤回成功')
  3210. getTableDataAll()
  3211. window?.location?.reload() //刷新页面
  3212. }
  3213. }
  3214. //附件列表
  3215. const attachmentModal = ref(false)
  3216. const attachmentModalShow = () => {
  3217. attachmentModal.value = true
  3218. getAttachmentList()
  3219. // nextTick(()=>{
  3220. // initSortable()
  3221. // })
  3222. }
  3223. const attachmentListLoaing = ref(false)
  3224. const attachmentList = ref([])
  3225. const getAttachmentList = async () => {
  3226. attachmentListLoaing.value = true
  3227. const info = nodeDataInfo.value
  3228. const { error, code, data } = await wbsApi.tablesAndFile({
  3229. primaryKeyId: info?.primaryKeyId || '',
  3230. type: authBtnTabKey.value,
  3231. contractId: contractId.value,
  3232. projectId: projectId.value,
  3233. classify: authBtnTabKey.value,
  3234. })
  3235. attachmentListLoaing.value = false
  3236. if (!error && code === 200) {
  3237. attachmentList.value = getArrValue(data)
  3238. } else {
  3239. attachmentList.value = []
  3240. }
  3241. }
  3242. // 新增拖拽相关代码
  3243. const attachmentListRefs = ref([])
  3244. const sortableInstances = ref([])
  3245. const setAttachmentListRef = (el) => {
  3246. if (el) {
  3247. attachmentListRefs.value.push(el)
  3248. }
  3249. }
  3250. // 初始化拖拽排序
  3251. const initSortable = () => {
  3252. nextTick(() => {
  3253. attachmentList.value.forEach((item) => {
  3254. // 更可靠的DOM查找方式
  3255. const container = document.querySelector(`.hc-attachment-card[data-node-id="${item.id}"] .hc-attachment-content`)
  3256. if (container && !sortableInstances.value[item.id]) {
  3257. sortableInstances.value[item.id] = Sortable.create(container, {
  3258. animation: 150,
  3259. handle: '.hc-attachment-file-name',
  3260. onEnd: (evt) => {
  3261. // 确保能正确找到对应的item
  3262. const currentItem = attachmentList.value.find(i => i.id === item.id)
  3263. if (!currentItem) return
  3264. const newFileList = [...currentItem.fileList]
  3265. const [movedItem] = newFileList.splice(evt.oldIndex, 1)
  3266. newFileList.splice(evt.newIndex, 0, movedItem)
  3267. // 使用Vue的响应式更新
  3268. currentItem.fileList = newFileList
  3269. },
  3270. })
  3271. }
  3272. })
  3273. })
  3274. }
  3275. // 销毁 Sortable 实例
  3276. const destroySortableInstances = () => {
  3277. sortableInstances.value.forEach(instance => {
  3278. instance.destroy()
  3279. })
  3280. sortableInstances.value = [] // 清空引用数组
  3281. }
  3282. // 监听 attachmentModal 的变化
  3283. watch(attachmentModal, (newVal) => {
  3284. if (!newVal) {
  3285. destroySortableInstances() // 关闭弹窗时销毁 Sortable 实例
  3286. } else {
  3287. initSortable() // 打开弹窗时初始化 Sortable
  3288. }
  3289. })
  3290. onUnmounted(() => {
  3291. destroySortableInstances()
  3292. if (sortableInstance) {
  3293. sortableInstance.destroy()
  3294. sortableInstance = null
  3295. }
  3296. })
  3297. // 保存文件顺序到后端
  3298. const saveFileOrderLoad = ref(false)
  3299. const saveFileOrder = async () => {
  3300. saveFileOrderLoad.value = true
  3301. const { error, code, msg } = await wbsApi.sortPdf( attachmentList.value)
  3302. saveFileOrderLoad.value = false
  3303. if (!error && code === 200) {
  3304. window?.$message?.success(msg)
  3305. getAttachmentList()
  3306. initSortable()
  3307. }
  3308. }
  3309. // 监听attachmentList变化时初始化拖拽
  3310. watch(() => attachmentList.value, () => {
  3311. nextTick(()=>{
  3312. initSortable()
  3313. })
  3314. }, { deep: true })
  3315. //预览
  3316. const previewFile = (item) => {
  3317. toPdfPage(item['domainPdfUrl'])
  3318. //window.open(item['domainPdfUrl'], '_blank')
  3319. }
  3320. //删除
  3321. const delFile = async (item) => {
  3322. const { isTrial, id, tabId } = item
  3323. item.loading = true
  3324. let response
  3325. if (isTrial) {
  3326. response = await wbsApi.clearTrialAssociation({
  3327. nodeId:tabId,
  3328. recordId:id,
  3329. })
  3330. } else {
  3331. response = await wbsApi.removeBussFile({
  3332. ids: item.id,
  3333. })
  3334. }
  3335. const { error, code, msg } = response
  3336. item.loading = false
  3337. if (!error && code === 200) {
  3338. window?.$message?.success('删除成功')
  3339. getAttachmentList()
  3340. getTableDataAll()
  3341. return true
  3342. } else {
  3343. window.$message.error(msg)
  3344. return false
  3345. }
  3346. }
  3347. //划分变更
  3348. const divisionClick = () => {
  3349. router.push({
  3350. path: '/data-fill/division',
  3351. })
  3352. }
  3353. //树展开和收起
  3354. const isWbsTreeShow = ref(true)
  3355. const setWbsTreeShow = () => {
  3356. isWbsTreeShow.value = !isWbsTreeShow.value
  3357. }
  3358. //拷贝内容
  3359. const copyPositionText = (val) => {
  3360. if (val) {
  3361. //navigator.clipboard.writeText(val);
  3362. setCopyText(val)
  3363. .then(() => {
  3364. window.$message?.success('复制成功')
  3365. })
  3366. .catch(() => {
  3367. window.$message?.error('复制失败,请手动复制')
  3368. })
  3369. } else {
  3370. window.$message?.warning('没有可复制的数据')
  3371. }
  3372. }
  3373. //左右拖动,改变树形结构宽度
  3374. const isMouseTree = ref(false)
  3375. const onmousedown = () => {
  3376. let leftNum = 0
  3377. if (isLayout.value === 'no') {
  3378. leftNum = 0
  3379. } else {
  3380. leftNum = isCollapse.value ? 142 : 272
  3381. }
  3382. isMouseTree.value = true
  3383. document.onmousemove = async (ve) => {
  3384. let diffVal = ve.clientX - leftNum
  3385. if (diffVal >= 310 && diffVal <= 900) {
  3386. leftWidth.value = diffVal
  3387. }
  3388. }
  3389. document.onmouseup = () => {
  3390. document.onmousemove = null
  3391. document.onmouseup = null
  3392. isMouseTree.value = false
  3393. }
  3394. }
  3395. //更新配置
  3396. watch(
  3397. () => leftWidth.value,
  3398. (diffVal) => {
  3399. setUserConfig(diffVal)
  3400. },
  3401. )
  3402. const setUserConfig = async (data) => {
  3403. if (data > 0) {
  3404. await useClick()
  3405. useAppState.setTreeWidth(data)
  3406. await userConfigSave({ treeWidth: data })
  3407. }
  3408. }
  3409. //同步质检资料
  3410. const syncdataloading = ref(false)
  3411. const syncdata = async () => {
  3412. ListItemRef.value?.setActiveKey('')
  3413. const info = nodeDataInfo.value
  3414. syncdataloading.value = true
  3415. const { error, code, msg } = await wbsApi.syncTbadata({
  3416. pKeyId: info?.primaryKeyId || '',
  3417. })
  3418. syncdataloading.value = false
  3419. if (!error && code === 200) {
  3420. window.$message?.success(msg)
  3421. getTableDataAll()
  3422. // window?.location?.reload() //刷新页面
  3423. }
  3424. }
  3425. //同步工序资料
  3426. const syncWorkloading = ref(false)
  3427. const syncWork = async () => {
  3428. ListItemRef.value?.setActiveKey('')
  3429. const info = nodeDataInfo.value
  3430. syncdataloading.value = true
  3431. const { error, code, msg } = await wbsApi.syncWorkDate({
  3432. nodeId: info?.primaryKeyId || '',
  3433. })
  3434. syncdataloading.value = false
  3435. if (!error && code === 200) {
  3436. window.$message?.success(msg)
  3437. getTableDataAll()
  3438. // window?.location?.reload() //刷新页面
  3439. }
  3440. }
  3441. //附件添加
  3442. const typeoptions = ref([
  3443. {
  3444. value: '1',
  3445. label: '模板1',
  3446. },
  3447. {
  3448. value: '2',
  3449. label: '模板2',
  3450. },
  3451. ])
  3452. const getFileTypeApi = async () => {
  3453. const { data } = await getDictionaryBiz({
  3454. code: 'table_file_type',
  3455. })
  3456. //处理数据
  3457. let newArr = []
  3458. const newData = getArrValue(data)
  3459. for (let i = 0; i < newData.length; i++) {
  3460. newArr.push({
  3461. label: newData[i]['dictValue'],
  3462. value: Number(newData[i]['dictKey']),
  3463. })
  3464. }
  3465. typeoptions.value = newArr
  3466. }
  3467. const typevalue = ref('')
  3468. const isCanadd = ref(true)
  3469. const uploadModal = ref(false)
  3470. const fileListData = ref([])
  3471. const uploadData = ref({})
  3472. const uploadModalClose = () => {
  3473. uploadModal.value = false
  3474. typevalue.value = ''
  3475. }
  3476. //获取附件添加列表
  3477. const getBussFileList = async (pkeyId) => {
  3478. const { error, code, data } = await wbsApi.selectTableFileListByTen({
  3479. pkeyid: pkeyId,
  3480. classify: authBtnTabKey.value,
  3481. })
  3482. if (!error && code === 200) {
  3483. fileListData.value = getArrValue(data)
  3484. } else {
  3485. fileListData.value = []
  3486. }
  3487. }
  3488. const addFilelist = async () => {
  3489. getBussFileList(primaryKeyId.value)
  3490. uploadModal.value = true
  3491. await getFileTypeApi()
  3492. //上传的配置
  3493. uploadData.value = {
  3494. classify: authBtnTabKey.value,
  3495. nodeId: primaryKeyId.value,
  3496. type: typevalue.value,
  3497. contractId: contractId.value,
  3498. }
  3499. }
  3500. const changeType = (val) => {
  3501. uploadData.value.type = val
  3502. }
  3503. //上传文件
  3504. const uploadChange = async ({ type }) => {
  3505. if (type === 'success') {
  3506. getBussFileList(primaryKeyId.value)
  3507. } else if (type === 'del') {
  3508. getBussFileList(primaryKeyId.value)
  3509. }
  3510. }
  3511. const uploadUpdate = (list)=>{
  3512. fileListData.value = list
  3513. }
  3514. //树节点被选中
  3515. const treeSelectNode = ref([])
  3516. const treeSelectdata = ref([])
  3517. const ElTreeNodeCheck = (_, { checkedKeys, checkedNodes }) => {
  3518. console.log(checkedNodes, 'checkedNodes')
  3519. treeSelectNode.value = getArrValue(checkedKeys)
  3520. treeSelectdata.value = getArrValue(checkedNodes)
  3521. }
  3522. const loadMenu = ({ node, item, level }, resolve) => {
  3523. setElTreeMenu(contractInfo.value?.contractType)
  3524. let menusArr = ElTreeMenu.value
  3525. console.log(menusArr, 'menusArr')
  3526. if (level === 1) {
  3527. // menusArr = [
  3528. // {
  3529. // icon: 'add-circle',
  3530. // label: '自定义节点(水利工程)',
  3531. // key: 'add1',
  3532. // },
  3533. // {
  3534. // icon: 'add-circle',
  3535. // label: '自定义节点(数字化文件)',
  3536. // key: 'add2',
  3537. // },
  3538. // ]
  3539. resolve(menusArr)
  3540. } else {
  3541. resolve(menusArr)
  3542. }
  3543. }
  3544. //批量保存
  3545. const nodeSaveLoading = ref(false)
  3546. const NodeSaveClick = async () => {
  3547. const keys = treeSelectNode.value
  3548. const rows = treeSelectdata.value
  3549. if (rows.length <= 0 || keys.length <= 0) {
  3550. window?.$message?.warning('请先在左侧项目树选择节点')
  3551. return
  3552. }
  3553. //判断是否满足条件
  3554. let result = false
  3555. if (!website.localModel) {
  3556. result = rows.every(({ colorStatus }) => {
  3557. return colorStatus === 1 || colorStatus === 2
  3558. })
  3559. } else {
  3560. //183 甬台温
  3561. result = rows.every(({ colorStatus }) => {
  3562. return colorStatus === 1 || colorStatus === 2 || colorStatus === 4
  3563. })
  3564. }
  3565. if (!result) {
  3566. window?.$message?.warning('只能选择未上报的节点进行辅助保存')
  3567. return
  3568. }
  3569. //发起请求
  3570. nodeSaveLoading.value = true
  3571. const { error, code, msg } = await wbsApi.save_nodeId(
  3572. {
  3573. projectId: projectId.value,
  3574. contractId: contractId.value,
  3575. classify: authBtnTabKey.value,
  3576. nodeIds: keys.join(),
  3577. },
  3578. false,
  3579. )
  3580. nodeSaveLoading.value = false
  3581. if (!error && code === 200) {
  3582. window?.$message?.success('批量保存成功')
  3583. window?.location?.reload() //刷新页面
  3584. }
  3585. }
  3586. //排序
  3587. const tableSortFormRef = ref(null)
  3588. const sortFormShow = ref(false)
  3589. const tableSortFormColumn = [{ key: 'nodeName', name: '名称' }]
  3590. const tableSortFormData = ref([])
  3591. const sortFormClick = () => {
  3592. sortFormShow.value = true
  3593. tableSortFormData.value = deepClone(ListItemDatas.value)
  3594. }
  3595. // 行拖拽
  3596. const sortFormDropTap = (rows) => {
  3597. tableSortFormData.value = [] // 先清空,否则排序会异常
  3598. nextTick(() => {
  3599. tableSortFormRef.value?.setData(rows)
  3600. })
  3601. }
  3602. // 点击排序
  3603. const rowSortFormTap = (rows) => {
  3604. tableSortFormData.value = [] // 先清空,否则排序会异常
  3605. nextTick(() => {
  3606. tableSortFormData.value = rows
  3607. })
  3608. }
  3609. //关闭排序
  3610. const sortFormClose = () => {
  3611. sortFormShow.value = false
  3612. sortFormLoading.value = false
  3613. tableSortFormData.value = []
  3614. }
  3615. //提交排序
  3616. const sortFormLoading = ref(false)
  3617. const sortFormSubmit = async () => {
  3618. const treeId = primaryKeyId.value
  3619. if (isNullES(treeId)) {
  3620. window?.$message?.warning('请先在左侧项目树选择一个节点')
  3621. return
  3622. }
  3623. const rows = tableSortFormData.value
  3624. const ids = arrToKey(rows, 'pkeyId')
  3625. //发起请求
  3626. sortFormLoading.value = true
  3627. const { error, code, msg } = await wbsApi.formTableSort(
  3628. {
  3629. projectId: projectId.value,
  3630. contractId: contractId.value,
  3631. classify: authBtnTabKey.value,
  3632. nodeIds: treeId,
  3633. ids: ids,
  3634. },
  3635. false,
  3636. )
  3637. sortFormLoading.value = false
  3638. if (!error && code === 200) {
  3639. window?.$message?.success('操作成功')
  3640. window?.location?.reload() //刷新页面
  3641. }
  3642. }
  3643. //文件题名
  3644. const titleInput = ref('')
  3645. //节点基础数据
  3646. const nodeBaseDataModalDialog = ref(false)
  3647. const nodeBaseDataClick = async ()=>{
  3648. await nextTick()
  3649. await getnodeBaseData()
  3650. nodeBaseDataModalDialog.value = true
  3651. }
  3652. const nodeBaseDataLoad = ref(false)
  3653. const getnodeBaseData = async ()=>{
  3654. const { error, code, msg, data } = await nodeBaseApi.getNodeData(
  3655. {
  3656. pKeyId: primaryKeyId.value,
  3657. classify: authBtnTabKey.value,
  3658. },
  3659. )
  3660. if (!error && code === 200) {
  3661. autoFormData.value = getObjValue(data)
  3662. }
  3663. }
  3664. const getOrSaveNodeBaseInfo = async ()=>{
  3665. const { error, code, msg, data } = await nodeBaseApi.getOrSaveNodeBaseInfo(
  3666. {
  3667. pKeyId: primaryKeyId.value,
  3668. },
  3669. )
  3670. if (!error && code === 200) {
  3671. console.log(data, 'data')
  3672. autoFormData.value = getObjValue(data)
  3673. autoFormData.value.unit = data.unit === null ? '' : data.unit || ''
  3674. autoFormData.value.subUnit = data.subUnit === null ? '' : data.subUnit || ''
  3675. autoFormData.value.division = data.division === null ? '' : data.division || ''
  3676. autoFormData.value.subDivision = data.subDivision === null ? '' : data.subDivision || ''
  3677. autoFormData.value.subItem = data.subItem === null ? '' : data.subItem || ''
  3678. autoFormData.value.item = data.item === null ? '' : data.item || ''
  3679. autoFormData.value.processes = data.processes === null ? '' : data.processes || ''
  3680. window?.$message?.success(msg)
  3681. }
  3682. }
  3683. const nodeBaseDataModalClose = ()=>{
  3684. nodeBaseDataModalDialog.value = false
  3685. }
  3686. const autoFormData = ref(
  3687. {
  3688. unit: '',
  3689. subUnit: '',
  3690. division: '',
  3691. subDivision: '',
  3692. subItem: '',
  3693. item: '',
  3694. processes: '',
  3695. },
  3696. )
  3697. const resetForm = ()=>{
  3698. getOrSaveNodeBaseInfo()
  3699. }
  3700. const nodeBaseDataModalSave = async ()=>{
  3701. if (autoFormData.value?.isDisable === 1) {
  3702. window?.$message?.warning('待审批和已审批不能修改基础数据')
  3703. return
  3704. }
  3705. nodeBaseDataLoad.value = true
  3706. const { error, code, msg } = await nodeBaseApi.save(
  3707. {
  3708. nodeId: primaryKeyId.value,
  3709. ...autoFormData.value,
  3710. },
  3711. )
  3712. nodeBaseDataLoad.value = false
  3713. if (!error && code === 200) {
  3714. window?.$message?.success(msg || '操作成功')
  3715. nodeBaseDataModalDialog.value = false
  3716. //刷新页面
  3717. // setTimeout(() => {
  3718. // window?.location?.reload()
  3719. // }, 1000)
  3720. const activeKey = ListItemRef.value?.getActiveKey()
  3721. getTableDataAll(activeKey)
  3722. }
  3723. }
  3724. const showMoveClick = async (node, data)=>{
  3725. await nextTick()
  3726. moveDialogShow.value = true
  3727. }
  3728. const moveDialogShow = ref(false)
  3729. /**
  3730. * 关闭移动对话框
  3731. *
  3732. * 当点击保存按钮时,调用此方法关闭移动对话框。
  3733. */
  3734. const moveSaveClick = ()=>{
  3735. moveDialogShow.value = false
  3736. // 刷新页面
  3737. window?.location?.reload()
  3738. }
  3739. // 收藏夹
  3740. // 控制tooltip显示状态
  3741. const collectListVisible = ref(false)
  3742. const collectListClick = async ()=>{
  3743. await nextTick()
  3744. getCollectList()
  3745. // 点击时显示收藏夹列表
  3746. collectListVisible.value = true
  3747. }
  3748. // 触发元素引用
  3749. const triggerRef = ref(null)
  3750. // 显示添加输入框
  3751. const showAddInput = ref(false)
  3752. // 新文件夹名称
  3753. const newFolderName = ref('')
  3754. // 文件夹列表
  3755. // 最多显示5个文件夹
  3756. const confirmAddFolderLoad = ref(false)
  3757. // 确认添加文件夹
  3758. const confirmAddFolder = async () => {
  3759. if (!newFolderName.value.trim()) return window?.$message?.error('请输入文件夹名称')
  3760. confirmAddFolderLoad.value = true
  3761. const { error, code, msg } = await collectApi.saveOrUpdateFolder(
  3762. {
  3763. nodeId: primaryKeyId.value,
  3764. contractId: contractId.value,
  3765. name: newFolderName.value.trim(),
  3766. type:1,
  3767. },
  3768. false,
  3769. )
  3770. confirmAddFolderLoad.value = false
  3771. if (!error && code === 200) {
  3772. window?.$message?.success(msg)
  3773. newFolderName.value = ''
  3774. showAddInput.value = false
  3775. getCollectList().then(() => {
  3776. // 数据更新后重新初始化拖拽
  3777. nextTick(() => {
  3778. initSortableCollect()
  3779. })
  3780. })
  3781. }
  3782. }
  3783. // 取消添加文件夹
  3784. const cancelAddFolder = async (id) => {
  3785. newFolderName.value = ''
  3786. showAddInput.value = false
  3787. }
  3788. // 删除文件夹的接口调用
  3789. const removeCollect = async (id) => {
  3790. const { error, code, msg } = await collectApi.deleteFolder({ id })
  3791. if (!error && code === 200) {
  3792. window?.$message?.success(msg)
  3793. // 等待数据更新完成
  3794. getCollectList().then(() => {
  3795. // 数据更新后重新初始化拖拽
  3796. nextTick(() => {
  3797. initSortableCollect()
  3798. })
  3799. })
  3800. }
  3801. }
  3802. // 删除文件夹的交互逻辑
  3803. const deleteFolder = async (index, item) => {
  3804. HcDelMsg(async (resolve) => {
  3805. // 等待删除接口和数据更新完成
  3806. await removeCollect(item.id)
  3807. resolve() // 关闭弹窗
  3808. collectListVisible.value = true
  3809. // 关键:等待Vue完成DOM更新后,再初始化拖拽
  3810. })
  3811. }
  3812. // 控制缩放状态的变量
  3813. const isScaling = ref(false)
  3814. // 点击事件处理函数
  3815. const handleClick = () => {
  3816. // 触发缩放效果
  3817. isScaling.value = true
  3818. // 缩放动画结束后重置状态
  3819. setTimeout(() => {
  3820. isScaling.value = false
  3821. }, 300) // 与CSS过渡时间保持一致
  3822. //重新加载左边树
  3823. folderId.value = ''
  3824. isLookHistory.value = false
  3825. isLookHide.value = true
  3826. isSearchTree.value = false
  3827. searchTreeVal.value = ''
  3828. isShowLeft.value = false
  3829. setTimeout(() => {
  3830. isShowLeft.value = true
  3831. setElTreeMenu(authBtnTabKey.value)
  3832. }, 500)
  3833. getTableDataAll()
  3834. }
  3835. //收藏
  3836. const collectTreeData = ref({})
  3837. const collectDialogPosition = ref(null)
  3838. const collectClick = async (data, position)=>{
  3839. collectTreeData.value = data
  3840. collectDialogPosition.value = position
  3841. if (data.isCollect === 0) {
  3842. collectDialog.value = true
  3843. const hasMatch = collectList.value.some(item => item.id === collectForm.value.id)
  3844. if (!hasMatch) {
  3845. collectForm.value.id = ''
  3846. collectForm.value.name = ''
  3847. }
  3848. await nextTick()
  3849. // 获取元素
  3850. const modal = document.querySelector('.collectModalStyle')
  3851. // 动态设置位置
  3852. if (modal && collectDialogPosition) {
  3853. modal.style.left = collectDialogPosition.value.left
  3854. modal.style.top = collectDialogPosition.value.top
  3855. modal.style.position = 'fixed'
  3856. modal.style.transform = 'translateY(0) translateX(0)' // 重置transform,防止位置偏移
  3857. }
  3858. getCollectList()
  3859. } else {
  3860. console.log('取消收藏')
  3861. collectModalCancel()
  3862. }
  3863. }
  3864. const collectModalCancel = async ()=>{
  3865. const { error, code, msg } = await collectApi.collect(
  3866. {
  3867. id:'',
  3868. nodeId: collectTreeData.value.primaryKeyId,
  3869. contractId: contractId.value,
  3870. name: '',
  3871. type:0,
  3872. },
  3873. false,
  3874. )
  3875. if (!error && code === 200) {
  3876. // window?.$message?.success(msg)
  3877. collectTreeData.value.isCollect = 0
  3878. }
  3879. }
  3880. const collectDialog = ref(false)
  3881. const collectLoad = ref(false)
  3882. const collectModalClose = ()=>{
  3883. collectDialog.value = false
  3884. }
  3885. const checkCollect = (val)=>{
  3886. collectList.value.forEach(item => {
  3887. if (item.id === val) {
  3888. collectForm.value.name = item.name
  3889. }
  3890. })
  3891. }
  3892. const saveCollectLoad = ref(false)
  3893. const collectModalSave = async ()=>{
  3894. const validate = await formValidate(collectFormRef.value)
  3895. if (!validate) return
  3896. saveCollectLoad.value = true
  3897. const { error, code, msg } = await collectApi.collect(
  3898. {
  3899. id:collectForm.value.id,
  3900. nodeId: collectTreeData.value.primaryKeyId,
  3901. contractId: contractId.value,
  3902. name: collectForm.value.name,
  3903. type:1,
  3904. },
  3905. false,
  3906. )
  3907. saveCollectLoad.value = false
  3908. if (!error && code === 200) {
  3909. window?.$message?.success(msg)
  3910. collectTreeData.value.isCollect = 1
  3911. collectDialog.value = false
  3912. }
  3913. }
  3914. const collectFormRef = ref(null)
  3915. const collectForm = ref({
  3916. name:'',
  3917. id:'',
  3918. })
  3919. const collectRules = ref({
  3920. id: [
  3921. {
  3922. required: true,
  3923. message: '请选择收藏夹',
  3924. trigger: 'change',
  3925. },
  3926. ],
  3927. })
  3928. const collectList = ref([])
  3929. const editInput = ref(null)
  3930. // 文件夹列表容器的引用
  3931. const folderListContainer = ref(null)
  3932. // Sortable实例
  3933. let sortableInstance = null
  3934. // 初始化拖拽排序功能
  3935. // 改进初始化拖拽排序功能,先销毁再创建
  3936. const initSortableCollect = () => {
  3937. // 先销毁可能存在的实例
  3938. destroySortable()
  3939. // 确保容器已挂载
  3940. if (folderListContainer.value) {
  3941. sortableInstance = new Sortable(folderListContainer.value, {
  3942. animation: 150,
  3943. handle: '.folder-item',
  3944. ghostClass: 'sortable-ghost',
  3945. onEnd: handleSortEnd,
  3946. })
  3947. }
  3948. }
  3949. // 处理拖拽结束事件
  3950. const handleSortEnd = async (evt) => {
  3951. // 保存原始顺序,用于出错时恢复
  3952. const originalList = [...collectList.value]
  3953. // 从原位置移除并插入到新位置
  3954. const [movedItem] = collectList.value.splice(evt.oldIndex, 1)
  3955. collectList.value.splice(evt.newIndex, 0, movedItem)
  3956. // 调用API保存新的排序
  3957. const folderIds = arrToKey(collectList.value, 'id')
  3958. const { error, code, msg } = await collectApi.sortFolder({
  3959. ids: folderIds,
  3960. })
  3961. if (!error && code === 200) {
  3962. window?.$message?.success(msg)
  3963. getCollectList()
  3964. } else {
  3965. // 出错时恢复原始顺序
  3966. collectList.value = originalList
  3967. }
  3968. }
  3969. // 添加销毁Sortable实例的函数
  3970. const destroySortable = () => {
  3971. if (sortableInstance) {
  3972. sortableInstance.destroy()
  3973. sortableInstance = null
  3974. }
  3975. }
  3976. // 监听collectList变化,数据加载完成后初始化拖拽
  3977. watch(collectList, (newVal) => {
  3978. if (newVal.length > 0) {
  3979. // 延迟初始化,确保DOM已更新
  3980. nextTick(() => {
  3981. initSortableCollect()
  3982. })
  3983. }
  3984. })
  3985. const getCollectList = async ()=>{
  3986. collectLoad.value = true
  3987. const { error, code, msg, data } = await collectApi.folderList(
  3988. {
  3989. contractId: contractId.value,
  3990. },
  3991. )
  3992. collectLoad.value = false
  3993. if (!error && code === 200) {
  3994. collectList.value = getArrValue(data)
  3995. collectList.value = getArrValue(data).map(folder => ({
  3996. ...folder,
  3997. isEditing: false, // 是否处于编辑状态
  3998. editableName: folder.name, // 编辑框绑定的值
  3999. originalName: folder.name, // 原始名称,用于取消编辑时恢复
  4000. }))
  4001. } else {
  4002. collectList.value = []
  4003. }
  4004. // setTimeout(initSortableCollect, 0)
  4005. }
  4006. // 开始编辑文件夹名称
  4007. const startEdit = (folder) => {
  4008. collectList.value.forEach((ele)=>{
  4009. ele.isEditing = false
  4010. })
  4011. // 记录原始名称用于取消编辑时恢复
  4012. folder.originalName = folder.name
  4013. // 设置编辑状态并初始化编辑框的值
  4014. folder.isEditing = true
  4015. folder.editableName = folder.name
  4016. // 确保输入框渲染后自动聚焦
  4017. nextTick(() => {
  4018. const input = document.querySelector(`.folder-item:nth-child(${collectList.value.indexOf(folder) + 1}) .el-input__inner`)
  4019. if (input) input.focus()
  4020. })
  4021. }
  4022. // 确认编辑
  4023. // 修改确认编辑函数,添加重新初始化拖拽
  4024. const confirmEdit = async (index, folder) => {
  4025. if (!folder.editableName.trim()) {
  4026. window.$message.warning('文件夹名称不能为空')
  4027. return
  4028. }
  4029. const { error, code, msg } = await collectApi.saveOrUpdateFolder({
  4030. nodeId: primaryKeyId.value,
  4031. contractId: contractId.value,
  4032. name: folder.editableName.trim(),
  4033. type: 1,
  4034. id: folder.id,
  4035. })
  4036. if (!error && code === 200) {
  4037. window.$message.success(msg)
  4038. folder.isEditing = false
  4039. getCollectList().then(() => {
  4040. // 数据更新后重新初始化拖拽
  4041. nextTick(() => {
  4042. initSortableCollect()
  4043. })
  4044. })
  4045. }
  4046. }
  4047. const folderId = ref(null)
  4048. const selectFolder = async (folder) => {
  4049. collectListVisible.value = false
  4050. folderId.value = folder.id
  4051. // isSearchTree.value = true
  4052. // getSearchTreeData('folder')
  4053. //重新加载左边树
  4054. isShowLeft.value = false
  4055. setTimeout(() => {
  4056. isSearchTree.value = false
  4057. isLookHide.value = true
  4058. isLookHistory.value = false
  4059. isShowLeft.value = true
  4060. selCollectMneu()
  4061. }, 500)
  4062. }
  4063. const selCollectMneu = ()=>{
  4064. let newArr = []
  4065. if (folderId.value) {
  4066. if (HcIsButton('wbs_tree_edit')) {
  4067. newArr.push({ icon: 'draft', label: '编辑节点', key: 'edit' })
  4068. }
  4069. if (HcIsButton('wbs_tree_del')) {
  4070. newArr.push({ icon: 'delete-bin', label: '删除节点', key: 'del' })
  4071. }
  4072. if (HcIsButton('wbs_tree_upload')) {
  4073. newArr.push({
  4074. icon: 'file-upload',
  4075. label: '上传图纸',
  4076. key: 'upload',
  4077. })
  4078. }
  4079. if (HcIsButton('wbs_tree_mark')) {
  4080. newArr.push({ icon: 'star', label: '标记为首件', key: 'mark' })
  4081. TreeMark.value = true
  4082. }
  4083. ElTreeMenu.value = newArr
  4084. }
  4085. }
  4086. // 输入框失焦处理
  4087. const handleEditBlur = (folder) => {
  4088. }
  4089. // 获取文件夹列表的方法需要修改,为每个文件夹添加编辑相关属性
  4090. //查看最近操作的节点
  4091. const lookLoading = ref(false)
  4092. const isLookHistory = ref(false)
  4093. const lookHistory = ()=>{
  4094. isLookHistory.value = true
  4095. isSearchTree.value = true
  4096. folderId.value = ''
  4097. setElTreeMenu(authBtnTabKey.value)
  4098. getSearchTreeData('history')
  4099. }
  4100. //隐藏节点
  4101. //隐藏节点
  4102. const eyeClick = (data)=>{
  4103. nodeDataInfo.value = data
  4104. hideTreeNode(data)
  4105. }
  4106. const hideSaveLoading = ref(false)
  4107. const hideTreeNode = (data) => {
  4108. console.log( data.isBussShow, ' data.isBussShow')
  4109. HcFirmMsg( {
  4110. title: data.isBussShow === 2 ? '确定要显示此节点吗?' : '确定要隐藏此节点吗?',
  4111. text: '请确认要执行此操作吗?',
  4112. }, async (resolve) => {
  4113. hideSaveLoading.value = true
  4114. if ([3, 4].includes(data.colorStatus)) {
  4115. window.$message.warning('已审批”、“已填报-待审批”的节点不允许隐藏;')
  4116. return
  4117. }
  4118. //发起请求
  4119. hideSaveLoading.value = true
  4120. const { error, code, msg } = await wbsApi.updateNodeStates(
  4121. {
  4122. ids: data['primaryKeyId'],
  4123. // status: 2,
  4124. status:data.isBussShow == 2 ? 0 : 2, //2隐藏 0显示
  4125. },
  4126. false,
  4127. )
  4128. hideSaveLoading.value = false
  4129. if (!error && code === 200) {
  4130. data.isBussShow = data.isBussShow == 2 ? 0 : 2
  4131. }
  4132. resolve()
  4133. })
  4134. }
  4135. const isLookHide = ref(true)
  4136. const handleClickBack = ()=>{
  4137. //重新加载左边树
  4138. folderId.value = null
  4139. isLookHide.value = true
  4140. isLookHistory.value = false
  4141. isSearchTree.value = false
  4142. searchTreeVal.value = ''
  4143. isShowLeft.value = false
  4144. setTimeout(() => {
  4145. isShowLeft.value = true
  4146. setElTreeMenu(authBtnTabKey.value)
  4147. }, 500)
  4148. getTableDataAll()
  4149. }
  4150. const lookHideList = ()=>{
  4151. isLookHide.value = false
  4152. isSearchTree.value = true
  4153. folderId.value = ''
  4154. setElTreeMenu(authBtnTabKey.value)
  4155. getSearchTreeData('hide')
  4156. }
  4157. </script>
  4158. <style lang="scss" scoped>
  4159. @import "../../styles/data-fill/wbs.scss";
  4160. .hc-project-box{
  4161. display: flex;
  4162. justify-content: space-between;
  4163. align-items: center;
  4164. font-size:20px;
  4165. }
  4166. .title-input{
  4167. height: 30px;
  4168. padding: 10px;
  4169. border: 1px solid #dcdfe6;
  4170. background-color: #dcdfe6;
  4171. line-height: 13px;
  4172. border-radius: 5px;
  4173. font-weight: 500;
  4174. margin-left: 4px;
  4175. max-width: 300px;
  4176. overflow-x: auto;
  4177. overflow-y: hidden;
  4178. }
  4179. .hc-add-node-modal-foot-box {
  4180. position: relative;
  4181. display: flex;
  4182. align-items: center;
  4183. .left-box {
  4184. position: relative;
  4185. flex: 1;
  4186. display: flex;
  4187. align-items: center;
  4188. }
  4189. .right-box {
  4190. position: relative;
  4191. }
  4192. }
  4193. .hc-expansion-contraction-tree {
  4194. position: absolute;
  4195. left: -13px;
  4196. top: 0;
  4197. width: 10px;
  4198. height: 100%;
  4199. user-select: none;
  4200. cursor: pointer;
  4201. display: flex;
  4202. justify-content: center;
  4203. align-items: center;
  4204. color: #8c9099;
  4205. font-size: 22px;
  4206. border-radius: 5px;
  4207. transition: background 0.2s;
  4208. background: rgba(255, 255, 255, 0);
  4209. &:hover {
  4210. background: #f1f5f8;
  4211. color: var(--el-color-primary);
  4212. }
  4213. }
  4214. .hc-table-form-action-tip {
  4215. position: absolute;
  4216. bottom: 77px;
  4217. width: 100%;
  4218. }
  4219. .data-fill-wbs-hide-btn {
  4220. background: #fff;
  4221. color: #ffffff;
  4222. }
  4223. html.dark .data-fill-wbs-hide-btn {
  4224. background: #141414;
  4225. color: #141414;
  4226. }
  4227. html.theme-dark {
  4228. .bg-svg-xml {
  4229. background-color: initial;
  4230. background-image: initial;
  4231. }
  4232. .hc-layout-box
  4233. .hc-layout-content-box
  4234. .hc-card-max-h-box.node-tree
  4235. .hc-tree-foot-tip-box {
  4236. border-top: 1px solid #303030;
  4237. }
  4238. }
  4239. </style>
  4240. <style lang="scss">
  4241. .hc-tree-box1 .el-tree-node {
  4242. .el-checkbox {
  4243. margin-right: 0;
  4244. .el-checkbox__inner {
  4245. display: none;
  4246. }
  4247. }
  4248. .is-leaf + .el-checkbox {
  4249. margin-right: 8px;
  4250. .el-checkbox__inner {
  4251. display: inline-block;
  4252. }
  4253. }
  4254. }
  4255. .data-fill-wbs-content {
  4256. position: relative;
  4257. height: 100%;
  4258. .n-drawer-container {
  4259. margin: -20px -24px;
  4260. }
  4261. .n-drawer.n-drawer--top-placement {
  4262. height: auto !important;
  4263. background-color: initial;
  4264. pointer-events: none;
  4265. bottom: 0;
  4266. }
  4267. .drawer-data-fill-content-box {
  4268. position: relative;
  4269. height: 100%;
  4270. padding: 24px;
  4271. .n-card {
  4272. pointer-events: auto;
  4273. height: 100%;
  4274. overflow: auto;
  4275. }
  4276. .data-fill-content {
  4277. position: relative;
  4278. height: 100%;
  4279. overflow-y: auto;
  4280. scroll-behavior: smooth;
  4281. .data-fill-list-box .data-fill-list-item-content {
  4282. height: calc(100vh - 470px);
  4283. .data-fill-table-form-box {
  4284. height: 100%;
  4285. }
  4286. }
  4287. }
  4288. .data-fill-foot {
  4289. position: relative;
  4290. text-align: center;
  4291. }
  4292. }
  4293. }
  4294. .n-card.hc-card-overflow-box .n-card__content {
  4295. padding: 24px;
  4296. }
  4297. .n-card.hc-custom-card > .n-card-header {
  4298. padding: 15px 24px;
  4299. }
  4300. .n-card.hc-custom-card.copy {
  4301. width: 1200px;
  4302. max-height: 90vh;
  4303. overflow: auto;
  4304. .n-card-header .n-card-header__close {
  4305. display: none;
  4306. }
  4307. &.one {
  4308. width: 600px;
  4309. }
  4310. &.many {
  4311. width: 1200px;
  4312. }
  4313. }
  4314. .img-preview-box {
  4315. position: relative;
  4316. height: 100%;
  4317. width: 100%;
  4318. }
  4319. .hc-layout-content-box {
  4320. position: relative;
  4321. }
  4322. .iscusor {
  4323. cursor: pointer;
  4324. }
  4325. .hc-table-form-action-tip .hc-alert {
  4326. background-color: #f1f5f8;
  4327. display: inline;
  4328. vertical-align: middle;
  4329. box-shadow: -2px 0 10px 0 rgba(32, 37, 50, 0.03),
  4330. 0 10px 21px 20px rgba(32, 37, 50, 0.03);
  4331. }
  4332. .copy-node-form-box {
  4333. margin-top: 24px;
  4334. padding-top: 24px;
  4335. border-top: 1px solid #efeff5;
  4336. }
  4337. .hc-position-input-icon {
  4338. position: relative;
  4339. margin-bottom: 0;
  4340. .el-form-item__content {
  4341. position: relative;
  4342. .el-textarea .el-textarea__inner {
  4343. padding-right: 30px;
  4344. }
  4345. .hc-icon-i {
  4346. position: absolute;
  4347. right: 10px;
  4348. bottom: 0;
  4349. font-size: 20px;
  4350. cursor: pointer;
  4351. color: #0081ff;
  4352. opacity: 1;
  4353. transition: opacity 0.2s;
  4354. &:hover {
  4355. opacity: 0.5;
  4356. }
  4357. }
  4358. }
  4359. }
  4360. </style>
  4361. <style lang="scss" scoped>
  4362. /* 由小变大的脉动动画效果 */
  4363. .animate-pulse {
  4364. /* 保持动画持续运行 */
  4365. animation: pulse 1.5s ease-in-out infinite;
  4366. /* 确保图标变换时不会超出容器 */
  4367. transform-origin: center;
  4368. }
  4369. @keyframes pulse {
  4370. 0%, 100% {
  4371. /* 原始大小 */
  4372. transform: scale(1);
  4373. }
  4374. 50% {
  4375. /* 放大到1.2倍 */
  4376. transform: scale(1.2);
  4377. }
  4378. }
  4379. .hc-tree-back-to{
  4380. display: flex;
  4381. justify-content: space-between;
  4382. }
  4383. /* 新增拖拽排序相关样式 */
  4384. .sortable-ghost {
  4385. opacity: 0.5;
  4386. background: #f5f5f5;
  4387. justify-content: center;
  4388. }
  4389. .hc-attachment-item {
  4390. transition: all 0.3s;
  4391. cursor: move;
  4392. display: flex;
  4393. justify-content: space-between;
  4394. align-items: center;
  4395. padding: 12px;
  4396. margin-bottom: 8px;
  4397. background: #fff;
  4398. border-radius: 4px;
  4399. border: 1px solid #ebeef5;
  4400. &:hover {
  4401. box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  4402. }
  4403. }
  4404. .hc-attachment-content {
  4405. min-height: 20px;
  4406. }
  4407. /* 原有样式保持不变 */
  4408. .hc-attachment-card {
  4409. margin-bottom: 16px;
  4410. .hc-attachment-header {
  4411. font-weight: bold;
  4412. margin-bottom: 8px;
  4413. padding-left: 8px;
  4414. border-left: 3px solid #409eff;
  4415. }
  4416. .hc-attachment-file-name {
  4417. display: flex;
  4418. align-items: center;
  4419. .name {
  4420. margin-left: 8px;
  4421. }
  4422. }
  4423. .hc-attachment-btn-box {
  4424. display: flex;
  4425. }
  4426. }
  4427. </style>
  4428. <style>
  4429. .custom-tooltip-pro {
  4430. background-color: #7691E0 !important;
  4431. color: white !important;
  4432. border: none !important;
  4433. max-width: 300px !important; /* 最大宽度 */
  4434. padding: 10px !important;
  4435. font-size: 14px;
  4436. }
  4437. .tooltip-content {
  4438. width: 100%;
  4439. }
  4440. .new-folder {
  4441. display: flex;
  4442. justify-content: space-between;
  4443. align-items: center;
  4444. padding: 8px 5px;
  4445. margin-bottom: 5px;
  4446. border-bottom: 1px solid rgba(255, 255, 255, 0.3);
  4447. cursor: pointer;
  4448. }
  4449. .add-icon {
  4450. font-size: 18px;
  4451. }
  4452. .add-input-container {
  4453. display: flex;
  4454. align-items: center;
  4455. gap: 8px;
  4456. padding: 8px 5px;
  4457. margin-bottom: 8px;
  4458. background: white;
  4459. }
  4460. .folder-input {
  4461. flex: 1;
  4462. background-color: rgba(255, 255, 255, 1);
  4463. border: none;
  4464. border-radius: 4px;
  4465. }
  4466. .input-buttons {
  4467. display: flex;
  4468. gap: 8px;
  4469. }
  4470. .confirm-icon {
  4471. color: #4CAF50;
  4472. font-size: 18px;
  4473. }
  4474. .cancel-icon {
  4475. color: #f44336;
  4476. font-size: 18px;
  4477. }
  4478. .folder-list-container {
  4479. max-height: 200px; /* 最大高度 */
  4480. overflow-y: auto; /* 超出滚动 */
  4481. overflow-x: hidden;
  4482. }
  4483. .folder-item {
  4484. display: flex;
  4485. justify-content: space-between;
  4486. align-items: center;
  4487. padding: 8px 5px;
  4488. white-space: nowrap;
  4489. text-overflow: ellipsis;
  4490. overflow: hidden;
  4491. }
  4492. .folder-name {
  4493. margin-right: 15px; /* 名称与删除图标间距 */
  4494. flex: 1;
  4495. overflow: hidden;
  4496. text-overflow: ellipsis;
  4497. }
  4498. .delete-icon {
  4499. font-size: 18px;
  4500. flex-shrink: 0; /* 防止图标被压缩 */
  4501. }
  4502. /* 滚动条样式优化 */
  4503. .folder-list-container::-webkit-scrollbar {
  4504. width: 6px;
  4505. }
  4506. .folder-list-container::-webkit-scrollbar-thumb {
  4507. background-color: rgba(255, 255, 255, 0.3);
  4508. border-radius: 3px;
  4509. }
  4510. </style>
  4511. <style scoped>
  4512. .collect-modal {
  4513. position: fixed;
  4514. width: 20rem;
  4515. background: #fff;
  4516. border-radius: 4px;
  4517. box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  4518. z-index: 1000;
  4519. transform: translateY(0) translateX(0);
  4520. }
  4521. .collect-modal-header {
  4522. padding: 15px 20px;
  4523. border-bottom: 1px solid #e5e5e5;
  4524. display: flex;
  4525. justify-content: space-between;
  4526. align-items: center;
  4527. }
  4528. .collect-modal-header h3 {
  4529. margin: 0;
  4530. font-size: 16px;
  4531. font-weight: 500;
  4532. }
  4533. .close-btn {
  4534. background: transparent;
  4535. border: none;
  4536. font-size: 18px;
  4537. cursor: pointer;
  4538. color: #909399;
  4539. }
  4540. .collect-modal-body {
  4541. padding: 20px;
  4542. }
  4543. .collect-modal-footer {
  4544. padding: 10px 20px 15px;
  4545. border-top: 1px solid #e5e5e5;
  4546. display: flex;
  4547. justify-content: center;
  4548. gap: 10px;
  4549. }
  4550. </style>