infoMaintain.vue 154 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369
  1. <template>
  2. <div>
  3. <div class="top-wrapper">
  4. <el-button plain type="primary" icon="el-icon-back" @click="handleBack">
  5. 返回
  6. </el-button>
  7. <div class="title ml20">{{ surveyTemplateName }}内容维护</div>
  8. </div>
  9. <!-- 搜索面板 -->
  10. <div class="search-panel mt20">
  11. <el-form :inline="true" :model="searchForm" label-width="80px">
  12. <el-form-item label="状态:">
  13. <el-select
  14. v-model="searchForm.status"
  15. placeholder="请选择状态"
  16. style="width: 180px"
  17. >
  18. <el-option label="全部" value=""></el-option>
  19. <el-option label="草稿" value="-1"></el-option>
  20. <el-option label="现行版本" value="0"></el-option>
  21. <el-option label="历史版本" value="1"></el-option>
  22. </el-select>
  23. </el-form-item>
  24. <el-form-item>
  25. <el-button type="primary" icon="el-icon-search" @click="handleSearch">
  26. 查询
  27. </el-button>
  28. <el-button
  29. plain
  30. type="primary"
  31. icon="el-icon-refresh"
  32. @click="handleReset"
  33. >
  34. 重置
  35. </el-button>
  36. </el-form-item>
  37. </el-form>
  38. </div>
  39. <!-- 操作栏 -->
  40. <div class="operation-bar">
  41. <!-- v-region-permission="{ category: 'costFormManage', action: 'add' }" -->
  42. <el-button
  43. plain
  44. type="success"
  45. icon="el-icon-circle-plus"
  46. @click="handleAdd"
  47. >
  48. 添加
  49. </el-button>
  50. <!-- v-region-permission="{
  51. category: 'costFormManage',
  52. action: 'delete',
  53. }" -->
  54. <el-button
  55. plain
  56. type="danger"
  57. icon="el-icon-delete"
  58. :disabled="selectedRows.length === 0"
  59. @click="handleBatchDelete"
  60. >
  61. 批量删除
  62. </el-button>
  63. </div>
  64. <!-- 表格 -->
  65. <div class="table-container">
  66. <CostAuditTable
  67. ref="costAuditTable"
  68. :table-data="tableData"
  69. :columns="tableColumns"
  70. :show-selection="true"
  71. :show-index="true"
  72. :show-pagination="true"
  73. :pagination="pagination"
  74. :loading="loading"
  75. @selection-change="handleSelectionChange"
  76. @pagination-change="handlePaginationChange"
  77. >
  78. <!-- 创建时间自定义单元格 -->
  79. <template #createTime="{ row }">
  80. <div>{{ row.createTime ? row.createTime.split(' ')[0] : '-' }}</div>
  81. <div>{{ row.createTime ? row.createTime.split(' ')[1] : '-' }}</div>
  82. </template>
  83. <!-- 操作列 -->
  84. <template #action="{ row }">
  85. <!-- v-region-permission="{
  86. category: 'costFormManage',
  87. action: 'view',
  88. }" -->
  89. <el-button type="text" size="small" @click="handleViewDetail(row)">
  90. 详情
  91. </el-button>
  92. <!-- v-if="row.status === '-1'"
  93. v-region-permission="{
  94. category: 'costFormManage',
  95. action: 'edit',
  96. }" -->
  97. <el-button
  98. v-if="row.status != '0'"
  99. type="text"
  100. size="small"
  101. @click="handleEdit(row)"
  102. >
  103. 修改
  104. </el-button>
  105. <!-- v-region-permission="{
  106. category: 'costFormManage',
  107. action: 'delete',
  108. targetData: row,
  109. }" -->
  110. <el-button
  111. v-if="row.status != '0'"
  112. class="delete-btn"
  113. type="text"
  114. size="small"
  115. @click="handleDelete(row)"
  116. >
  117. 删除
  118. </el-button>
  119. <!-- v-region-permission="{
  120. category: 'costFormManage',
  121. action: 'edit',
  122. }" -->
  123. <el-button
  124. v-if="row.status === '-1'"
  125. type="text"
  126. size="small"
  127. @click="handleEditContent(row)"
  128. >
  129. 内容维护
  130. </el-button>
  131. <!-- v-region-permission="{
  132. category: 'costFormManage',
  133. action: 'edit',
  134. }" -->
  135. <el-button
  136. v-if="row.status === '-1'"
  137. type="text"
  138. size="small"
  139. @click="handleStatus(row)"
  140. >
  141. 启用
  142. </el-button>
  143. <!-- v-region-permission="{
  144. category: 'costFormManage',
  145. action: 'edit',
  146. }" -->
  147. <el-button
  148. v-if="row.status === '0'"
  149. type="text"
  150. size="small"
  151. @click="handleStatus(row)"
  152. >
  153. 停用
  154. </el-button>
  155. </template>
  156. </CostAuditTable>
  157. </div>
  158. <!-- 详情弹窗 -->
  159. <el-dialog title="详情" :visible.sync="detailDialogVisible" width="800px">
  160. <el-form :model="detailForm" label-width="120px" class="detail-form">
  161. <el-form-item label="ID:">{{ detailForm.id }}</el-form-item>
  162. <el-form-item label="版本号:">{{ detailForm.versionNo }}</el-form-item>
  163. <el-form-item label="状态:">
  164. {{ forStatus(detailForm.status) }}
  165. </el-form-item>
  166. <el-form-item label="创建人:">{{ detailForm.createBy }}</el-form-item>
  167. <el-form-item label="创建时间:">
  168. {{ detailForm.createTime }}
  169. </el-form-item>
  170. <el-form-item label="备注:">{{ detailForm.remarks }}</el-form-item>
  171. </el-form>
  172. <div slot="footer">
  173. <el-button @click="detailDialogVisible = false">关闭</el-button>
  174. </div>
  175. </el-dialog>
  176. <!-- 添加/修改弹窗 -->
  177. <el-dialog
  178. :title="dialogTitle"
  179. :visible.sync="dialogVisible"
  180. width="650px"
  181. :close-on-click-modal="false"
  182. >
  183. <el-form
  184. ref="dataForm"
  185. :model="dataForm"
  186. :rules="dataFormRules"
  187. label-width="120px"
  188. class="data-form"
  189. >
  190. <el-form-item label="创建人" prop="createBy">
  191. <el-input
  192. v-model="dataForm.createBy"
  193. placeholder="请输入创建人"
  194. maxlength="30"
  195. show-word-limit
  196. ></el-input>
  197. </el-form-item>
  198. <el-form-item label="创建时间" prop="createTime">
  199. <el-date-picker
  200. v-model="dataForm.createTime"
  201. type="datetime"
  202. placeholder="选择日期时间"
  203. style="width: 100%"
  204. ></el-date-picker>
  205. </el-form-item>
  206. <el-form-item label="备注">
  207. <el-input
  208. v-model="dataForm.remarks"
  209. type="textarea"
  210. placeholder="请输入备注"
  211. rows="3"
  212. maxlength="500"
  213. show-word-limit
  214. ></el-input>
  215. </el-form-item>
  216. </el-form>
  217. <div slot="footer" class="dialog-footer">
  218. <el-button @click="dialogVisible = false">取消</el-button>
  219. <el-button type="primary" @click="submitForm">确定</el-button>
  220. </div>
  221. </el-dialog>
  222. <!-- 内容修改弹窗 -->
  223. <el-dialog
  224. title="内容维护"
  225. :visible.sync="contentEditDialogVisible"
  226. width="75%"
  227. class="content-edit-dialog"
  228. :close-on-click-modal="false"
  229. >
  230. <div class="content-edit-container">
  231. <div class="table-header-info">
  232. <div class="table-name">
  233. 调查表名称:{{ contentEditForm.tableName }}
  234. </div>
  235. <div class="table-style">
  236. 表单样式:
  237. <el-radio-group
  238. v-model="contentEditForm.templateType"
  239. @change="handleFormStyleChange"
  240. >
  241. <el-radio v-if="contentEditForm.templateType === '1'" label="1">
  242. 单记录
  243. </el-radio>
  244. <el-radio v-if="contentEditForm.templateType === '2'" label="2">
  245. 固定表
  246. </el-radio>
  247. <el-radio v-if="contentEditForm.templateType === '3'" label="3">
  248. 动态表
  249. </el-radio>
  250. </el-radio-group>
  251. </div>
  252. <div v-if="viewDetail" class="detail-info-container">
  253. <div class="detail-item">
  254. <span class="detail-label">版本号:</span>
  255. <span class="detail-value">{{ detailForm.versionNo }}</span>
  256. </div>
  257. <div class="detail-item">
  258. <span class="detail-label">状态:</span>
  259. <span class="detail-value">
  260. {{ forStatus(detailForm.status) }}
  261. </span>
  262. </div>
  263. <div class="detail-item">
  264. <span class="detail-label">创建人:</span>
  265. <span class="detail-value">{{ detailForm.createBy }}</span>
  266. </div>
  267. <div class="detail-item">
  268. <span class="detail-label">创建时间:</span>
  269. <span class="detail-value">{{ detailForm.createTime }}</span>
  270. </div>
  271. <div class="detail-item">
  272. <span class="detail-label">备注:</span>
  273. <span class="detail-value">{{ detailForm.remarks }}</span>
  274. </div>
  275. </div>
  276. </div>
  277. <!-- 单记录列表 -->
  278. <div v-if="contentEditForm.templateType === '1'">
  279. <div class="button-group">
  280. <el-button
  281. v-if="!viewDetail"
  282. type="primary"
  283. @click="handleAddTableHeader('单记录')"
  284. >
  285. 添加项目
  286. </el-button>
  287. <el-button
  288. v-if="!viewDetail"
  289. type="primary"
  290. @click="handleSaveContent('单记录')"
  291. >
  292. 保存
  293. </el-button>
  294. </div>
  295. <div class="table-edit-container">
  296. <el-table
  297. :data="contentEditForm.tableHeaders"
  298. border
  299. style="width: 100%"
  300. >
  301. <el-table-column label="序号" width="80" align="center">
  302. <template slot-scope="scope">
  303. <span>{{ scope.$index + 1 }}</span>
  304. </template>
  305. </el-table-column>
  306. <el-table-column
  307. prop="fieldName"
  308. label="字段名称"
  309. min-width="150"
  310. >
  311. <template slot-scope="scope">
  312. <el-input
  313. v-model="scope.row.fieldName"
  314. placeholder="请输入字段名称"
  315. size="small"
  316. :disabled="viewDetail"
  317. ></el-input>
  318. </template>
  319. </el-table-column>
  320. <el-table-column prop="fieldType" label="字段类型" width="220">
  321. <template slot-scope="scope">
  322. <el-select
  323. v-model="scope.row.fieldType"
  324. placeholder="请选择字段类型"
  325. size="small"
  326. :disabled="viewDetail"
  327. @change="handleFieldTypeChange(scope.row)"
  328. >
  329. <el-option label="字符串" value="string"></el-option>
  330. <el-option label="整数" value="integer"></el-option>
  331. <el-option label="小数" value="double"></el-option>
  332. <el-option label="日期" value="datetime"></el-option>
  333. <el-option label="布尔值" value="boolean"></el-option>
  334. </el-select>
  335. </template>
  336. </el-table-column>
  337. <el-table-column prop="format" label="格式" width="220">
  338. <template slot-scope="scope">
  339. <!-- 字符串类型格式 -->
  340. <div
  341. v-if="scope.row.fieldType === 'string'"
  342. class="format-input"
  343. >
  344. <span class="format-prefix">长度</span>
  345. <el-input
  346. v-model="scope.row.format"
  347. placeholder="请输入长度"
  348. size="small"
  349. style="width: calc(100% - 80px)"
  350. :disabled="viewDetail"
  351. ></el-input>
  352. </div>
  353. <!-- 整数类型格式 -->
  354. <div
  355. v-else-if="scope.row.fieldType === 'integer'"
  356. class="format-input"
  357. >
  358. <span class="format-prefix">整数</span>
  359. <el-input
  360. v-model="scope.row.fieldTypelen"
  361. placeholder="整数位数"
  362. size="small"
  363. style="width: 80px; margin: 0 5px"
  364. :disabled="viewDetail"
  365. ></el-input>
  366. </div>
  367. <!-- 小数类型格式 -->
  368. <div
  369. v-else-if="scope.row.fieldType === 'double'"
  370. class="format-input"
  371. >
  372. <span class="format-prefix">小数</span>
  373. <el-input
  374. v-model="scope.row.fieldTypenointlen"
  375. placeholder="小数位数"
  376. size="small"
  377. style="width: 80px; margin-left: 5px"
  378. :disabled="viewDetail"
  379. ></el-input>
  380. </div>
  381. <!-- 日期类型格式 -->
  382. <div
  383. v-else-if="scope.row.fieldType === 'datetime'"
  384. class="format-input"
  385. >
  386. <el-select
  387. v-model="scope.row.format"
  388. placeholder="请选择日期格式"
  389. size="small"
  390. style="width: 100%"
  391. :disabled="viewDetail"
  392. >
  393. <el-option
  394. label="yyyy-MM-dd HH:mm:ss"
  395. value="yyyy-MM-dd HH:mm:ss"
  396. ></el-option>
  397. <el-option
  398. label="yyyy-MM-dd"
  399. value="yyyy-MM-dd"
  400. ></el-option>
  401. </el-select>
  402. </div>
  403. <!-- 布尔类型格式 -->
  404. <div v-else-if="scope.row.fieldType === 'boolean'">
  405. <el-select
  406. v-model="scope.row.format"
  407. placeholder="请选择布尔值格式"
  408. size="small"
  409. style="width: 100%"
  410. :disabled="viewDetail"
  411. >
  412. <el-option label="是" value="true"></el-option>
  413. <el-option label="否" value="false"></el-option>
  414. </el-select>
  415. </div>
  416. <!-- 默认情况 -->
  417. <el-input
  418. v-else
  419. v-model="scope.row.format"
  420. :placeholder="getFormatPlaceholder(scope.row.fieldType)"
  421. size="small"
  422. :disabled="viewDetail"
  423. ></el-input>
  424. </template>
  425. </el-table-column>
  426. <el-table-column prop="isRequired" label="是否必填" width="120">
  427. <template slot-scope="scope">
  428. <el-select
  429. v-model="scope.row.isRequired"
  430. size="small"
  431. :disabled="scope.row.isDisabled || viewDetail"
  432. >
  433. <el-option label="是" value="true"></el-option>
  434. <el-option label="否" value="false"></el-option>
  435. </el-select>
  436. </template>
  437. </el-table-column>
  438. <el-table-column prop="showVisible" label="是否显示" width="120">
  439. <template slot-scope="scope">
  440. <el-select
  441. v-model="scope.row.showVisible"
  442. size="small"
  443. :disabled="scope.row.isDisabled || viewDetail"
  444. >
  445. <el-option label="是" value="1"></el-option>
  446. <el-option label="否" value="0"></el-option>
  447. </el-select>
  448. </template>
  449. </el-table-column>
  450. <el-table-column prop="isDict" label="绑定字典" min-width="150">
  451. <template slot-scope="scope">
  452. <div class="bind-dict-column">
  453. <el-select
  454. v-model="scope.row.isDict"
  455. size="small"
  456. style="width: 80px"
  457. :disabled="scope.row.isDisabled || viewDetail"
  458. @change="handleBindDictChange(scope.row)"
  459. >
  460. <el-option label="是" value="true"></el-option>
  461. <el-option label="否" value="false"></el-option>
  462. </el-select>
  463. <el-select
  464. v-if="scope.row.isDict === 'true'"
  465. v-model="scope.row.dictCode"
  466. placeholder="请选择字典"
  467. class="dict-select"
  468. size="small"
  469. style="width: 120px; margin-top: 5px"
  470. :disabled="scope.row.isDisabled || viewDetail"
  471. >
  472. <el-option
  473. v-for="(item, index) in dictTypeList"
  474. :key="index"
  475. :label="item.name"
  476. :value="String(item.typeKey)"
  477. ></el-option>
  478. </el-select>
  479. </div>
  480. </template>
  481. </el-table-column>
  482. <el-table-column label="操作" width="150" fixed="right">
  483. <template slot-scope="scope">
  484. <div class="table-actions">
  485. <el-button
  486. type="text"
  487. size="mini"
  488. :disabled="viewDetail"
  489. class="delete-btn"
  490. @click="
  491. handleDeleteHeader(scope.$index, '单记录', scope.row)
  492. "
  493. >
  494. 删除
  495. </el-button>
  496. <el-button
  497. v-if="scope.$index !== 0"
  498. type="text"
  499. size="mini"
  500. :disabled="viewDetail"
  501. @click="
  502. handleMoveUp(scope.$index, '单记录表头', scope.row)
  503. "
  504. >
  505. 上升
  506. </el-button>
  507. <el-button
  508. v-if="
  509. scope.$index !== contentEditForm.tableHeaders.length - 1
  510. "
  511. type="text"
  512. size="mini"
  513. :disabled="viewDetail"
  514. @click="handleMoveDown(scope.$index)"
  515. >
  516. 下降
  517. </el-button>
  518. </div>
  519. </template>
  520. </el-table-column>
  521. </el-table>
  522. </div>
  523. </div>
  524. <!-- 固定表时显示 -->
  525. <div v-if="contentEditForm.templateType === '2'">
  526. <div class="button-group">
  527. <el-button
  528. v-if="!viewDetail"
  529. type="primary"
  530. @click="handleAddTableHeader('固定表表头')"
  531. >
  532. 添加表头
  533. </el-button>
  534. <el-button
  535. v-if="!viewDetail"
  536. type="primary"
  537. @click="handleSaveContent('固定表表头')"
  538. >
  539. 下一步
  540. </el-button>
  541. </div>
  542. <div class="table-edit-container">
  543. <el-table
  544. :data="contentEditForm.fixedTable.tableHeaders"
  545. border
  546. style="width: 100%"
  547. >
  548. <el-table-column label="序号" width="80" align="center">
  549. <template slot-scope="scope">
  550. <span>{{ scope.$index + 1 }}</span>
  551. </template>
  552. </el-table-column>
  553. <el-table-column
  554. prop="fieldName"
  555. label="字段名称"
  556. min-width="150"
  557. >
  558. <template slot-scope="scope">
  559. <el-input
  560. v-model="scope.row.fieldName"
  561. placeholder="请输入字段名称"
  562. size="small"
  563. :disabled="scope.row.isDisabled || viewDetail"
  564. ></el-input>
  565. </template>
  566. </el-table-column>
  567. <el-table-column prop="fieldType" label="字段类型" width="120">
  568. <template slot-scope="scope">
  569. <el-select
  570. v-model="scope.row.fieldType"
  571. placeholder="请选择字段类型"
  572. size="small"
  573. :disabled="scope.row.isDisabled || viewDetail"
  574. @change="handleFieldTypeChange(scope.row)"
  575. >
  576. <el-option label="字符串" value="string"></el-option>
  577. <el-option label="整数" value="integer"></el-option>
  578. <el-option label="小数" value="double"></el-option>
  579. <el-option label="日期" value="datetime"></el-option>
  580. <el-option label="布尔值" value="boolean"></el-option>
  581. </el-select>
  582. </template>
  583. </el-table-column>
  584. <el-table-column prop="format" label="格式" width="220">
  585. <template slot-scope="scope">
  586. <!-- 字符串类型格式 -->
  587. <div
  588. v-if="scope.row.fieldType === 'string'"
  589. class="format-input"
  590. >
  591. <span class="format-prefix">长度</span>
  592. <el-input
  593. v-model="scope.row.format"
  594. placeholder="请输入长度"
  595. size="small"
  596. style="width: calc(100% - 80px)"
  597. :disabled="scope.row.isDisabled || viewDetail"
  598. ></el-input>
  599. </div>
  600. <!-- 整数类型格式 -->
  601. <div
  602. v-else-if="scope.row.fieldType === 'integer'"
  603. class="format-input"
  604. >
  605. <span class="format-prefix">整数</span>
  606. <el-input
  607. v-model="scope.row.fieldTypelen"
  608. placeholder="整数位数"
  609. size="small"
  610. style="width: 80px; margin: 0 5px"
  611. :disabled="scope.row.isDisabled || viewDetail"
  612. ></el-input>
  613. </div>
  614. <!-- 小数类型格式 -->
  615. <div
  616. v-else-if="scope.row.fieldType === 'double'"
  617. class="format-input"
  618. >
  619. <span class="format-prefix">小数</span>
  620. <el-input
  621. v-model="scope.row.fieldTypenointlen"
  622. placeholder="小数位数"
  623. size="small"
  624. style="width: 80px; margin-left: 5px"
  625. :disabled="scope.row.isDisabled || viewDetail"
  626. ></el-input>
  627. </div>
  628. <!-- 日期类型格式 -->
  629. <div
  630. v-else-if="scope.row.fieldType === 'datetime'"
  631. class="format-input"
  632. >
  633. <el-select
  634. v-model="scope.row.format"
  635. placeholder="请选择日期格式"
  636. size="small"
  637. style="width: 100%"
  638. :disabled="scope.row.isDisabled"
  639. >
  640. <el-option
  641. label="yyyy-MM-dd HH:mm:ss"
  642. value="yyyy-MM-dd HH:mm:ss"
  643. ></el-option>
  644. <el-option
  645. label="yyyy-MM-dd"
  646. value="yyyy-MM-dd"
  647. ></el-option>
  648. </el-select>
  649. </div>
  650. <!-- 布尔类型格式 -->
  651. <div v-else-if="scope.row.fieldType === 'boolean'">
  652. <el-select
  653. v-model="scope.row.format"
  654. placeholder="请选择布尔值格式"
  655. size="small"
  656. style="width: 100%"
  657. :disabled="scope.row.isDisabled || viewDetail"
  658. >
  659. <el-option label="是" value="true"></el-option>
  660. <el-option label="否" value="false"></el-option>
  661. </el-select>
  662. </div>
  663. <!-- 默认情况 -->
  664. <el-input
  665. v-else
  666. v-model="scope.row.format"
  667. :placeholder="getFormatPlaceholder(scope.row.fieldType)"
  668. size="small"
  669. :disabled="scope.row.isDisabled || viewDetail"
  670. ></el-input>
  671. </template>
  672. </el-table-column>
  673. <el-table-column prop="isRequired" label="是否必填" width="120">
  674. <template slot-scope="scope">
  675. <el-select
  676. v-model="scope.row.isRequired"
  677. size="small"
  678. :disabled="scope.row.isDisabled || viewDetail"
  679. >
  680. <el-option label="是" value="true"></el-option>
  681. <el-option label="否" value="false"></el-option>
  682. </el-select>
  683. </template>
  684. </el-table-column>
  685. <el-table-column prop="showVisible" label="是否显示" width="120">
  686. <template slot-scope="scope">
  687. <el-select
  688. v-model="scope.row.showVisible"
  689. size="small"
  690. :disabled="scope.row.isDisabled || viewDetail"
  691. >
  692. <el-option label="是" value="1"></el-option>
  693. <el-option label="否" value="0"></el-option>
  694. </el-select>
  695. </template>
  696. </el-table-column>
  697. <el-table-column
  698. prop="isAuditPeriod"
  699. label="是否绑定监审期间"
  700. width="140"
  701. >
  702. <template slot-scope="scope">
  703. <el-select
  704. v-model="scope.row.isAuditPeriod"
  705. size="small"
  706. :disabled="scope.row.isDisabled || viewDetail"
  707. >
  708. <el-option label="是" value="true"></el-option>
  709. <el-option label="否" value="false"></el-option>
  710. </el-select>
  711. </template>
  712. </el-table-column>
  713. <el-table-column prop="isDict" label="绑定字典" min-width="150">
  714. <template slot-scope="scope">
  715. <div class="bind-dict-column">
  716. <el-select
  717. v-model="scope.row.isDict"
  718. size="small"
  719. style="width: 80px"
  720. :disabled="scope.row.isDisabled || viewDetail"
  721. @change="handleBindDictChange(scope.row)"
  722. >
  723. <el-option label="是" value="true"></el-option>
  724. <el-option label="否" value="false"></el-option>
  725. </el-select>
  726. <el-select
  727. v-if="scope.row.isDict === 'true'"
  728. v-model="scope.row.dictCode"
  729. placeholder="请选择字典"
  730. class="dict-select"
  731. size="small"
  732. style="width: 120px; margin-top: 5px"
  733. :disabled="scope.row.isDisabled || viewDetail"
  734. >
  735. <el-option
  736. v-for="(item, index) in dictTypeList"
  737. :key="index"
  738. :label="item.name"
  739. :value="String(item.typeKey)"
  740. ></el-option>
  741. </el-select>
  742. </div>
  743. </template>
  744. </el-table-column>
  745. <el-table-column label="操作" width="150" fixed="right">
  746. <template slot-scope="scope">
  747. <div class="table-actions">
  748. <el-button
  749. type="text"
  750. size="mini"
  751. :disabled="scope.row.isDisabled || viewDetail"
  752. class="delete-btn"
  753. @click="
  754. handleDeleteHeader(
  755. scope.$index,
  756. '固定表表头',
  757. scope.row
  758. )
  759. "
  760. >
  761. 删除
  762. </el-button>
  763. <el-button
  764. v-if="scope.$index !== 0"
  765. type="text"
  766. size="mini"
  767. :disabled="scope.row.isDisabled || viewDetail"
  768. @click="
  769. handleMoveUp(scope.$index, '固定表表头', scope.row)
  770. "
  771. >
  772. 上升
  773. </el-button>
  774. <el-button
  775. v-if="
  776. scope.$index !== contentEditForm.tableHeaders.length - 1
  777. "
  778. type="text"
  779. size="mini"
  780. :disabled="scope.row.isDisabled || viewDetail"
  781. @click="handleMoveDown(scope.$index)"
  782. >
  783. 下降
  784. </el-button>
  785. </div>
  786. </template>
  787. </el-table-column>
  788. </el-table>
  789. </div>
  790. <div>
  791. <div class="button-group">
  792. <el-button
  793. v-if="!viewDetail"
  794. type="primary"
  795. @click="handleAddTableHeader('固定表项目')"
  796. >
  797. 添加项目
  798. </el-button>
  799. <el-button
  800. v-if="!viewDetail"
  801. type="primary"
  802. @click="handleSaveContent('固定表项目')"
  803. >
  804. 保存
  805. </el-button>
  806. </div>
  807. <div class="table-edit-container">
  808. <el-table
  809. :data="contentEditForm.fixedTable.fixedTables"
  810. border
  811. style="width: 100%"
  812. row-key="rowid"
  813. default-expand-all
  814. :tree-props="{
  815. children: 'children',
  816. hasChildren: 'hasChildren',
  817. }"
  818. @selection-change="handleSelectionChange"
  819. >
  820. <el-table-column label="父子节点" align="center" width="100">
  821. <template slot-scope="scope">
  822. <el-tag
  823. v-if="
  824. scope.row.isChild ||
  825. scope.row.isSubItem ||
  826. (scope.row.parentid &&
  827. scope.row.parentid != -1 &&
  828. scope.row.parentid != '-1')
  829. "
  830. type="success"
  831. size="small"
  832. >
  833. 子项
  834. </el-tag>
  835. <el-tag
  836. v-else-if="
  837. scope.row.parentid === -1 ||
  838. scope.row.parentid === '-1' ||
  839. !scope.row.parentid
  840. "
  841. type="primary"
  842. size="small"
  843. >
  844. 父项
  845. </el-tag>
  846. <el-tag v-else type="info" size="small">无</el-tag>
  847. </template>
  848. </el-table-column>
  849. <el-table-column label="序号" width="120" align="center">
  850. <template slot-scope="scope">
  851. <el-input
  852. :value="
  853. scope.row.fixedValues
  854. ? scope.row.fixedValues['序号']
  855. : ''
  856. "
  857. size="small"
  858. placeholder="数字或中文"
  859. :disabled="viewDetail"
  860. style="flex: 1; margin: 0"
  861. @input="handleFixedValueChange(scope.row, '序号', $event)"
  862. ></el-input>
  863. </template>
  864. </el-table-column>
  865. <el-table-column
  866. v-for="(item, index) in contentEditForm.fixedTable
  867. .fixedTableHeaders"
  868. :key="index"
  869. :label="item.rkey"
  870. align="center"
  871. >
  872. <template slot-scope="scope">
  873. <el-input
  874. :value="
  875. scope.row.fixedValues
  876. ? scope.row.fixedValues[item.rkey]
  877. : ''
  878. "
  879. size="small"
  880. :disabled="viewDetail"
  881. @input="
  882. handleFixedValueChange(scope.row, item.rkey, $event)
  883. "
  884. ></el-input>
  885. </template>
  886. </el-table-column>
  887. <el-table-column label="指标编号" width="100" align="center">
  888. <template slot-scope="scope">
  889. <el-input
  890. :value="scope.row.cellCode"
  891. size="small"
  892. :disabled="viewDetail"
  893. @input="(val) => $set(scope.row, 'cellCode', val)"
  894. ></el-input>
  895. </template>
  896. </el-table-column>
  897. <el-table-column label="计算公式" width="100" align="center">
  898. <template slot-scope="scope">
  899. <el-input
  900. v-model="scope.row.calculationFormula"
  901. size="small"
  902. readonly
  903. :disabled="viewDetail"
  904. @click.native="
  905. openCalculationFormulaDialogVisible(
  906. scope.row,
  907. scope.$index
  908. )
  909. "
  910. ></el-input>
  911. </template>
  912. </el-table-column>
  913. <el-table-column label="单位" width="100" align="center">
  914. <template slot-scope="scope">
  915. <el-input
  916. :value="scope.row.unit"
  917. size="small"
  918. :disabled="viewDetail"
  919. @input="(val) => $set(scope.row, 'unit', val)"
  920. ></el-input>
  921. </template>
  922. </el-table-column>
  923. <el-table-column label="操作" align="center" fixed="right">
  924. <template slot-scope="scope">
  925. <div class="table-actions">
  926. <el-button
  927. v-if="!scope.row.isChild"
  928. type="text"
  929. size="mini"
  930. :disabled="viewDetail"
  931. @click="
  932. handleAddChildItem(
  933. scope.$index,
  934. '固定表项目',
  935. scope.row
  936. )
  937. "
  938. >
  939. 添加子项
  940. </el-button>
  941. <el-button
  942. type="text"
  943. size="mini"
  944. :disabled="viewDetail"
  945. class="delete-btn"
  946. @click="
  947. handleDeleteHeader(
  948. scope.$index,
  949. '固定表项目',
  950. scope.row
  951. )
  952. "
  953. >
  954. 删除
  955. </el-button>
  956. <el-button
  957. v-if="scope.$index !== 0"
  958. type="text"
  959. size="mini"
  960. :disabled="viewDetail"
  961. @click="handleMoveUp(scope.$index, '固定表', scope.row)"
  962. >
  963. 上升
  964. </el-button>
  965. <el-button
  966. v-if="
  967. scope.$index !==
  968. contentEditForm.fixedTable.fixedTables.length - 1
  969. "
  970. type="text"
  971. size="mini"
  972. :disabled="viewDetail"
  973. @click="
  974. handleMoveDown(scope.$index, '固定表', scope.row)
  975. "
  976. >
  977. 下降
  978. </el-button>
  979. </div>
  980. </template>
  981. </el-table-column>
  982. </el-table>
  983. </div>
  984. </div>
  985. </div>
  986. <!-- 动态表时显示 -->
  987. <div v-if="contentEditForm.templateType === '3'">
  988. <div class="button-group">
  989. <el-button
  990. v-if="!viewDetail"
  991. type="primary"
  992. @click="handleAddTableHeader('动态表表头')"
  993. >
  994. 添加表头
  995. </el-button>
  996. <el-button
  997. v-if="!viewDetail"
  998. type="primary"
  999. @click="handleSaveContent('动态表表头')"
  1000. >
  1001. 下一步
  1002. </el-button>
  1003. </div>
  1004. <div class="table-edit-container">
  1005. <el-table
  1006. :data="contentEditForm.dynamicTable.tableHeaders"
  1007. border
  1008. style="width: 100%"
  1009. >
  1010. <el-table-column label="序号" width="80" align="center">
  1011. <template slot-scope="scope">
  1012. <span>{{ scope.$index + 1 }}</span>
  1013. </template>
  1014. </el-table-column>
  1015. <el-table-column
  1016. prop="fieldName"
  1017. label="字段名称"
  1018. min-width="150"
  1019. >
  1020. <template slot-scope="scope">
  1021. <el-input
  1022. v-model="scope.row.fieldName"
  1023. placeholder="请输入字段名称"
  1024. size="small"
  1025. :disabled="scope.row.isDisabled || viewDetail"
  1026. ></el-input>
  1027. </template>
  1028. </el-table-column>
  1029. <el-table-column prop="fieldType" label="字段类型" width="120">
  1030. <template slot-scope="scope">
  1031. <el-select
  1032. v-model="scope.row.fieldType"
  1033. placeholder="请选择字段类型"
  1034. size="small"
  1035. :disabled="scope.row.isDisabled || viewDetail"
  1036. @change="handleFieldTypeChange(scope.row)"
  1037. >
  1038. <el-option label="字符串" value="string"></el-option>
  1039. <el-option label="整数" value="integer"></el-option>
  1040. <el-option label="小数" value="double"></el-option>
  1041. <el-option label="日期" value="datetime"></el-option>
  1042. <el-option label="布尔值" value="boolean"></el-option>
  1043. </el-select>
  1044. </template>
  1045. </el-table-column>
  1046. <el-table-column prop="format" label="格式" width="220">
  1047. <template slot-scope="scope">
  1048. <!-- 字符串类型格式 -->
  1049. <div
  1050. v-if="scope.row.fieldType === 'string'"
  1051. class="format-input"
  1052. >
  1053. <span class="format-prefix">长度</span>
  1054. <el-input
  1055. v-model="scope.row.format"
  1056. placeholder="请输入长度"
  1057. size="small"
  1058. style="width: calc(100% - 80px)"
  1059. :disabled="scope.row.isDisabled || viewDetail"
  1060. ></el-input>
  1061. </div>
  1062. <!-- 整数类型格式 -->
  1063. <div
  1064. v-else-if="scope.row.fieldType === 'integer'"
  1065. class="format-input"
  1066. >
  1067. <span class="format-prefix">整数</span>
  1068. <el-input
  1069. v-model="scope.row.fieldTypelen"
  1070. placeholder="整数位数"
  1071. size="small"
  1072. style="width: 80px; margin: 0 5px"
  1073. :disabled="scope.row.isDisabled || viewDetail"
  1074. ></el-input>
  1075. </div>
  1076. <!-- 小数类型格式 -->
  1077. <div
  1078. v-else-if="scope.row.fieldType === 'double'"
  1079. class="format-input"
  1080. >
  1081. <span class="format-prefix">小数</span>
  1082. <el-input
  1083. v-model="scope.row.fieldTypenointlen"
  1084. placeholder="小数位数"
  1085. size="small"
  1086. style="width: 80px; margin-left: 5px"
  1087. :disabled="scope.row.isDisabled || viewDetail"
  1088. ></el-input>
  1089. </div>
  1090. <!-- 日期类型格式 -->
  1091. <div
  1092. v-else-if="scope.row.fieldType === 'datetime'"
  1093. class="format-input"
  1094. >
  1095. <el-select
  1096. v-model="scope.row.format"
  1097. placeholder="请选择日期格式"
  1098. size="small"
  1099. style="width: 100%"
  1100. :disabled="scope.row.isDisabled || viewDetail"
  1101. >
  1102. <el-option
  1103. label="yyyy-MM-dd HH:mm:ss"
  1104. value="yyyy-MM-dd HH:mm:ss"
  1105. ></el-option>
  1106. <el-option
  1107. label="yyyy-MM-dd"
  1108. value="yyyy-MM-dd"
  1109. ></el-option>
  1110. </el-select>
  1111. </div>
  1112. <!-- 布尔类型格式 -->
  1113. <div v-else-if="scope.row.fieldType === 'boolean'">
  1114. <el-select
  1115. v-model="scope.row.format"
  1116. placeholder="请选择布尔值格式"
  1117. size="small"
  1118. style="width: 100%"
  1119. :disabled="scope.row.isDisabled || viewDetail"
  1120. >
  1121. <el-option label="是" value="true"></el-option>
  1122. <el-option label="否" value="false"></el-option>
  1123. </el-select>
  1124. </div>
  1125. <!-- 默认情况 -->
  1126. <el-input
  1127. v-else
  1128. v-model="scope.row.format"
  1129. :placeholder="getFormatPlaceholder(scope.row.fieldType)"
  1130. size="small"
  1131. :disabled="scope.row.isDisabled || viewDetail"
  1132. ></el-input>
  1133. </template>
  1134. </el-table-column>
  1135. <el-table-column prop="isRequired" label="是否必填" width="120">
  1136. <template slot-scope="scope">
  1137. <el-select
  1138. v-model="scope.row.isRequired"
  1139. size="small"
  1140. :disabled="scope.row.isDisabled || viewDetail"
  1141. >
  1142. <el-option label="是" value="true"></el-option>
  1143. <el-option label="否" value="false"></el-option>
  1144. </el-select>
  1145. </template>
  1146. </el-table-column>
  1147. <el-table-column prop="showVisible" label="是否显示" width="120">
  1148. <template slot-scope="scope">
  1149. <el-select
  1150. v-model="scope.row.showVisible"
  1151. size="small"
  1152. :disabled="scope.row.isDisabled || viewDetail"
  1153. >
  1154. <el-option label="是" value="1"></el-option>
  1155. <el-option label="否" value="0"></el-option>
  1156. </el-select>
  1157. </template>
  1158. </el-table-column>
  1159. <el-table-column prop="isDict" label="绑定字典" min-width="150">
  1160. <template slot-scope="scope">
  1161. <div class="bind-dict-column">
  1162. <el-select
  1163. v-model="scope.row.isDict"
  1164. size="small"
  1165. style="width: 80px"
  1166. :disabled="scope.row.isDisabled || viewDetail"
  1167. @change="handleBindDictChange(scope.row)"
  1168. >
  1169. <el-option label="是" value="true"></el-option>
  1170. <el-option label="否" value="false"></el-option>
  1171. </el-select>
  1172. <el-select
  1173. v-if="scope.row.isDict === 'true'"
  1174. v-model="scope.row.dictCode"
  1175. placeholder="请选择字典"
  1176. class="dict-select"
  1177. size="small"
  1178. style="width: 120px; margin-top: 5px"
  1179. :disabled="scope.row.isDisabled || viewDetail"
  1180. >
  1181. <el-option
  1182. v-for="(item, index) in dictTypeList"
  1183. :key="index"
  1184. :label="item.name"
  1185. :value="String(item.typeKey)"
  1186. ></el-option>
  1187. </el-select>
  1188. </div>
  1189. </template>
  1190. </el-table-column>
  1191. <el-table-column label="操作" width="150" fixed="right">
  1192. <template slot-scope="scope">
  1193. <div class="table-actions">
  1194. <el-button
  1195. type="text"
  1196. size="mini"
  1197. :disabled="scope.row.isDisabled || viewDetail"
  1198. class="delete-btn"
  1199. @click="
  1200. handleDeleteHeader(
  1201. scope.$index,
  1202. '动态表表头',
  1203. scope.row
  1204. )
  1205. "
  1206. >
  1207. 删除
  1208. </el-button>
  1209. <el-button
  1210. v-if="scope.$index !== 0"
  1211. type="text"
  1212. size="mini"
  1213. :disabled="scope.row.isDisabled || viewDetail"
  1214. @click="
  1215. handleMoveUp(scope.$index, '动态表表头', scope.row)
  1216. "
  1217. >
  1218. 上升
  1219. </el-button>
  1220. <el-button
  1221. v-if="
  1222. scope.$index !== contentEditForm.tableHeaders.length - 1
  1223. "
  1224. type="text"
  1225. size="mini"
  1226. :disabled="scope.row.isDisabled || viewDetail"
  1227. @click="handleMoveDown(scope.$index)"
  1228. >
  1229. 下降
  1230. </el-button>
  1231. </div>
  1232. </template>
  1233. </el-table-column>
  1234. </el-table>
  1235. </div>
  1236. <div>
  1237. <div class="button-group">
  1238. <el-button
  1239. v-if="!viewDetail"
  1240. type="primary"
  1241. @click="handleAddTableHeader('动态表项目')"
  1242. >
  1243. 添加项目
  1244. </el-button>
  1245. <el-button
  1246. v-if="!viewDetail"
  1247. type="primary"
  1248. @click="handleSaveContent('动态表项目')"
  1249. >
  1250. 保存
  1251. </el-button>
  1252. </div>
  1253. <div class="table-edit-container">
  1254. <el-table
  1255. :data="contentEditForm.dynamicTable.dynamicTables"
  1256. border
  1257. style="width: 100%"
  1258. row-key="rowid"
  1259. default-expand-all
  1260. :tree-props="{
  1261. children: 'children',
  1262. hasChildren: 'hasChildren',
  1263. }"
  1264. @selection-change="handleSelectionChange"
  1265. >
  1266. <el-table-column label="父子节点" align="center" width="100">
  1267. <template slot-scope="scope">
  1268. <el-tag
  1269. v-if="
  1270. scope.row.isChild ||
  1271. scope.row.isSubItem ||
  1272. (scope.row.parentid &&
  1273. scope.row.parentid != -1 &&
  1274. scope.row.parentid != '-1')
  1275. "
  1276. type="success"
  1277. size="small"
  1278. >
  1279. 子项
  1280. </el-tag>
  1281. <el-tag
  1282. v-else-if="
  1283. scope.row.parentid === -1 ||
  1284. scope.row.parentid === '-1' ||
  1285. !scope.row.parentid
  1286. "
  1287. type="primary"
  1288. size="small"
  1289. >
  1290. 父项
  1291. </el-tag>
  1292. <el-tag v-else type="info" size="small">无</el-tag>
  1293. </template>
  1294. </el-table-column>
  1295. <el-table-column label="序号" width="120" align="center">
  1296. <template slot-scope="scope">
  1297. <div
  1298. style="
  1299. display: flex;
  1300. align-items: center;
  1301. min-height: 32px;
  1302. "
  1303. >
  1304. <el-input
  1305. :value="
  1306. scope.row.dynamicValues
  1307. ? scope.row.dynamicValues['序号']
  1308. : ''
  1309. "
  1310. size="small"
  1311. placeholder="数字或中文"
  1312. :disabled="viewDetail"
  1313. style="flex: 1; margin: 0"
  1314. @input="
  1315. handleDynamicValueChange(scope.row, '序号', $event)
  1316. "
  1317. ></el-input>
  1318. </div>
  1319. </template>
  1320. </el-table-column>
  1321. <el-table-column
  1322. v-for="(item, index) in contentEditForm.dynamicTable
  1323. .dynamicTableHeaders"
  1324. :key="index"
  1325. :label="item.rkey"
  1326. align="center"
  1327. >
  1328. <template slot-scope="scope">
  1329. <el-input
  1330. :value="
  1331. scope.row.dynamicValues
  1332. ? scope.row.dynamicValues[item.rkey]
  1333. : ''
  1334. "
  1335. size="small"
  1336. :disabled="viewDetail"
  1337. @input="
  1338. handleDynamicValueChange(scope.row, item.rkey, $event)
  1339. "
  1340. ></el-input>
  1341. </template>
  1342. </el-table-column>
  1343. <el-table-column
  1344. label="操作"
  1345. align="center"
  1346. fixed="right"
  1347. width="200"
  1348. >
  1349. <template slot-scope="scope">
  1350. <div class="table-actions">
  1351. <el-button
  1352. v-if="!scope.row.isChild"
  1353. type="text"
  1354. size="mini"
  1355. :disabled="viewDetail"
  1356. @click="
  1357. handleAddChildItem(
  1358. scope.$index,
  1359. '动态表项目',
  1360. scope.row
  1361. )
  1362. "
  1363. >
  1364. 添加子项
  1365. </el-button>
  1366. <el-button
  1367. type="text"
  1368. size="mini"
  1369. :disabled="viewDetail"
  1370. class="delete-btn"
  1371. @click="
  1372. handleDeleteHeader(
  1373. scope.$index,
  1374. '动态表项目',
  1375. scope.row
  1376. )
  1377. "
  1378. >
  1379. 删除
  1380. </el-button>
  1381. <el-button
  1382. v-if="scope.$index !== 0"
  1383. type="text"
  1384. size="mini"
  1385. :disabled="viewDetail"
  1386. @click="handleMoveUp(scope.$index, '动态表', scope.row)"
  1387. >
  1388. 上升
  1389. </el-button>
  1390. <el-button
  1391. v-if="
  1392. scope.$index !==
  1393. contentEditForm.tableHeaders.length - 1
  1394. "
  1395. type="text"
  1396. size="mini"
  1397. :disabled="viewDetail"
  1398. @click="
  1399. handleMoveDown(scope.$index, '动态表', scope.row)
  1400. "
  1401. >
  1402. 下降
  1403. </el-button>
  1404. </div>
  1405. </template>
  1406. </el-table-column>
  1407. </el-table>
  1408. </div>
  1409. </div>
  1410. </div>
  1411. </div>
  1412. </el-dialog>
  1413. <el-dialog
  1414. title="计算公式"
  1415. :visible.sync="calculationFormulaDialogVisible"
  1416. width="500px"
  1417. :before-close="handleDialogClose"
  1418. :close-on-click-modal="false"
  1419. >
  1420. <!-- 单选按钮组:切换“当前指标项”/“其他模板指标项” -->
  1421. <el-radio-group
  1422. v-model="radioType"
  1423. class="mb20"
  1424. @change="handleRadioChange"
  1425. >
  1426. <el-radio label="current">当前指标项</el-radio>
  1427. <el-radio label="other">其他模板指标项</el-radio>
  1428. </el-radio-group>
  1429. <!-- 「当前指标项」内容区域 -->
  1430. <div v-if="radioType === 'current'" class="current-panel">
  1431. <el-input
  1432. v-model="formulaText"
  1433. type="textarea"
  1434. rows="4"
  1435. placeholder="请输入公式(如 C1+C2+C3)"
  1436. />
  1437. </div>
  1438. <!-- 「其他模板指标项」内容区域 -->
  1439. <div v-else class="other-panel">
  1440. <span>版本号:</span>
  1441. <el-select
  1442. v-model="selectedTemplateId"
  1443. placeholder="请选择版本号"
  1444. @change="handleTemplateChange"
  1445. >
  1446. <el-option
  1447. v-for="(item, index) in templateList"
  1448. :key="index"
  1449. :label="item.versionNo"
  1450. :value="item.pkVal"
  1451. ></el-option>
  1452. </el-select>
  1453. <!-- 指标表格 -->
  1454. <el-table
  1455. ref="indicatorTable"
  1456. :data="indicatorTableData"
  1457. border
  1458. style="width: 100%; margin-top: 10px"
  1459. @row-click="handleRowClick"
  1460. >
  1461. <el-table-column label="选择" width="60">
  1462. <template #default="scope">
  1463. <el-checkbox
  1464. v-model="scope.row.checked"
  1465. @change="handleCheckboxChange(scope.row)"
  1466. @click.stop
  1467. ></el-checkbox>
  1468. </template>
  1469. </el-table-column>
  1470. <el-table-column
  1471. label="指标编号"
  1472. prop="cellCode"
  1473. align="center"
  1474. ></el-table-column>
  1475. <!--循环表头 -->
  1476. <el-table-column
  1477. v-for="(item, index) in indicatorTableHeaders"
  1478. :key="index"
  1479. :label="item.rkey"
  1480. align="center"
  1481. show-overflow-tooltip
  1482. >
  1483. <template slot-scope="scope">
  1484. {{
  1485. scope.row.fixedValues ? scope.row.fixedValues[item.rkey] : ''
  1486. }}
  1487. </template>
  1488. </el-table-column>
  1489. </el-table>
  1490. <el-input
  1491. v-model="formulaText"
  1492. type="textarea"
  1493. rows="4"
  1494. placeholder="请输入公式(如 C1+C2+C3)"
  1495. @input="handleFormulaTextChange"
  1496. />
  1497. </div>
  1498. <!-- 弹窗底部按钮 -->
  1499. <template #footer>
  1500. <span class="dialog-footer">
  1501. <el-button type="primary" @click="handleConfirm">确定</el-button>
  1502. <el-button @click="calculationFormulaDialogVisible = false">
  1503. 取消
  1504. </el-button>
  1505. </span>
  1506. </template>
  1507. </el-dialog>
  1508. </div>
  1509. </template>
  1510. <script>
  1511. // 导入API模块
  1512. import {
  1513. getCostFormList,
  1514. addCostForm,
  1515. editCostForm,
  1516. deleteCostForm,
  1517. getDataStorageTableOptions,
  1518. } from '@/api/costFormManage'
  1519. import CostAuditTable from '@/components/costAudit/CostAuditTable.vue'
  1520. import { getDictTypList } from '@/api/dictionaryManage.js'
  1521. import {
  1522. listByTemplateIdAndVersion,
  1523. getCellCodesByTemplateId,
  1524. } from '@/api/costSurveyTemplateItems'
  1525. import {
  1526. addSurveyTemplateVersion,
  1527. delSurveyTemplateVersionById,
  1528. putSurveyTemplatePublishVersion,
  1529. getCostSurveyTemplateVersionsByTemplateId,
  1530. batchDeleteCostForm,
  1531. } from '@/api/costSurveyTemplateVersion'
  1532. import { getListFixedEnabled } from '@/api/costSurveyTemplate'
  1533. import { listByCurrentTemplateId } from '@/api/catalogManage.js'
  1534. import {
  1535. getListBySurveyTemplateId,
  1536. getListBySurveyTemplateIdAndVersion,
  1537. getBatchSaveOrUpdate,
  1538. } from '@/api/costSurveyTemplateHeaders'
  1539. import { commonMixin } from '@/mixins/useDict'
  1540. import { mapState } from 'vuex'
  1541. export default {
  1542. name: 'InfoMaintain',
  1543. components: {
  1544. CostAuditTable,
  1545. },
  1546. mixins: [commonMixin],
  1547. data() {
  1548. return {
  1549. surveyTemplateName: '',
  1550. loading: false,
  1551. searchForm: {
  1552. status: '',
  1553. },
  1554. tableData: [],
  1555. currentRow: null,
  1556. selectedRows: [],
  1557. pagination: {
  1558. currentPage: 1,
  1559. pageSize: 50,
  1560. total: 0, // 初始化为0
  1561. },
  1562. dialogVisible: false,
  1563. detailDialogVisible: false,
  1564. viewDetail: false,
  1565. contentEditDialogVisible: false,
  1566. calculationFormulaDialogVisible: false,
  1567. currentEditingRow: null,
  1568. currentEditingRowIndex: -1,
  1569. radioType: 'current',
  1570. formulaText: 'C1+C2+C3',
  1571. templateName: '',
  1572. templateList: [],
  1573. indicatorTableData: [],
  1574. indicatorTableHeaders: [],
  1575. selectedIndicatorCodes: [],
  1576. selectedIndicatorsPerTemplate: {},
  1577. dialogTitle: '',
  1578. dataForm: {
  1579. id: null,
  1580. version: '',
  1581. status: '',
  1582. createBy: '',
  1583. createTime: '',
  1584. remark: '',
  1585. },
  1586. detailForm: {
  1587. id: null,
  1588. version: '',
  1589. status: '',
  1590. createBy: '',
  1591. createTime: '',
  1592. remark: '',
  1593. },
  1594. contentEditForm: {
  1595. tableName: '',
  1596. templateType: '1',
  1597. versionId: '',
  1598. // 单记录列表
  1599. tableHeaders: [],
  1600. // 固定表列表
  1601. fixedTable: {
  1602. tableHeaders: [],
  1603. fixedTables: [],
  1604. fixedTablesTitle: [],
  1605. fixedTableHeaders: [],
  1606. },
  1607. // 动态表列表
  1608. dynamicTable: {
  1609. tableHeaders: [],
  1610. dynamicTables: [],
  1611. dynamicTablesTitle: [],
  1612. dynamicTableHeaders: [],
  1613. },
  1614. isDynamicTables: false,
  1615. isFixedTables: false,
  1616. },
  1617. tableKey: 0, // 用于强制刷新表格
  1618. dataFormRules: {
  1619. status: [
  1620. { required: true, message: '请选择状态', trigger: 'change' },
  1621. ],
  1622. createBy: [
  1623. { required: true, message: '请输入创建人', trigger: 'blur' },
  1624. ],
  1625. createTime: [
  1626. { required: true, message: '请选择创建时间', trigger: 'change' },
  1627. ],
  1628. },
  1629. id: '', // 从路由获取的ID
  1630. dataStorageTableOptions: [], // 数据存储库表选项
  1631. surveyTemplateId: '', // 成本调查表ID
  1632. versionId: '',
  1633. dictTypeList: [],
  1634. }
  1635. },
  1636. computed: {
  1637. ...mapState('user', ['userInfo', 'username']),
  1638. formatter: (status) => {
  1639. return status === '-1' ? '草稿' : status === '0' ? '现行' : '历史'
  1640. },
  1641. tableColumns() {
  1642. return [
  1643. {
  1644. prop: 'versionNo',
  1645. label: '版本号',
  1646. align: 'center',
  1647. showOverflowTooltip: true,
  1648. },
  1649. {
  1650. prop: 'status',
  1651. label: '状态',
  1652. align: 'center',
  1653. formatter: (row) => {
  1654. return row.status == '-1'
  1655. ? '草稿'
  1656. : row.status == '0'
  1657. ? '现行'
  1658. : '历史'
  1659. },
  1660. },
  1661. {
  1662. prop: 'createBy',
  1663. label: '创建人',
  1664. align: 'center',
  1665. },
  1666. {
  1667. prop: 'createTime',
  1668. label: '创建时间',
  1669. showOverflowTooltip: true,
  1670. slotName: 'createTime',
  1671. },
  1672. {
  1673. prop: 'remarks',
  1674. label: '备注',
  1675. align: 'center',
  1676. showOverflowTooltip: true,
  1677. },
  1678. {
  1679. prop: 'action',
  1680. width: '270',
  1681. label: '操作',
  1682. align: 'center',
  1683. fixed: 'right',
  1684. slotName: 'action',
  1685. },
  1686. ]
  1687. },
  1688. },
  1689. watch: {
  1690. indicatorTableData: {
  1691. handler(newVal) {
  1692. if (this.radioType === 'other' && this.selectedTemplateId) {
  1693. this.$set(
  1694. this.selectedIndicatorsPerTemplate,
  1695. this.selectedTemplateId,
  1696. newVal.filter((item) => item.checked)
  1697. )
  1698. }
  1699. this.updateSelectedIndicatorCodes()
  1700. },
  1701. deep: true,
  1702. },
  1703. selectedIndicatorCodes: {
  1704. handler(newVal) {
  1705. if (this.radioType === 'other') {
  1706. const allSelectedTemplateIds = [
  1707. ...new Set([
  1708. this.selectedTemplateId,
  1709. ...Object.keys(this.selectedIndicatorsPerTemplate).filter(
  1710. (id) =>
  1711. id !== this.selectedTemplateId &&
  1712. this.selectedIndicatorsPerTemplate[id].some(
  1713. (item) => item.checked
  1714. )
  1715. ),
  1716. ]),
  1717. ].filter((id) => id)
  1718. const isSingleTemplate = allSelectedTemplateIds.length === 1
  1719. if (isSingleTemplate && allSelectedTemplateIds[0]) {
  1720. const selectedTemplate = this.templateList.find(
  1721. (item) => item.pkVal === allSelectedTemplateIds[0]
  1722. )
  1723. const templateNameYw = selectedTemplate
  1724. ? selectedTemplate.surveyTemplateNameYw ||
  1725. selectedTemplate.surveyTemplateName ||
  1726. ''
  1727. : ''
  1728. let selectedItems = []
  1729. if (allSelectedTemplateIds[0] === this.selectedTemplateId) {
  1730. selectedItems = newVal
  1731. } else {
  1732. selectedItems = this.selectedIndicatorsPerTemplate[
  1733. allSelectedTemplateIds[0]
  1734. ]
  1735. .filter((item) => item.checked)
  1736. .map(
  1737. (item) => `${templateNameYw}.${item.code || item.cellCode}`
  1738. )
  1739. }
  1740. if (selectedItems.length > 0) {
  1741. this.formulaText = selectedItems.join('+')
  1742. this.isAutoGeneratedFormula = true
  1743. } else if (this.isAutoGeneratedFormula) {
  1744. this.formulaText = ''
  1745. }
  1746. } else {
  1747. let allSelectedCodes = []
  1748. if (newVal.length > 0 && this.selectedTemplateId) {
  1749. allSelectedCodes = [...newVal]
  1750. }
  1751. Object.keys(this.selectedIndicatorsPerTemplate).forEach(
  1752. (templateId) => {
  1753. if (templateId !== this.selectedTemplateId) {
  1754. const items = this.selectedIndicatorsPerTemplate[templateId]
  1755. const selectedTemplate = this.templateList.find(
  1756. (item) => item.pkVal === templateId
  1757. )
  1758. const templateName = selectedTemplate
  1759. ? selectedTemplate.surveyTemplateNameYw ||
  1760. selectedTemplate.surveyTemplateName ||
  1761. ''
  1762. : ''
  1763. items
  1764. .filter((item) => item.checked)
  1765. .forEach((item) => {
  1766. allSelectedCodes.push(
  1767. `${templateName}.${item.code || item.cellCode}`
  1768. )
  1769. })
  1770. }
  1771. }
  1772. )
  1773. if (allSelectedCodes.length > 0) {
  1774. this.formulaText = allSelectedCodes.join('+')
  1775. this.isAutoGeneratedFormula = true
  1776. } else if (this.isAutoGeneratedFormula) {
  1777. this.formulaText = ''
  1778. }
  1779. }
  1780. } else if (newVal.length > 0 && this.radioType === 'current') {
  1781. if (
  1782. !this.formulaText ||
  1783. this.formulaText === 'C1+C2+C3' ||
  1784. this.isAutoGeneratedFormula
  1785. ) {
  1786. this.formulaText = newVal.join('+')
  1787. this.isAutoGeneratedFormula = true
  1788. }
  1789. } else if (newVal.length === 0 && this.radioType === 'current') {
  1790. if (this.isAutoGeneratedFormula) {
  1791. this.formulaText = ''
  1792. }
  1793. }
  1794. },
  1795. deep: true,
  1796. },
  1797. },
  1798. mounted() {
  1799. this.isAutoGeneratedFormula = false
  1800. },
  1801. methods: {
  1802. async loadDictTypeList() {
  1803. try {
  1804. const res = await getDictTypList()
  1805. this.dictTypeList = res || []
  1806. } catch (error) {
  1807. console.error('加载字典类型失败:', error)
  1808. }
  1809. },
  1810. getTemplateRow(row) {
  1811. this.currentRow = row
  1812. this.surveyTemplateId = row.surveyTemplateId
  1813. this.templateType = row.templateType
  1814. this.contentEditForm.tableName = row.surveyTemplateName
  1815. this.surveyTemplateName = row.surveyTemplateName
  1816. this.contentEditForm.templateType = row.templateType
  1817. this.handleSearch()
  1818. this.loadDictTypeList()
  1819. },
  1820. handleBack() {
  1821. this.$emit('back', 'list')
  1822. },
  1823. // 查询
  1824. handleSearch() {
  1825. this.loading = true
  1826. const params = {
  1827. surveyTemplateId: this.surveyTemplateId,
  1828. status: this.searchForm.status,
  1829. // pageNum: this.pagination.currentPage,
  1830. // pageSize: this.pagination.pageSize,
  1831. }
  1832. // 根据成本调查表ID获取所有版本数据
  1833. getCostSurveyTemplateVersionsByTemplateId(params)
  1834. .then((response) => {
  1835. this.tableData = response.value || []
  1836. this.pagination.total = response.total || 0
  1837. this.loading = false
  1838. })
  1839. .catch((error) => {
  1840. console.error('查询失败:', error)
  1841. this.loading = false
  1842. })
  1843. },
  1844. // 重置
  1845. handleReset() {
  1846. this.searchForm = {
  1847. status: '',
  1848. }
  1849. this.pagination.currentPage = 1
  1850. this.handleSearch()
  1851. },
  1852. handleRowClick(row, column, event) {
  1853. // 只有点击非 checkbox 列才触发
  1854. if (column && column.property !== 'checked') {
  1855. // 如果没有 cellCode,则不允许选中
  1856. if (!row.cellCode) {
  1857. // this.$message.warning('该数据没有指标编号,无法选择')
  1858. return
  1859. }
  1860. // 切换选中状态
  1861. this.toggleRowSelection(row)
  1862. }
  1863. },
  1864. toggleRowSelection(row) {
  1865. // 切换选中状态
  1866. this.$set(row, 'checked', !row.checked)
  1867. // 格式化代码并存储在行数据中
  1868. if (row.checked) {
  1869. this.formatRowCode(row)
  1870. }
  1871. // 触发选中状态更新
  1872. this.$forceUpdate()
  1873. },
  1874. handleCheckboxChange(row) {
  1875. // 如果没有 cellCode,则不允许选中
  1876. if (!row.cellCode) {
  1877. this.$message.warning('该数据没有指标编号,无法选择')
  1878. this.$set(row, 'checked', false)
  1879. return
  1880. }
  1881. this.$set(row, 'checked', !row.checked)
  1882. if (row.checked) {
  1883. this.formatRowCode(row)
  1884. }
  1885. this.updateSelectedIndicatorCodes()
  1886. this.$forceUpdate()
  1887. },
  1888. updateSelectedIndicatorCodes() {
  1889. // 获取当前选中的行
  1890. const selectedRows = this.indicatorTableData.filter(
  1891. (item) => item.checked
  1892. )
  1893. // 更新选中的指标代码列表
  1894. this.selectedIndicatorCodes = selectedRows.map((item) => {
  1895. // 获取选中的模板信息
  1896. const selectedTemplate = this.templateList.find(
  1897. (template) => template.pkVal === this.selectedTemplateId
  1898. )
  1899. // 获取模板的 surveyTemplateNameYw
  1900. const templateName = selectedTemplate
  1901. ? selectedTemplate.surveyTemplateNameYw ||
  1902. selectedTemplate.surveyTemplateName ||
  1903. ''
  1904. : ''
  1905. return templateName
  1906. ? `${templateName}.${item.code || item.cellCode || ''}`
  1907. : item.code || item.cellCode || ''
  1908. })
  1909. },
  1910. formatRowCode(row) {
  1911. const selectedTemplate = this.templateList.find(
  1912. (item) => item.pkVal === this.selectedTemplateId
  1913. )
  1914. const surveyTemplateNameYw = selectedTemplate
  1915. ? selectedTemplate.surveyTemplateNameYw ||
  1916. selectedTemplate.surveyTemplateName ||
  1917. ''
  1918. : ''
  1919. const formattedCode = surveyTemplateNameYw
  1920. ? `${surveyTemplateNameYw}.${row.code || row.cellCode || ''}`
  1921. : row.code || row.cellCode || ''
  1922. this.$set(row, 'formattedCode', formattedCode)
  1923. const templateCode = surveyTemplateNameYw
  1924. ? `${surveyTemplateNameYw}_${row.code || row.cellCode || ''}`
  1925. : row.code || row.cellCode || ''
  1926. this.$set(
  1927. row,
  1928. 'jsonStr',
  1929. JSON.stringify([
  1930. {
  1931. [templateCode]: this.selectedTemplateId,
  1932. },
  1933. ])
  1934. )
  1935. },
  1936. openCalculationFormulaDialogVisible(row, index) {
  1937. this.currentEditingRow = row
  1938. this.currentEditingRowIndex = index
  1939. this.calculationFormulaDialogVisible = true
  1940. this.formulaText = row.calculationFormula || ''
  1941. this.selectedTemplateId = '' // 重置选中的模板
  1942. this.indicatorTableData = [] // 清空指标数据
  1943. this.getListFixedEnabled()
  1944. },
  1945. getListFixedEnabled() {
  1946. // 修改为调用状态为现行的数据
  1947. const params = {
  1948. surveyTemplateId: this.surveyTemplateId,
  1949. status: '0',
  1950. // pageNum: this.pagination.currentPage,
  1951. // pageSize: this.pagination.pageSize,
  1952. }
  1953. // 根据成本调查表ID获取所有版本数据
  1954. getCostSurveyTemplateVersionsByTemplateId(params)
  1955. .then((response) => {
  1956. this.templateList = response.value || []
  1957. })
  1958. .catch((error) => {
  1959. console.error('查询失败:', error)
  1960. })
  1961. // getListFixedEnabled().then((res) => {
  1962. // this.templateList = res.value
  1963. // })
  1964. },
  1965. // 处理模板选择变化
  1966. handleTemplateChange(templateId) {
  1967. if (templateId) {
  1968. // 根据选中的模板ID查找对应的surveyTemplateId
  1969. const selectedTemplate = this.templateList.find(
  1970. (item) => item.pkVal === templateId
  1971. )
  1972. if (selectedTemplate && selectedTemplate.surveyTemplateId) {
  1973. // this.getCellCodesByTemplateId(selectedTemplate.surveyTemplateId)
  1974. listByCurrentTemplateId({
  1975. surveyTemplateId: selectedTemplate.surveyTemplateId,
  1976. }).then((responseData) => {
  1977. //解析并显示数据
  1978. if (responseData.value && responseData.value.itemlist) {
  1979. const itemList = responseData.value.itemlist
  1980. let fixedTablesTitle = this.stringToObjects(
  1981. responseData.value.fixedFields || ''
  1982. )
  1983. this.indicatorTableHeaders = fixedTablesTitle
  1984. // 遍历itemList,为每个项目创建一行数据
  1985. itemList.forEach((item, index) => {
  1986. const newRow = {
  1987. ...item,
  1988. checked: false,
  1989. cellCode: item.cellCode || '',
  1990. fixedValues: {},
  1991. }
  1992. // 初始化fixedValues并填充实际值
  1993. fixedTablesTitle.forEach((title) => {
  1994. newRow.fixedValues[title.rkey] = item[title.rkey] || ''
  1995. })
  1996. this.indicatorTableData.push(newRow)
  1997. })
  1998. }
  1999. })
  2000. } else {
  2001. this.indicatorTableData = []
  2002. }
  2003. } else {
  2004. this.indicatorTableData = []
  2005. }
  2006. // 恢复该模板之前选中的指标项
  2007. this.$nextTick(() => {
  2008. if (this.selectedIndicatorsPerTemplate[templateId]) {
  2009. this.indicatorTableData.forEach((item) => {
  2010. const isSelected = this.selectedIndicatorsPerTemplate[
  2011. templateId
  2012. ].some((selectedItem) => selectedItem.code === item.code)
  2013. this.$set(item, 'checked', isSelected)
  2014. if (isSelected) {
  2015. this.formatRowCode(item)
  2016. }
  2017. })
  2018. }
  2019. // 更新选中的指标代码列表
  2020. this.updateSelectedIndicatorCodes()
  2021. })
  2022. },
  2023. handleDialogClose(done) {
  2024. this.selectedIndicatorsPerTemplate = {}
  2025. done()
  2026. },
  2027. handleRadioChange(value) {
  2028. this.formulaText = ''
  2029. },
  2030. handleConfirm() {
  2031. const result = {
  2032. type: this.radioType,
  2033. formula: this.formulaText,
  2034. selectedTemplate: this.selectedTemplateId,
  2035. selectedItems: this.indicatorTableData.filter((item) => item.checked),
  2036. }
  2037. let _data = []
  2038. if (this.radioType == 'current') {
  2039. // 使用递归函数扁平化树形结构
  2040. const flattenTree = (nodes) => {
  2041. let result = []
  2042. nodes.forEach((node) => {
  2043. result.push(node)
  2044. if (node.children && node.children.length > 0) {
  2045. result = result.concat(flattenTree(node.children))
  2046. }
  2047. })
  2048. return result
  2049. }
  2050. // 扁平化数据并提取cellCode
  2051. _data = flattenTree(this.contentEditForm.fixedTable.fixedTables)
  2052. .filter((item) => item.cellCode)
  2053. .map((item) => item.cellCode)
  2054. } else if (this.radioType == 'other') {
  2055. if (!result.selectedTemplate) {
  2056. this.$message.error('请选择指标编号')
  2057. return
  2058. }
  2059. _data = this.indicatorTableData
  2060. .filter((item) => item.cellCode)
  2061. .map((item) => item.cellCode)
  2062. }
  2063. if (!this.validateFormula(this.formulaText, _data).valid) {
  2064. this.$message.error(
  2065. this.validateFormula(this.formulaText, _data).errorMsg
  2066. )
  2067. return
  2068. }
  2069. // 生成 jsonstr 字段
  2070. const jsonStrArray = this.indicatorTableData
  2071. .filter((item) => item.checked)
  2072. .map((item) => {
  2073. if (item.jsonStr) {
  2074. try {
  2075. return JSON.parse(item.jsonStr)[0]
  2076. } catch (e) {
  2077. console.error('解析 jsonStr 失败:', e)
  2078. return {}
  2079. }
  2080. }
  2081. return {}
  2082. })
  2083. .filter((item) => Object.keys(item).length > 0)
  2084. const jsonstr = JSON.stringify(jsonStrArray)
  2085. // 更新当前编辑行的计算公式值
  2086. if (this.currentEditingRow) {
  2087. this.$set(
  2088. this.currentEditingRow,
  2089. 'calculationFormula',
  2090. this.formulaText
  2091. )
  2092. this.$set(this.currentEditingRow, 'jsonstr', jsonstr)
  2093. }
  2094. console.log('点击了确定,获取到的数据:', {
  2095. ...result,
  2096. jsonstr: jsonstr,
  2097. })
  2098. // 清空当前操作的状态
  2099. this.calculationFormulaDialogVisible = false
  2100. this.currentEditingRow = null
  2101. this.currentEditingRowIndex = -1
  2102. this.isAutoGeneratedFormula = false
  2103. this.selectedTemplateId = ''
  2104. this.indicatorTableData = []
  2105. this.selectedIndicatorsPerTemplate = {} // 清空模板选中记录
  2106. },
  2107. // 获取单元格代码
  2108. getCellCodesByTemplateId(surveyTemplateId) {
  2109. getCellCodesByTemplateId(surveyTemplateId)
  2110. .then((res) => {
  2111. // 将返回的数据转换为表格需要的格式
  2112. if (res.value && Array.isArray(res.value)) {
  2113. this.indicatorTableData = res.value.map((item) => ({
  2114. ...item,
  2115. checked: false,
  2116. code: item.cellCode || '',
  2117. name: item.rvalue || '',
  2118. formattedCode: '', // 添加格式化代码字段
  2119. }))
  2120. } else {
  2121. this.indicatorTableData = []
  2122. }
  2123. })
  2124. .catch((error) => {
  2125. console.error('获取指标数据失败:', error)
  2126. this.$message.error('获取指标数据失败')
  2127. this.indicatorTableData = []
  2128. })
  2129. },
  2130. handleFormulaTextChange(value) {
  2131. // 当用户手动修改公式文本时,标记为非自动生成
  2132. this.isAutoGeneratedFormula = false
  2133. },
  2134. handleAdd() {
  2135. this.dialogTitle = '添加'
  2136. // 获取当前时间
  2137. const now = new Date()
  2138. // 格式化时间为YYYY-MM-DD HH:mm:ss
  2139. const formattedDate = `${now.getFullYear()}-${String(
  2140. now.getMonth() + 1
  2141. ).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')} ${String(
  2142. now.getHours()
  2143. ).padStart(2, '0')}:${String(now.getMinutes()).padStart(
  2144. 2,
  2145. '0'
  2146. )}:${String(now.getSeconds()).padStart(2, '0')}`
  2147. this.dataForm = {
  2148. id: null,
  2149. version: '',
  2150. status: '',
  2151. createBy: this.username,
  2152. createTime: formattedDate,
  2153. remarks: '',
  2154. }
  2155. this.dialogVisible = true
  2156. },
  2157. // 修改
  2158. handleEdit(row) {
  2159. this.dialogTitle = '修改'
  2160. this.dataForm = { ...row }
  2161. this.dialogVisible = true
  2162. },
  2163. //状态格式化
  2164. forStatus(status) {
  2165. return status === '-1' ? '草稿' : status === '0' ? '现行' : '历史'
  2166. },
  2167. // 查看详情
  2168. handleViewDetail(row) {
  2169. this.viewDetail = true
  2170. this.detailForm = { ...row }
  2171. // this.detailDialogVisible = true
  2172. this.handleEditContent(row, this.viewDetail)
  2173. },
  2174. // 添加子项方法
  2175. handleAddChildItem(index, type, parentRow) {
  2176. if (!parentRow.rowid) {
  2177. this.$set(parentRow, 'rowid', this.generateUUID())
  2178. }
  2179. switch (type) {
  2180. case '固定表项目':
  2181. let parentIndex1 =
  2182. this.contentEditForm.fixedTable.fixedTables.findIndex(
  2183. (item) => item.rowid == parentRow.rowid
  2184. )
  2185. if (
  2186. !this.contentEditForm.fixedTable.fixedTables[parentIndex1]
  2187. .children
  2188. ) {
  2189. this.$set(
  2190. this.contentEditForm.fixedTable.fixedTables[parentIndex1],
  2191. 'children',
  2192. []
  2193. )
  2194. }
  2195. let childOrderNum =
  2196. this.contentEditForm.fixedTable.fixedTables[parentIndex1].children
  2197. .length + 1
  2198. let fixedValues = {
  2199. ...parentRow.fixedValues,
  2200. }
  2201. for (const key in fixedValues) {
  2202. if (key == '序号') {
  2203. fixedValues[key] = childOrderNum
  2204. } else {
  2205. fixedValues[key] = ''
  2206. }
  2207. }
  2208. const fixedNewRow = {
  2209. orderText: this.contentEditForm.fixedTable.fixedTables.length + 1,
  2210. orderNum: this.contentEditForm.fixedTable.fixedTables.length + 1,
  2211. cellCode: '',
  2212. calculationFormula: '',
  2213. unit: '',
  2214. tabtype: this.templateType,
  2215. surveyTemplateId: this.surveyTemplateId,
  2216. versionId: this.versionId,
  2217. fixedValues: fixedValues,
  2218. parentid: parentRow.rowid,
  2219. isChild: true,
  2220. isSubItem: true,
  2221. rowid: this.generateUUID(),
  2222. }
  2223. this.contentEditForm.fixedTable.fixedTablesTitle.forEach(
  2224. (title) => {
  2225. if (!(title.rkey in fixedNewRow.fixedValues)) {
  2226. fixedNewRow.fixedValues[title.rkey] = ''
  2227. }
  2228. }
  2229. )
  2230. // 先将子项添加到children数组
  2231. this.contentEditForm.fixedTable.fixedTables[
  2232. parentIndex1
  2233. ].children.push(fixedNewRow)
  2234. // this.contentEditForm.fixedTable.fixedTables.splice(
  2235. // index + 1,
  2236. // 0,
  2237. // fixedNewRow
  2238. // )
  2239. break
  2240. case '动态表项目':
  2241. let parentIndex2 =
  2242. this.contentEditForm.dynamicTable.dynamicTables.findIndex(
  2243. (item) => item.rowid == parentRow.rowid
  2244. )
  2245. if (
  2246. !this.contentEditForm.dynamicTable.dynamicTables[parentIndex2]
  2247. .children
  2248. ) {
  2249. this.$set(
  2250. this.contentEditForm.dynamicTable.dynamicTables[parentIndex2],
  2251. 'children',
  2252. []
  2253. )
  2254. }
  2255. let dynamicChildOrderNum =
  2256. this.contentEditForm.dynamicTable.dynamicTables[parentIndex2]
  2257. .children.length + 1
  2258. let dynamicValues = { ...parentRow.dynamicValues }
  2259. for (const key in dynamicValues) {
  2260. if (key == '序号') {
  2261. dynamicValues[key] = dynamicChildOrderNum
  2262. } else {
  2263. dynamicValues[key] = ''
  2264. }
  2265. }
  2266. const dynamicNewRow = {
  2267. orderText: dynamicChildOrderNum,
  2268. orderNum: dynamicChildOrderNum,
  2269. tabtype: this.templateType,
  2270. surveyTemplateId: this.surveyTemplateId,
  2271. versionId: this.versionId,
  2272. dynamicValues: dynamicValues,
  2273. parentid: parentRow.rowid,
  2274. isChild: true,
  2275. isSubItem: true,
  2276. rowid: Date.now() + Math.random() + 1,
  2277. }
  2278. this.contentEditForm.dynamicTable.dynamicTablesTitle.forEach(
  2279. (title) => {
  2280. if (!(title.rkey in dynamicNewRow.dynamicValues)) {
  2281. dynamicNewRow.dynamicValues[title.rkey] = ''
  2282. }
  2283. }
  2284. )
  2285. this.contentEditForm.dynamicTable.dynamicTables[
  2286. parentIndex2
  2287. ].children.push(dynamicNewRow)
  2288. // this.contentEditForm.dynamicTable.dynamicTables.splice(
  2289. // index + 1,
  2290. // 0,
  2291. // dynamicNewRow
  2292. // )
  2293. break
  2294. }
  2295. this.$nextTick(() => {
  2296. const tableBody = document.querySelector('.el-table__body-wrapper')
  2297. if (tableBody) {
  2298. tableBody.scrollTop = tableBody.scrollHeight
  2299. }
  2300. })
  2301. },
  2302. handleFormStyleChange() {},
  2303. getListBySurveyTemplateIdAndVersion(surveyTemplateId, versionId) {
  2304. return getListBySurveyTemplateIdAndVersion({
  2305. surveyTemplateId: surveyTemplateId,
  2306. versionId: versionId,
  2307. })
  2308. .then((res) => {
  2309. // 确保表头数据包含所有必要的字段,包括 id
  2310. this.contentEditForm.tableHeaders =
  2311. res.value.map((item) => ({
  2312. ...item,
  2313. fieldKey: item.fieldEname
  2314. ? item.fieldEname.toLowerCase()
  2315. : `field_${Date.now()}_${Math.random()
  2316. .toString(36)
  2317. .substr(2, 9)}`,
  2318. })) || []
  2319. // 检查并添加序号字段(固定表和动态表需要)
  2320. if (['2', '3'].includes(this.contentEditForm.templateType)) {
  2321. const hasSerialNumber = this.contentEditForm.tableHeaders.some(
  2322. (item) => item.fieldName === '序号'
  2323. )
  2324. if (!hasSerialNumber) {
  2325. this.contentEditForm.tableHeaders.unshift({
  2326. fieldName: '序号',
  2327. fieldType: 'string',
  2328. format: '255',
  2329. fieldTypelen: '',
  2330. fieldTypenointlen: '',
  2331. isRequired: 'false',
  2332. showVisible: '1',
  2333. isAuditPeriod: 'false',
  2334. tabtype: this.templateType,
  2335. surveyTemplateId: this.surveyTemplateId,
  2336. versionId: this.versionId,
  2337. isDisabled: true,
  2338. orderNum: 1,
  2339. })
  2340. } else {
  2341. // 如果已存在序号字段,确保其不可编辑
  2342. const serialNumberIndex =
  2343. this.contentEditForm.tableHeaders.findIndex(
  2344. (item) => item.fieldName === '序号'
  2345. )
  2346. if (serialNumberIndex !== -1) {
  2347. this.contentEditForm.tableHeaders[
  2348. serialNumberIndex
  2349. ].isDisabled = true
  2350. }
  2351. }
  2352. }
  2353. this.contentEditForm.dynamicTable.tableHeaders =
  2354. this.contentEditForm.tableHeaders
  2355. this.contentEditForm.fixedTable.tableHeaders =
  2356. this.contentEditForm.tableHeaders
  2357. // 表头按照orderNum重新排序
  2358. this.contentEditForm.tableHeaders.sort(
  2359. (a, b) => a.orderNum - b.orderNum
  2360. )
  2361. this.contentEditForm.dynamicTable.tableHeaders.sort(
  2362. (a, b) => a.orderNum - b.orderNum
  2363. )
  2364. this.contentEditForm.fixedTable.tableHeaders.sort(
  2365. (a, b) => a.orderNum - b.orderNum
  2366. )
  2367. // 同时获取表头标题信息
  2368. listByTemplateIdAndVersion(surveyTemplateId, versionId)
  2369. .then((response) => {
  2370. if (response.code === 200) {
  2371. if (this.contentEditForm.templateType === '2') {
  2372. this.contentEditForm.fixedTable.fixedTablesTitle =
  2373. this.stringToObjects(response.value.fixedFields || '')
  2374. } else if (this.contentEditForm.templateType === '3') {
  2375. this.contentEditForm.dynamicTable.dynamicTablesTitle =
  2376. this.stringToObjects(response.value.fixedFields || '')
  2377. }
  2378. }
  2379. return response
  2380. })
  2381. .catch((error) => {
  2382. console.error('获取表头标题信息失败:', error)
  2383. throw error
  2384. })
  2385. })
  2386. .catch((error) => {
  2387. console.error('查询失败:', error)
  2388. this.loading = false
  2389. throw error
  2390. })
  2391. },
  2392. initFixedTableRow(row) {
  2393. if (row.cellCode === undefined) {
  2394. this.$set(row, 'cellCode', '')
  2395. }
  2396. if (row.calculationFormula === undefined) {
  2397. this.$set(row, 'calculationFormula', '')
  2398. }
  2399. if (row.unit === undefined) {
  2400. this.$set(row, 'unit', '')
  2401. }
  2402. if (!row.fixedValues) {
  2403. this.$set(row, 'fixedValues', {})
  2404. }
  2405. this.contentEditForm.fixedTable.fixedTablesTitle.forEach(
  2406. (title, index) => {
  2407. if (!(title.rkey in row.fixedValues)) {
  2408. this.$set(row.fixedValues, title.rkey, '')
  2409. }
  2410. }
  2411. )
  2412. return row
  2413. },
  2414. initDynamicTableRow(row) {
  2415. // 为当前行创建一个与 dynamicTablesTitle 对应的值对象
  2416. if (!row.dynamicValues) {
  2417. this.$set(row, 'dynamicValues', {})
  2418. }
  2419. // 确保每个动态列在当前行都有对应的值
  2420. this.contentEditForm.dynamicTable.dynamicTablesTitle.forEach(
  2421. (title) => {
  2422. if (!(title.rkey in row.dynamicValues)) {
  2423. this.$set(row.dynamicValues, title.rkey, '')
  2424. }
  2425. }
  2426. )
  2427. return row
  2428. },
  2429. /**
  2430. * 处理固定表项目字段值变化
  2431. */
  2432. handleFixedValueChange(row, rkey, value) {
  2433. if (!row.fixedValues) {
  2434. this.$set(row, 'fixedValues', {})
  2435. }
  2436. this.$set(row.fixedValues, rkey, value)
  2437. },
  2438. // 获取或设置序号字段
  2439. getOrSetOrder(row, value) {
  2440. // 如果提供了value参数,则设置值
  2441. if (value !== undefined) {
  2442. // 使用this.$set确保响应式更新
  2443. if (row['序号'] === undefined) {
  2444. this.$set(row, '序号', value)
  2445. } else {
  2446. row['序号'] = value
  2447. }
  2448. }
  2449. // 如果没有提供value参数,则获取值
  2450. return row['序号'] !== undefined && row['序号'] !== null
  2451. ? row['序号']
  2452. : row.orderNum || ''
  2453. },
  2454. /**
  2455. * 处理动态表项目字段值变化
  2456. */
  2457. handleDynamicValueChange(row, rkey, value) {
  2458. if (!row.dynamicValues) {
  2459. this.$set(row, 'dynamicValues', {})
  2460. }
  2461. this.$set(row.dynamicValues, rkey, value)
  2462. },
  2463. // 内容维护
  2464. handleEditContent(row, viewDetail) {
  2465. this.viewDetail = viewDetail || false
  2466. this.versionId = row.id
  2467. // 显示加载状态
  2468. this.loading = true
  2469. // 获取所有需要的数据
  2470. this.getListBySurveyTemplateIdAndVersion(row.surveyTemplateId, row.id)
  2471. .then(() => {
  2472. // 获取项目数据用于回显
  2473. return listByTemplateIdAndVersion(row.surveyTemplateId, row.id)
  2474. })
  2475. .then((res) => {
  2476. if (res.code === 200) {
  2477. // 根据模板类型解析并显示数据
  2478. if (this.contentEditForm.templateType === '2') {
  2479. // 解析并显示固定表项目数据
  2480. setTimeout(() => {
  2481. this.parseAndDisplayFixedTableData(res)
  2482. }, 1000)
  2483. } else if (this.contentEditForm.templateType === '3') {
  2484. // 解析并显示动态表项目数据
  2485. setTimeout(() => {
  2486. this.parseAndDisplayDynamicTableData(res)
  2487. }, 1000)
  2488. }
  2489. }
  2490. this.loading = false
  2491. this.contentEditDialogVisible = true
  2492. })
  2493. .catch((error) => {
  2494. console.error('获取数据失败:', error)
  2495. // this.$message.error('获取数据失败')
  2496. this.contentEditDialogVisible = true
  2497. this.loading = false
  2498. })
  2499. },
  2500. // 字段类型变化处理
  2501. handleFieldTypeChange(row) {
  2502. // 重置格式相关字段
  2503. row.format = ''
  2504. row.integerDigits = ''
  2505. row.decimalDigits = ''
  2506. },
  2507. // 添加表头
  2508. handleAddTableHeader(type) {
  2509. switch (type) {
  2510. case '单记录':
  2511. this.contentEditForm.tableHeaders.push({
  2512. fieldName: '',
  2513. fieldType: 'string',
  2514. format: '255',
  2515. fieldTypelen: '',
  2516. fieldTypenointlen: '',
  2517. isRequired: 'false',
  2518. showVisible: '1',
  2519. isDict: 'false',
  2520. dictid: '',
  2521. dictValue: '',
  2522. tabtype: this.templateType,
  2523. surveyTemplateId: this.surveyTemplateId,
  2524. versionId: this.versionId,
  2525. orderNum: this.contentEditForm.tableHeaders.length + 1,
  2526. })
  2527. break
  2528. case '固定表表头':
  2529. this.contentEditForm.fixedTable.tableHeaders.push({
  2530. fieldName: '',
  2531. fieldType: 'string',
  2532. format: '255',
  2533. fieldTypelen: '',
  2534. fieldTypenointlen: '',
  2535. isRequired: 'false',
  2536. showVisible: '1',
  2537. isAuditPeriod: 'false',
  2538. tabtype: this.templateType,
  2539. surveyTemplateId: this.surveyTemplateId,
  2540. versionId: this.versionId,
  2541. orderNum: this.contentEditForm.fixedTable.tableHeaders.length + 1,
  2542. })
  2543. // 确保添加后顺序正确
  2544. this.updateTableHeadersOrderNumbers()
  2545. break
  2546. case '固定表项目':
  2547. let maxFixedOrderNum = 0
  2548. if (this.contentEditForm.fixedTable.fixedTables.length > 0) {
  2549. maxFixedOrderNum = Math.max(
  2550. ...this.contentEditForm.fixedTable.fixedTables.map(
  2551. (item) => item.orderNum || 0
  2552. )
  2553. )
  2554. }
  2555. const newRow = {
  2556. orderText: maxFixedOrderNum + 1,
  2557. orderNum: maxFixedOrderNum + 1,
  2558. cellCode: '',
  2559. calculationFormula: '',
  2560. unit: '',
  2561. tabtype: this.templateType,
  2562. surveyTemplateId: this.surveyTemplateId,
  2563. versionId: this.versionId,
  2564. fixedValues: {},
  2565. parentid: -1,
  2566. rowid: this.generateUUID(),
  2567. children: [],
  2568. }
  2569. this.contentEditForm.fixedTable.fixedTablesTitle.forEach(
  2570. (title) => {
  2571. newRow.fixedValues[title.rkey] = ''
  2572. }
  2573. )
  2574. this.contentEditForm.fixedTable.fixedTables.push(newRow)
  2575. break
  2576. case '动态表表头':
  2577. this.contentEditForm.dynamicTable.tableHeaders.push({
  2578. fieldName: '',
  2579. fieldType: 'string',
  2580. format: '255',
  2581. fieldTypelen: '',
  2582. fieldTypenointlen: '',
  2583. isRequired: 'false',
  2584. showVisible: '1',
  2585. tabtype: this.templateType,
  2586. surveyTemplateId: this.surveyTemplateId,
  2587. versionId: this.versionId,
  2588. orderNum:
  2589. this.contentEditForm.dynamicTable.tableHeaders.length + 1,
  2590. })
  2591. break
  2592. case '动态表项目':
  2593. let maxDynamicOrderNum = 0
  2594. if (this.contentEditForm.dynamicTable.dynamicTables.length > 0) {
  2595. maxDynamicOrderNum = Math.max(
  2596. ...this.contentEditForm.dynamicTable.dynamicTables.map(
  2597. (item) => item.orderNum || 0
  2598. )
  2599. )
  2600. }
  2601. const dynamicRow = {
  2602. orderText: maxDynamicOrderNum + 1,
  2603. orderNum: maxDynamicOrderNum + 1,
  2604. tabtype: this.templateType,
  2605. surveyTemplateId: this.surveyTemplateId,
  2606. versionId: this.versionId,
  2607. dynamicValues: {},
  2608. parentid: -1,
  2609. rowid: this.generateUUID(),
  2610. children: [],
  2611. }
  2612. this.contentEditForm.dynamicTable.dynamicTablesTitle.forEach(
  2613. (title) => {
  2614. dynamicRow.dynamicValues[title.rkey] = ''
  2615. }
  2616. )
  2617. this.contentEditForm.dynamicTable.dynamicTables.push(dynamicRow)
  2618. break
  2619. default:
  2620. break
  2621. }
  2622. this.$nextTick(() => {
  2623. const tableBody = document.querySelector('.el-table__body-wrapper')
  2624. if (tableBody) {
  2625. tableBody.scrollTop = tableBody.scrollHeight
  2626. }
  2627. })
  2628. },
  2629. // 删除表头
  2630. handleDeleteHeader(index, type, row) {
  2631. const handleDelete = () => {
  2632. const data = {
  2633. deleteheadersList: [row],
  2634. }
  2635. getBatchSaveOrUpdate(data)
  2636. .then((res) => {
  2637. if (res.code === 200) {
  2638. this.$message.success('删除成功')
  2639. } else {
  2640. this.$message.error(`删除失败:${res.message || '未知错误'}`)
  2641. }
  2642. })
  2643. .catch((error) => {
  2644. console.error('删除接口异常:', error)
  2645. // this.$message.error('删除接口异常,请重试')
  2646. })
  2647. .finally(() => {})
  2648. }
  2649. switch (type) {
  2650. case '固定表表头':
  2651. if (this.contentEditForm.fixedTable.tableHeaders.length <= 1) {
  2652. this.$message.warning('至少保留一个表头')
  2653. return
  2654. }
  2655. this.contentEditForm.fixedTable.tableHeaders.splice(index, 1)
  2656. let fixedFields = this.contentEditForm.fixedTable.tableHeaders
  2657. .map((item) => item.fieldName)
  2658. .join(',')
  2659. this.contentEditForm.fixedTable.fixedTablesTitle =
  2660. this.stringToObjects(fixedFields || '')
  2661. this.contentEditForm.fixedTable.fixedTableHeaders =
  2662. this.contentEditForm.fixedTable.fixedTablesTitle.filter(
  2663. (title) => title.rkey !== '序号'
  2664. )
  2665. handleDelete()
  2666. // 重新排序
  2667. this.updateTableHeadersOrderNumbers()
  2668. break
  2669. case '固定表项目':
  2670. this.$confirm(
  2671. '确定要删除此行数据吗?如果删除的是父项,将同时删除其所有子项。',
  2672. '确认删除',
  2673. {
  2674. confirmButtonText: '确定',
  2675. cancelButtonText: '取消',
  2676. type: 'warning',
  2677. }
  2678. )
  2679. .then(() => {
  2680. // 检查是否是删除子项
  2681. const isChildItem = row.isChild || row.isSubItem || false
  2682. console.log('isChildItem', isChildItem)
  2683. console.log('row', row)
  2684. if (isChildItem) {
  2685. // 查找父项
  2686. const parentItem =
  2687. this.contentEditForm.fixedTable.fixedTables.find(
  2688. (item) =>
  2689. item.children &&
  2690. item.children.some((child) => child.rowid === row.rowid)
  2691. )
  2692. if (parentItem && parentItem.children) {
  2693. // 从父项的children数组中删除子项
  2694. const childIndex = parentItem.children.findIndex(
  2695. (child) => child.rowid === row.rowid
  2696. )
  2697. if (childIndex > -1) {
  2698. parentItem.children.splice(childIndex, 1)
  2699. // 如果children数组为空,将hasChildren设为false
  2700. if (parentItem.children.length === 0) {
  2701. this.$set(parentItem, 'hasChildren', false)
  2702. } else {
  2703. // 重新计算子项序号
  2704. parentItem.children.forEach((child, idx) => {
  2705. child.orderText = idx + 1
  2706. child.orderNum = idx + 1
  2707. })
  2708. }
  2709. // 确保Vue响应式系统检测到变化
  2710. const children = [...parentItem.children]
  2711. this.$set(parentItem, 'children', children)
  2712. this.handleSaveContent('固定表项目', 'delete') // 保存数据
  2713. }
  2714. }
  2715. } else {
  2716. // 处理删除父项的情况
  2717. if (this.contentEditForm.fixedTable.fixedTables.length <= 1) {
  2718. this.$message.warning('至少保留一个项目')
  2719. return
  2720. }
  2721. // 获取要删除的行
  2722. index =
  2723. this.contentEditForm.fixedTable.fixedTables.indexOf(row)
  2724. const rowToDelete =
  2725. this.contentEditForm.fixedTable.fixedTables[index]
  2726. // 先删除所有子项(parentid等于当前行的rowid或itemId的项)
  2727. // 从后往前删除,避免索引偏移
  2728. const rowsToDelete = []
  2729. // 找出所有需要删除的行(包括父项和子项)
  2730. for (
  2731. let i = 0;
  2732. i < this.contentEditForm.fixedTable.fixedTables.length;
  2733. i++
  2734. ) {
  2735. const currentRow =
  2736. this.contentEditForm.fixedTable.fixedTables[i]
  2737. // 是当前行或其子项(子项的parentid等于当前行的rowid或itemId)
  2738. if (
  2739. i === index ||
  2740. (currentRow.parentid &&
  2741. (currentRow.parentid === rowToDelete.rowid ||
  2742. currentRow.parentid === rowToDelete.itemId))
  2743. ) {
  2744. rowsToDelete.push(i)
  2745. }
  2746. }
  2747. // 从后往前删除,避免索引偏移
  2748. for (let i = rowsToDelete.length - 1; i >= 0; i--) {
  2749. this.contentEditForm.fixedTable.fixedTables.splice(
  2750. rowsToDelete[i],
  2751. 1
  2752. )
  2753. }
  2754. this.handleSaveContent('固定表项目', 'delete') // 保存数据
  2755. }
  2756. })
  2757. .catch(() => {})
  2758. break
  2759. case '动态表表头':
  2760. if (this.contentEditForm.dynamicTable.tableHeaders.length <= 1) {
  2761. this.$message.warning('至少保留一个表头')
  2762. return
  2763. }
  2764. this.contentEditForm.dynamicTable.tableHeaders.splice(index, 1)
  2765. let dynamicFields = this.contentEditForm.dynamicTable.tableHeaders
  2766. .map((item) => item.fieldName)
  2767. .join(',')
  2768. this.contentEditForm.dynamicTable.dynamicTablesTitle =
  2769. this.stringToObjects(dynamicFields || '')
  2770. this.contentEditForm.dynamicTable.dynamicTableHeaders =
  2771. this.contentEditForm.dynamicTable.dynamicTablesTitle.filter(
  2772. (title) => title.rkey !== '序号'
  2773. )
  2774. handleDelete()
  2775. // 重新排序
  2776. this.updateTableHeadersOrderNumbers()
  2777. break
  2778. case '动态表项目':
  2779. if (this.contentEditForm.dynamicTable.dynamicTables.length <= 1) {
  2780. this.$message.warning('至少保留一个项目')
  2781. return
  2782. }
  2783. this.$confirm(
  2784. '确定要删除此行数据吗?如果删除的是父项,将同时删除其所有子项。',
  2785. '确认删除',
  2786. {
  2787. confirmButtonText: '确定',
  2788. cancelButtonText: '取消',
  2789. type: 'warning',
  2790. }
  2791. )
  2792. .then(() => {
  2793. // 检查是否是删除子项
  2794. const isChildItem = row.isChild || row.isSubItem || false
  2795. if (isChildItem) {
  2796. // 查找父项
  2797. const parentItem =
  2798. this.contentEditForm.dynamicTable.dynamicTables.find(
  2799. (item) =>
  2800. item.children &&
  2801. item.children.some((child) => child.rowid === row.rowid)
  2802. )
  2803. if (parentItem && parentItem.children) {
  2804. // 从父项的children数组中删除子项
  2805. const childIndex = parentItem.children.findIndex(
  2806. (child) => child.rowid === row.rowid
  2807. )
  2808. if (childIndex > -1) {
  2809. parentItem.children.splice(childIndex, 1)
  2810. // 如果children数组为空,将hasChildren设为false
  2811. if (parentItem.children.length === 0) {
  2812. this.$set(parentItem, 'hasChildren', false)
  2813. } else {
  2814. // 重新计算子项序号
  2815. parentItem.children.forEach((child, idx) => {
  2816. child.orderText = idx + 1
  2817. child.orderNum = idx + 1
  2818. })
  2819. }
  2820. // 确保Vue响应式系统检测到变化
  2821. const children = [...parentItem.children]
  2822. this.$set(parentItem, 'children', children)
  2823. this.handleSaveContent('动态表项目', 'delete') // 保存数据
  2824. }
  2825. }
  2826. } else {
  2827. // 处理删除父项的情况
  2828. if (
  2829. this.contentEditForm.dynamicTable.dynamicTables.length <= 1
  2830. ) {
  2831. this.$message.warning('至少保留一个项目')
  2832. return
  2833. }
  2834. // 获取要删除的行
  2835. index =
  2836. this.contentEditForm.dynamicTable.dynamicTables.indexOf(row)
  2837. const rowToDelete =
  2838. this.contentEditForm.dynamicTable.dynamicTables[index]
  2839. // 先删除所有子项(parentid等于当前行的rowid或itemId的项)
  2840. // 从后往前删除,避免索引偏移
  2841. const rowsToDelete = []
  2842. // 找出所有需要删除的行(包括父项和子项)
  2843. for (
  2844. let i = 0;
  2845. i < this.contentEditForm.dynamicTable.dynamicTables.length;
  2846. i++
  2847. ) {
  2848. const currentRow =
  2849. this.contentEditForm.dynamicTable.dynamicTables[i]
  2850. // 是当前行或其子项(子项的parentid等于当前行的rowid或itemId)
  2851. if (
  2852. i === index ||
  2853. (currentRow.parentid &&
  2854. (currentRow.parentid === rowToDelete.rowid ||
  2855. currentRow.parentid === rowToDelete.itemId))
  2856. ) {
  2857. rowsToDelete.push(i)
  2858. }
  2859. }
  2860. // 从后往前删除,避免索引偏移
  2861. for (let i = rowsToDelete.length - 1; i >= 0; i--) {
  2862. this.contentEditForm.dynamicTable.dynamicTables.splice(
  2863. rowsToDelete[i],
  2864. 1
  2865. )
  2866. }
  2867. this.handleSaveContent('动态表项目', 'delete') // 保存数据
  2868. }
  2869. })
  2870. .catch(() => {})
  2871. break
  2872. case '单记录':
  2873. if (this.contentEditForm.tableHeaders.length <= 1) {
  2874. this.$message.warning('至少保留一个表头')
  2875. return
  2876. }
  2877. this.contentEditForm.tableHeaders.splice(index, 1)
  2878. handleDelete()
  2879. break
  2880. default:
  2881. break
  2882. }
  2883. },
  2884. // 上升
  2885. handleMoveUp(index, tableType, row) {
  2886. if (tableType === '固定表') {
  2887. const fixedTableData = this.contentEditForm.fixedTable.fixedTables
  2888. const newFixedTableData = [...fixedTableData]
  2889. this.swamTableArr(newFixedTableData, row, true)
  2890. this.contentEditForm.fixedTable.fixedTables = newFixedTableData
  2891. } else if (tableType === '动态表') {
  2892. const dynamicTableData =
  2893. this.contentEditForm.dynamicTable.dynamicTables
  2894. const newDynamicTableData = [...dynamicTableData]
  2895. this.swamTableArr(newDynamicTableData, row, true)
  2896. this.contentEditForm.dynamicTable.dynamicTables = newDynamicTableData
  2897. } else {
  2898. // const tableHeaders = this.contentEditForm.tableHeaders
  2899. // const newTableHeaders = [...tableHeaders]
  2900. // this.swamTableArr(newTableHeaders, row, true, true)
  2901. // this.contentEditForm.tableHeaders = newTableHeaders
  2902. // console.log('newTableHeaders', newTableHeaders)
  2903. if (index > 0) {
  2904. const temp = this.contentEditForm.tableHeaders[index]
  2905. this.contentEditForm.tableHeaders.splice(index, 1)
  2906. this.contentEditForm.tableHeaders.splice(index - 1, 0, temp)
  2907. // 更新表头的序号
  2908. this.updateTableHeadersOrderNumbers()
  2909. }
  2910. }
  2911. },
  2912. // 下降
  2913. handleMoveDown(index, tableType, row) {
  2914. if (tableType === '固定表') {
  2915. const fixedTableData = this.contentEditForm.fixedTable.fixedTables
  2916. const newFixedTableData = [...fixedTableData]
  2917. this.swamTableArr(newFixedTableData, row, false)
  2918. this.contentEditForm.fixedTable.fixedTables = newFixedTableData
  2919. } else if (tableType === '动态表') {
  2920. const dynamicTableData =
  2921. this.contentEditForm.dynamicTable.dynamicTables
  2922. const newDynamicTableData = [...dynamicTableData]
  2923. this.swamTableArr(newDynamicTableData, row, false)
  2924. this.contentEditForm.dynamicTable.dynamicTables = newDynamicTableData
  2925. } else {
  2926. // const tableHeaders = this.contentEditForm.tableHeaders
  2927. // const newTableHeaders = [...tableHeaders]
  2928. // this.swamTableArr(newTableHeaders, row, false)
  2929. // this.contentEditForm.tableHeaders = newTableHeaders
  2930. if (index < this.contentEditForm.tableHeaders.length - 1) {
  2931. const temp = this.contentEditForm.tableHeaders[index]
  2932. this.contentEditForm.tableHeaders.splice(index, 1)
  2933. this.contentEditForm.tableHeaders.splice(index + 1, 0, temp)
  2934. // 更新表头的序号
  2935. this.updateTableHeadersOrderNumbers()
  2936. }
  2937. }
  2938. },
  2939. swamTableArr(arr, row, asc, isHeader) {
  2940. if (isHeader) {
  2941. // 创建数组副本以确保Vue能检测到变化
  2942. // 直接替换整个数组,确保Vue能检测到变化
  2943. this.doSwamTableArr(arr, row, asc, isHeader)
  2944. } else {
  2945. const isChild = row.isChild || row.isSubItem || false
  2946. if (isChild) {
  2947. // 子节点处理逻辑后续实现 parentid rowid
  2948. let child = arr.find((item) => item.rowid === row.parentid)
  2949. // const rowIndex = arr.indexOf(row);
  2950. // newFixedTableData[rowIndex]
  2951. this.doSwamTableArr(child.children, row, asc, isHeader)
  2952. } else {
  2953. this.doSwamTableArr(arr, row, asc, isHeader)
  2954. }
  2955. }
  2956. },
  2957. // 更新表头序号
  2958. updateTableHeadersOrderNumbers() {
  2959. if (!this.contentEditForm || !this.contentEditForm.tableHeaders) return
  2960. // 更新主表头的orderNum
  2961. this.contentEditForm.tableHeaders.forEach((header, index) => {
  2962. header.orderNum = index + 1
  2963. })
  2964. // 同步更新固定表和动态表的表头序号
  2965. if (
  2966. this.contentEditForm.fixedTable &&
  2967. this.contentEditForm.fixedTable.tableHeaders
  2968. ) {
  2969. this.contentEditForm.fixedTable.tableHeaders.forEach(
  2970. (header, index) => {
  2971. header.orderNum = index + 1
  2972. }
  2973. )
  2974. }
  2975. if (
  2976. this.contentEditForm.dynamicTable &&
  2977. this.contentEditForm.dynamicTable.tableHeaders
  2978. ) {
  2979. this.contentEditForm.dynamicTable.tableHeaders.forEach(
  2980. (header, index) => {
  2981. header.orderNum = index + 1
  2982. }
  2983. )
  2984. }
  2985. },
  2986. doSwamTableArr(arr, row, asc, isHeader) {
  2987. const rowIndex = arr.indexOf(row)
  2988. let swamIndex = 0
  2989. if (asc) {
  2990. // 正序
  2991. if (rowIndex < 1) {
  2992. return
  2993. }
  2994. swamIndex = rowIndex - 1
  2995. } else {
  2996. // 倒序
  2997. if (rowIndex >= arr.length - 1) {
  2998. return
  2999. }
  3000. swamIndex = rowIndex + 1
  3001. }
  3002. const curr = arr[rowIndex]
  3003. const swam = arr[swamIndex]
  3004. // 交换orderNum
  3005. const tempOrderNum = curr.orderNum
  3006. curr.orderNum = swam.orderNum
  3007. swam.orderNum = tempOrderNum
  3008. // row.isChild &&
  3009. if (!isHeader) {
  3010. // 获取当前项的序号值
  3011. let currIndex = curr.fixedValues
  3012. ? curr.fixedValues['序号']
  3013. : curr.dynamicValues['序号']
  3014. // 获取交换项的序号值
  3015. let swamIndex = swam.fixedValues
  3016. ? swam.fixedValues['序号']
  3017. : swam.dynamicValues['序号']
  3018. // 先保存交换项的值,再进行赋值,避免值被覆盖
  3019. if (curr.fixedValues) {
  3020. curr.fixedValues['序号'] = swamIndex
  3021. } else {
  3022. curr.dynamicValues['序号'] = swamIndex
  3023. }
  3024. if (swam.fixedValues) {
  3025. swam.fixedValues['序号'] = currIndex
  3026. } else {
  3027. swam.dynamicValues['序号'] = currIndex
  3028. }
  3029. }
  3030. // 交换数组中的位置
  3031. arr[rowIndex] = swam
  3032. arr[swamIndex] = curr
  3033. },
  3034. // 启动/停用状态
  3035. handleStatus(row) {
  3036. const action = row.status === '启用' ? '停用' : '启用'
  3037. if (row.status === '0') {
  3038. this.$confirm(`确认要停用该数据吗?`, '操作确认', {
  3039. confirmButtonText: '确定',
  3040. cancelButtonText: '取消',
  3041. type: 'warning',
  3042. })
  3043. .then(() => {
  3044. row.status = '-1'
  3045. putSurveyTemplatePublishVersion(row).then((res) => {
  3046. if (res.code === 200) {
  3047. this.$message.success(`停用成功`)
  3048. this.handleSearch()
  3049. }
  3050. })
  3051. })
  3052. .catch(() => {
  3053. this.$message({
  3054. type: 'info',
  3055. message: '已取消操作',
  3056. })
  3057. })
  3058. } else if (row.status === '-1') {
  3059. this.$confirm(`确认要启用该数据吗?`, '操作确认', {
  3060. confirmButtonText: '确定',
  3061. cancelButtonText: '取消',
  3062. type: 'warning',
  3063. })
  3064. .then(() => {
  3065. row.status = '0'
  3066. putSurveyTemplatePublishVersion(row).then((res) => {
  3067. if (res.code === 200) {
  3068. this.$message.success(`启用成功`)
  3069. this.handleSearch()
  3070. }
  3071. })
  3072. })
  3073. .catch(() => {
  3074. this.$message({
  3075. type: 'info',
  3076. message: '已取消操作',
  3077. })
  3078. })
  3079. }
  3080. },
  3081. // 更新固定表行序号
  3082. updateFixedTableOrderNumbers() {
  3083. this.contentEditForm.fixedTable.fixedTables.forEach((row, index) => {
  3084. // 更新显示序号
  3085. this.$set(row, 'orderText', index + 1)
  3086. // 更新后端序号
  3087. this.$set(row, 'orderNum', index + 1)
  3088. })
  3089. },
  3090. // 更新动态表行序号
  3091. updateDynamicTableOrderNumbers() {
  3092. this.contentEditForm.dynamicTable.dynamicTables.forEach(
  3093. (row, index) => {
  3094. // 更新显示序号
  3095. this.$set(row, 'orderText', index + 1)
  3096. // 更新后端序号
  3097. this.$set(row, 'orderNum', index + 1)
  3098. }
  3099. )
  3100. },
  3101. // 绑定字典变化
  3102. handleBindDictChange(row) {
  3103. if (row.isDict === 'false') {
  3104. row.dictid = ''
  3105. }
  3106. },
  3107. // 获取格式占位符
  3108. getFormatPlaceholder(fieldType) {
  3109. switch (fieldType) {
  3110. case '日期':
  3111. return '如:yyyy-MM-dd'
  3112. case '数字':
  3113. return '如:#,##0.00'
  3114. default:
  3115. return '请输入格式'
  3116. }
  3117. },
  3118. // 滚动到错误行
  3119. scrollToErrorRow(rowIndex) {
  3120. this.$nextTick(() => {
  3121. const tableBody = document.querySelector(
  3122. '.table-edit-container .el-table__body-wrapper'
  3123. )
  3124. if (tableBody) {
  3125. const scrollTop = rowIndex * 48
  3126. tableBody.scrollTop = scrollTop
  3127. }
  3128. })
  3129. },
  3130. // 保存内容
  3131. handleSaveContent(type, action) {
  3132. this.loading = true
  3133. let isValid = false
  3134. try {
  3135. if (type === '单记录') {
  3136. var data = {
  3137. headersList: this.contentEditForm.tableHeaders,
  3138. }
  3139. getBatchSaveOrUpdate(data)
  3140. .then((res) => {
  3141. if (res.code === 200) {
  3142. if (action != 'delete') {
  3143. this.$message.success('保存成功')
  3144. this.contentEditDialogVisible = false
  3145. }
  3146. } else {
  3147. this.$message.error(`保存失败:${res.message || '未知错误'}`)
  3148. }
  3149. })
  3150. .catch((error) => {
  3151. console.error('保存接口异常:', error)
  3152. // this.$message.error('保存接口异常,请重试')
  3153. })
  3154. .finally(() => {
  3155. this.loading = false
  3156. })
  3157. } else if (type === '固定表表头') {
  3158. var data = {
  3159. headersList: this.contentEditForm.fixedTable.tableHeaders,
  3160. }
  3161. getBatchSaveOrUpdate(data)
  3162. .then((res) => {
  3163. if (res.code === 200) {
  3164. this.contentEditForm.isFixedTables = true
  3165. this.loading = true
  3166. // 如果后端返回了保存后的数据,更新本地数据
  3167. if (res.value && Array.isArray(res.value)) {
  3168. this.contentEditForm.fixedTable.tableHeaders =
  3169. res.value.map((item) => ({
  3170. ...item,
  3171. }))
  3172. // 确保保存后的数据也按正确顺序显示
  3173. this.updateTableHeadersOrderNumbers()
  3174. }
  3175. this.getListBySurveyTemplateIdAndVersion(
  3176. this.surveyTemplateId,
  3177. this.versionId
  3178. )
  3179. listByTemplateIdAndVersion(
  3180. this.surveyTemplateId,
  3181. this.versionId
  3182. )
  3183. .then((res) => {
  3184. this.loading = false
  3185. this.contentEditForm.fixedTable.fixedTablesTitle =
  3186. this.stringToObjects(res.value.fixedFields)
  3187. this.contentEditForm.fixedTable.fixedTables.forEach(
  3188. (row) => {
  3189. this.initFixedTableRow(row)
  3190. }
  3191. )
  3192. this.contentEditForm.fixedTable.fixedTableHeaders =
  3193. this.contentEditForm.fixedTable.fixedTablesTitle.filter(
  3194. (title) => title.rkey !== '序号'
  3195. )
  3196. })
  3197. .catch((error) => {
  3198. console.error('查询失败:', error)
  3199. this.loading = false
  3200. })
  3201. } else {
  3202. this.$message.error(`保存失败:${res.message || '未知错误'}`)
  3203. }
  3204. })
  3205. .catch((error) => {
  3206. console.error('保存接口异常:', error)
  3207. // this.$message.error('保存接口异常,请重试')
  3208. })
  3209. .finally(() => {
  3210. this.loading = false
  3211. })
  3212. } else if (type === '固定表项目') {
  3213. this.saveFixedTableData(action)
  3214. } else if (type === '动态表表头') {
  3215. var data = {
  3216. headersList: this.contentEditForm.dynamicTable.tableHeaders,
  3217. }
  3218. getBatchSaveOrUpdate(data)
  3219. .then((res) => {
  3220. if (res.code === 200) {
  3221. this.contentEditForm.isDynamicTables = true
  3222. this.loading = true
  3223. // 如果后端返回了保存后的数据,更新本地数据
  3224. if (res.value && Array.isArray(res.value)) {
  3225. this.contentEditForm.dynamicTable.tableHeaders =
  3226. res.value.map((item) => ({
  3227. ...item,
  3228. fieldKey: item.fieldEname
  3229. ? item.fieldEname.toLowerCase()
  3230. : `field_${Date.now()}_${Math.random()
  3231. .toString(36)
  3232. .substr(2, 9)}`,
  3233. }))
  3234. // 确保保存后的数据也按正确顺序显示
  3235. this.updateTableHeadersOrderNumbers()
  3236. }
  3237. this.getListBySurveyTemplateIdAndVersion(
  3238. this.surveyTemplateId,
  3239. this.versionId
  3240. )
  3241. listByTemplateIdAndVersion(
  3242. this.surveyTemplateId,
  3243. this.versionId
  3244. )
  3245. .then((res) => {
  3246. this.loading = false
  3247. this.contentEditForm.dynamicTable.dynamicTablesTitle =
  3248. this.stringToObjects(res.value.fixedFields || '')
  3249. // 初始化所有已有行的 dynamicValues
  3250. this.contentEditForm.dynamicTable.dynamicTables.forEach(
  3251. (row) => {
  3252. this.initDynamicTableRow(row)
  3253. }
  3254. )
  3255. this.contentEditForm.dynamicTable.dynamicTableHeaders =
  3256. this.contentEditForm.dynamicTable.dynamicTablesTitle.filter(
  3257. (title) => title.rkey !== '序号'
  3258. )
  3259. })
  3260. .catch((error) => {
  3261. console.error('查询失败:', error)
  3262. this.loading = false
  3263. })
  3264. } else {
  3265. this.$message.error(`保存失败:${res.message || '未知错误'}`)
  3266. }
  3267. })
  3268. .catch((error) => {
  3269. console.error('保存接口异常:', error)
  3270. // this.$message.error('保存接口异常,请重试')
  3271. })
  3272. .finally(() => {
  3273. this.loading = false
  3274. })
  3275. } else if (type === '动态表项目') {
  3276. this.saveDynamicTableData(action)
  3277. }
  3278. } catch (error) {
  3279. console.error('保存处理异常:', error)
  3280. // this.$message.error('保存过程中发生错误,请重试')
  3281. this.loading = false
  3282. }
  3283. },
  3284. // 公式验证函数
  3285. validateFormula(formula, data) {
  3286. if (!formula || typeof formula !== 'string') {
  3287. return { valid: false, errorMsg: '公式不能为空' }
  3288. }
  3289. // 定义有效的操作符
  3290. const operators = ['+', '-', '*', '/', '(', ')']
  3291. // 检查是否包含至少一个操作符
  3292. const hasOperator = operators.some((operator) =>
  3293. formula.includes(operator)
  3294. )
  3295. if (!hasOperator) {
  3296. return { valid: false, errorMsg: '公式必须包含操作符' }
  3297. }
  3298. // 检查值是否在data中存在
  3299. function checkValueInData(value, data) {
  3300. if (!data) return false
  3301. if (Array.isArray(data)) {
  3302. return data.includes(value)
  3303. } else if (typeof data === 'object') {
  3304. return Object.values(data).includes(value)
  3305. }
  3306. return data === value
  3307. }
  3308. // 提取公式中的变量/值
  3309. function extractValues(formulaStr) {
  3310. // 改进实现:支持形如"CeShi3.C2"的格式,提取点后面的部分作为变量,同时保留普通变量
  3311. const result = new Set()
  3312. // 1. 首先提取带点格式中的变量部分(如CeShi3.C2中的C2)
  3313. const dotRegex = /[A-Za-z0-9]+\.([A-Za-z0-9]+)/g
  3314. let dotMatch
  3315. while ((dotMatch = dotRegex.exec(formulaStr)) !== null) {
  3316. result.add(dotMatch[1]) // 提取点后面的部分作为变量
  3317. }
  3318. // 2. 然后提取普通变量(C3等),但排除已经从带点格式中提取的部分
  3319. // 移除所有带点的部分,然后提取剩余的变量
  3320. const remainingFormula = formulaStr.replace(
  3321. /[A-Za-z0-9]+\.[A-Za-z0-9]+/g,
  3322. ''
  3323. )
  3324. const normalRegex = /[A-Za-z0-9]+/g
  3325. let normalMatch
  3326. while ((normalMatch = normalRegex.exec(remainingFormula)) !== null) {
  3327. // 跳过纯数字
  3328. if (
  3329. !isNaN(Number(normalMatch[0])) &&
  3330. Number(normalMatch[0]).toString() === normalMatch[0]
  3331. ) {
  3332. continue
  3333. }
  3334. result.add(normalMatch[0])
  3335. }
  3336. return Array.from(result)
  3337. }
  3338. function checkOperatorContext(formulaStr, data) {
  3339. for (let i = 0; i < formulaStr.length; i++) {
  3340. const char = formulaStr[i]
  3341. // 跳过括号
  3342. if (char === '(' || char === ')') continue
  3343. // 检查操作符
  3344. if (operators.includes(char)) {
  3345. // 检查操作符前是否有值(开头或不是操作符和左括号)
  3346. if (
  3347. i === 0 ||
  3348. (operators.includes(formulaStr[i - 1]) &&
  3349. formulaStr[i - 1] !== ')') ||
  3350. formulaStr[i - 1] === '('
  3351. ) {
  3352. return {
  3353. valid: false,
  3354. errorMsg: `位置 ${i + 1} 的操作符 '${char}' 前缺少值`,
  3355. }
  3356. }
  3357. // 检查操作符后是否有值(结尾或不是操作符和右括号)
  3358. if (
  3359. i === formulaStr.length - 1 ||
  3360. (operators.includes(formulaStr[i + 1]) &&
  3361. formulaStr[i + 1] !== '(') ||
  3362. formulaStr[i + 1] === ')'
  3363. ) {
  3364. return {
  3365. valid: false,
  3366. errorMsg: `位置 ${i + 1} 的操作符 '${char}' 后缺少值`,
  3367. }
  3368. }
  3369. }
  3370. }
  3371. // 验证通过后,检查公式中的值是否都在data中存在
  3372. if (data.length > 0) {
  3373. const values = extractValues(formulaStr)
  3374. for (const value of values) {
  3375. // 跳过纯数字(假设有值不在data中)
  3376. if (!isNaN(Number(value)) && Number(value).toString() === value) {
  3377. continue
  3378. }
  3379. if (!checkValueInData(value, data)) {
  3380. return {
  3381. valid: false,
  3382. errorMsg: `变量 '${value}' 在数据中不存在`,
  3383. }
  3384. }
  3385. }
  3386. }
  3387. return { valid: true }
  3388. }
  3389. // 执行验证
  3390. return checkOperatorContext(formula, data)
  3391. },
  3392. /**
  3393. * 将固定表项目的数据根据固定列拆分成对应的数据结构
  3394. * @returns {Array} 拆分后的数据数组,每个固定列对应一行数据
  3395. */
  3396. splitFixedTableDataForSave() {
  3397. const fixedTables = this.contentEditForm.fixedTable.fixedTables
  3398. const fixedTitles = this.contentEditForm.fixedTable.fixedTablesTitle
  3399. const fixedHeaders = this.contentEditForm.fixedTable.tableHeaders
  3400. // 结果数组
  3401. const result = []
  3402. // 递归处理树形结构中的所有节点
  3403. const processNode = (node, parentRowIndex = 0) => {
  3404. // 确保node和fixedValues存在
  3405. if (!node) {
  3406. console.warn('遇到空节点,跳过处理')
  3407. return
  3408. }
  3409. // 确保fixedValues属性存在,如果不存在则初始化为空对象
  3410. if (!node.fixedValues) {
  3411. node.fixedValues = {}
  3412. }
  3413. // 为每个固定列创建一条记录
  3414. fixedTitles.forEach((title) => {
  3415. // 找到对应的表头信息
  3416. const correspondingHeader = fixedHeaders.find(
  3417. (header) => header.fieldName === title.rkey
  3418. )
  3419. const newItem = {
  3420. rkey: title.rkey,
  3421. rvalue: node.fixedValues[title.rkey] || '',
  3422. surveyTemplateId: node.surveyTemplateId || this.surveyTemplateId,
  3423. versionId: node.versionId || this.versionId,
  3424. tabtype: node.tabtype || this.templateType,
  3425. // 添加 headersId 字段(表头的id)
  3426. headersId: correspondingHeader ? correspondingHeader.id : null,
  3427. // 添加记录的id(itemlist中每条记录的id)
  3428. id: node.itemId || null,
  3429. // 添加父子关系字段
  3430. parentid: node.parentid || -1, // 父项ID,默认为-1表示无父项
  3431. isChild: node.isChild || false, // 是否为子项
  3432. // 添加 rowid 字段
  3433. rowid: node.rowid || null,
  3434. // 添加计算公式相关字段
  3435. calculationFormula: node.calculationFormula || null,
  3436. jsonstr: node.jsonstr || null,
  3437. orderNum:
  3438. typeof node.orderNum === 'number'
  3439. ? node.orderNum
  3440. : parseInt(node.orderNum, 10) || 0,
  3441. }
  3442. // 添加其他固定表特有的字段
  3443. if (!node.isSubItem) {
  3444. newItem.cellCode = node.cellCode || ''
  3445. newItem.unit = node.unit || ''
  3446. }
  3447. // 添加其他可能需要的字段,但排除特定字段
  3448. Object.keys(node).forEach((key) => {
  3449. if (
  3450. !(key in newItem) &&
  3451. key !== 'fixedValues' &&
  3452. key !== 'itemId' &&
  3453. key !== 'id' &&
  3454. key !== 'parentid' &&
  3455. key !== 'isChild' &&
  3456. key !== 'isSubItem' &&
  3457. key !== 'rowid' &&
  3458. key !== 'jsonstr' &&
  3459. key !== 'calculationFormula' &&
  3460. key !== 'children' // 排除children字段
  3461. ) {
  3462. newItem[key] = node[key]
  3463. }
  3464. })
  3465. result.push(newItem)
  3466. })
  3467. // 递归处理子节点
  3468. if (node.children && node.children.length > 0) {
  3469. node.children.forEach((childNode) => {
  3470. processNode(childNode)
  3471. })
  3472. }
  3473. }
  3474. // 遍历所有顶级节点
  3475. fixedTables.forEach((row) => {
  3476. processNode(row)
  3477. })
  3478. // 重新给子节点赋值orderNum 保证所有元素orderNum字段不重复
  3479. // 为所有子节点分配唯一的orderNum,但保持父节点的orderNum不变
  3480. // 计算所有已存在的orderNum中的最大值
  3481. let maxExistingOrderNum = 0
  3482. // 首先遍历结果数组找出当前最大的orderNum
  3483. result.forEach((item) => {
  3484. const orderNum =
  3485. typeof item.orderNum === 'number'
  3486. ? item.orderNum
  3487. : parseInt(item.orderNum, 10) || 0
  3488. if (orderNum > maxExistingOrderNum) {
  3489. maxExistingOrderNum = orderNum
  3490. }
  3491. })
  3492. // 子节点orderNum从当前最大orderNum + 1开始
  3493. let childOrderNumCounter = maxExistingOrderNum + 1
  3494. // 创建一个映射表,用于记录每个子节点对应的新orderNum
  3495. const childOrderMap = new Map()
  3496. // 第一次遍历:为每个子节点分配新的orderNum并存储映射关系
  3497. function assignChildOrderNums(nodes) {
  3498. nodes.forEach((node) => {
  3499. if (node.isChild || node.isSubItem) {
  3500. // 为每个子节点分配唯一的orderNum
  3501. childOrderMap.set(node.id || node.rowid, childOrderNumCounter++)
  3502. }
  3503. // 递归处理子节点
  3504. if (node.children && node.children.length > 0) {
  3505. assignChildOrderNums(node.children)
  3506. }
  3507. })
  3508. }
  3509. // 第二次遍历:更新结果数组中的orderNum
  3510. assignChildOrderNums(fixedTables)
  3511. // 应用新的orderNum到结果数组
  3512. result.forEach((item) => {
  3513. // 只更新子节点的orderNum
  3514. if (item.isChild || item.isSubItem) {
  3515. const newOrderNum =
  3516. childOrderMap.get(item.id) || childOrderMap.get(item.rowid)
  3517. if (newOrderNum) {
  3518. item.orderNum = newOrderNum
  3519. }
  3520. }
  3521. })
  3522. return result
  3523. },
  3524. /**
  3525. * 将动态表项目的数据根据动态列拆分成对应的数据结构
  3526. * @returns {Array} 拆分后的数据数组,每个动态列对应一行数据
  3527. */
  3528. splitDynamicTableDataForSave() {
  3529. const dynamicTables = this.contentEditForm.dynamicTable.dynamicTables
  3530. const dynamicTitles =
  3531. this.contentEditForm.dynamicTable.dynamicTablesTitle
  3532. const dynamicHeaders = this.contentEditForm.dynamicTable.tableHeaders
  3533. // 结果数组
  3534. const result = []
  3535. // 递归处理树形结构中的所有节点
  3536. const processNode = (node) => {
  3537. // 确保node和dynamicValues存在
  3538. if (!node) {
  3539. console.warn('遇到空节点,跳过处理')
  3540. return
  3541. }
  3542. // 确保dynamicValues属性存在,如果不存在则初始化为空对象
  3543. if (!node.dynamicValues) {
  3544. node.dynamicValues = {}
  3545. }
  3546. // 为每个固定列创建一条记录
  3547. dynamicTitles.forEach((title) => {
  3548. // 找到对应的表头信息
  3549. const correspondingHeader = dynamicHeaders.find(
  3550. (header) => header.fieldName === title.rkey
  3551. )
  3552. const newItem = {
  3553. rkey: title.rkey,
  3554. rvalue: node.dynamicValues[title.rkey] || '',
  3555. surveyTemplateId: node.surveyTemplateId,
  3556. versionId: node.versionId,
  3557. tabtype: node.tabtype,
  3558. // 添加 headersId 字段(表头的id)
  3559. headersId: correspondingHeader ? correspondingHeader.id : null,
  3560. // 添加记录的id(itemlist中每条记录的id)
  3561. id: node.itemId || null,
  3562. // 添加父子关系字段
  3563. parentid: node.parentid || -1, // 父项ID,默认为-1表示无父项
  3564. isChild: node.isChild || false, // 是否为子项
  3565. // 添加 rowid 字段
  3566. rowid: node.rowid || null,
  3567. // 添加计算公式相关字段
  3568. calculationFormula: node.calculationFormula || null,
  3569. jsonstr: node.jsonstr || null,
  3570. orderNum:
  3571. typeof node.orderNum === 'number'
  3572. ? node.orderNum
  3573. : parseInt(node.orderNum, 10) || 0,
  3574. }
  3575. // 添加其他可能需要的字段,但排除特定字段
  3576. Object.keys(node).forEach((key) => {
  3577. if (
  3578. !(key in newItem) &&
  3579. key !== 'dynamicValues' &&
  3580. key !== 'itemId' &&
  3581. key !== 'id' &&
  3582. key !== 'parentid' &&
  3583. key !== 'isChild' &&
  3584. key !== 'isSubItem' &&
  3585. key !== 'rowid' &&
  3586. key !== 'jsonstr' &&
  3587. key !== 'calculationFormula' &&
  3588. key !== 'children' // 排除children字段
  3589. ) {
  3590. newItem[key] = node[key]
  3591. }
  3592. })
  3593. result.push(newItem)
  3594. })
  3595. // 递归处理子节点
  3596. if (node.children && node.children.length > 0) {
  3597. node.children.forEach((childNode) => {
  3598. processNode(childNode)
  3599. })
  3600. }
  3601. }
  3602. // 遍历所有顶级节点
  3603. dynamicTables.forEach((row) => {
  3604. processNode(row)
  3605. })
  3606. // 重新给子节点赋值orderNum 保证所有元素orderNum字段不重复
  3607. // 为所有子节点分配唯一的orderNum,但保持父节点的orderNum不变
  3608. // 计算所有已存在的orderNum中的最大值
  3609. let maxExistingOrderNum = 0
  3610. // 首先遍历结果数组找出当前最大的orderNum
  3611. result.forEach((item) => {
  3612. const orderNum =
  3613. typeof item.orderNum === 'number'
  3614. ? item.orderNum
  3615. : parseInt(item.orderNum, 10) || 0
  3616. if (orderNum > maxExistingOrderNum) {
  3617. maxExistingOrderNum = orderNum
  3618. }
  3619. })
  3620. // 子节点orderNum从当前最大orderNum + 1开始
  3621. let childOrderNumCounter = maxExistingOrderNum + 1
  3622. // 创建一个映射表,用于记录每个子节点对应的新orderNum
  3623. const childOrderMap = new Map()
  3624. // 第一次遍历:为每个子节点分配新的orderNum并存储映射关系
  3625. function assignChildOrderNums(nodes) {
  3626. nodes.forEach((node) => {
  3627. if (node.isChild || node.isSubItem) {
  3628. // 为每个子节点分配唯一的orderNum
  3629. childOrderMap.set(node.id || node.rowid, childOrderNumCounter++)
  3630. }
  3631. // 递归处理子节点
  3632. if (node.children && node.children.length > 0) {
  3633. assignChildOrderNums(node.children)
  3634. }
  3635. })
  3636. }
  3637. // 第二次遍历:更新结果数组中的orderNum
  3638. assignChildOrderNums(dynamicTables)
  3639. // 应用新的orderNum到结果数组
  3640. result.forEach((item) => {
  3641. // 只更新子节点的orderNum
  3642. if (item.isChild || item.isSubItem) {
  3643. const newOrderNum =
  3644. childOrderMap.get(item.id) || childOrderMap.get(item.rowid)
  3645. if (newOrderNum) {
  3646. item.orderNum = newOrderNum
  3647. }
  3648. }
  3649. })
  3650. return result
  3651. },
  3652. //保存固定表项目数据
  3653. saveFixedTableData(action = '') {
  3654. try {
  3655. // 获取拆分后的数据
  3656. const splitData = this.splitFixedTableDataForSave()
  3657. // 构造保存数据的结构
  3658. const saveData = {
  3659. itemsList: splitData,
  3660. }
  3661. // 调用保存接口
  3662. getBatchSaveOrUpdate(saveData)
  3663. .then((res) => {
  3664. if (res.code === 200) {
  3665. // 如果是删除操作,不显示成功提示且不关闭对话框
  3666. if (action !== 'delete') {
  3667. this.$message.success('固定表数据保存成功')
  3668. this.contentEditDialogVisible = false
  3669. }
  3670. // 刷新数据以确保UI更新
  3671. this.getListBySurveyTemplateIdAndVersion(
  3672. this.surveyTemplateId,
  3673. this.versionId
  3674. )
  3675. } else {
  3676. this.$message.error(`保存失败:${res.message || '未知错误'}`)
  3677. }
  3678. })
  3679. .catch((error) => {
  3680. console.error('保存固定表数据接口异常:', error)
  3681. // this.$message.error('保存固定表数据失败,请重试')
  3682. })
  3683. .finally(() => {
  3684. this.loading = false
  3685. })
  3686. return splitData
  3687. } catch (error) {
  3688. console.error('处理固定表数据保存时出错:', error)
  3689. // this.$message.error('保存过程中发生错误,请重试')
  3690. this.loading = false
  3691. }
  3692. },
  3693. //保存动态表项目数据
  3694. saveDynamicTableData() {
  3695. try {
  3696. // 获取拆分后的数据
  3697. const splitData = this.splitDynamicTableDataForSave()
  3698. // 构造保存数据的结构
  3699. const saveData = {
  3700. itemsList: splitData,
  3701. }
  3702. // 调用保存接口
  3703. getBatchSaveOrUpdate(saveData)
  3704. .then((res) => {
  3705. if (res.code === 200) {
  3706. if (action != 'delete') {
  3707. this.$message.success('动态表数据保存成功')
  3708. this.contentEditDialogVisible = false
  3709. }
  3710. } else {
  3711. this.$message.error(`保存失败:${res.message || '未知错误'}`)
  3712. }
  3713. })
  3714. .catch((error) => {
  3715. console.error('保存动态表数据接口异常:', error)
  3716. // this.$message.error('保存动态表数据失败,请重试')
  3717. })
  3718. .finally(() => {
  3719. this.loading = false
  3720. })
  3721. return splitData
  3722. } catch (error) {
  3723. console.error('处理动态表数据保存时出错:', error)
  3724. // this.$message.error('保存过程中发生错误,请重试')
  3725. this.loading = false
  3726. }
  3727. },
  3728. /**
  3729. * 解析并回显固定表项目数据
  3730. * @param {Object} responseData - listByTemplateIdAndVersion接口返回的数据
  3731. */
  3732. parseAndDisplayFixedTableData(responseData) {
  3733. if (responseData.value.fixedFields) {
  3734. this.contentEditForm.fixedTable.fixedTablesTitle =
  3735. this.stringToObjects(responseData.value.fixedFields || '')
  3736. } else {
  3737. let fixedFields = this.contentEditForm.fixedTable.tableHeaders
  3738. .map((item) => item.fieldName)
  3739. .join(',')
  3740. this.contentEditForm.fixedTable.fixedTablesTitle =
  3741. this.stringToObjects(fixedFields || '')
  3742. }
  3743. const fixedTitles = this.contentEditForm.fixedTable.fixedTablesTitle
  3744. this.contentEditForm.fixedTable.fixedTableHeaders = fixedTitles.filter(
  3745. (title) => title.rkey !== '序号'
  3746. )
  3747. if (
  3748. !responseData ||
  3749. !responseData.value ||
  3750. !responseData.value.itemlist
  3751. ) {
  3752. return
  3753. }
  3754. const itemList = responseData.value.itemlist
  3755. const allRows = []
  3756. const rowMap = new Map()
  3757. // 清空现有数据
  3758. this.contentEditForm.fixedTable.fixedTables = []
  3759. // 遍历itemList,为每个项目创建一行数据
  3760. itemList.forEach((item, index) => {
  3761. // 判断是否为子项(parentid不为-1且不为"-1")
  3762. const isSubItem =
  3763. item.parentid && item.parentid !== -1 && item.parentid !== '-1'
  3764. const newRow = {
  3765. orderText: item.orderNum || '', // 显示用序号
  3766. orderNum: item.orderNum || '', // 保留原始序号用于发送后端
  3767. surveyTemplateId: item.surveyTemplateId,
  3768. versionId: item.versionId,
  3769. cellCode: item.cellCode || '',
  3770. calculationFormula: item.calculationFormula || '',
  3771. unit: item.unit || '',
  3772. fixedValues: {},
  3773. itemId: item.id || null,
  3774. parentid: item.parentid || -1,
  3775. isChild: isSubItem,
  3776. isSubItem: isSubItem,
  3777. rowid: item.rowid || this.generateUUID(),
  3778. jsonstr: item.jsonstr || null,
  3779. children: [], // 添加children数组用于树形结构
  3780. }
  3781. // 确保orderNum是数字类型
  3782. if (item.orderNum) {
  3783. newRow.orderNum = parseInt(item.orderNum, 10) || 0
  3784. }
  3785. // 初始化fixedValues并填充实际值
  3786. fixedTitles.forEach((title) => {
  3787. newRow.fixedValues[title.rkey] = item[title.rkey] || ''
  3788. })
  3789. allRows.push(newRow)
  3790. // 构建rowMap用于快速查找
  3791. if (newRow.rowid) rowMap.set(String(newRow.rowid), newRow)
  3792. if (newRow.itemId) rowMap.set(String(newRow.itemId), newRow)
  3793. })
  3794. // 构建树形结构
  3795. const treeData = []
  3796. const parentItems = allRows.filter((item) => !item.isChild)
  3797. // 父级按orderNum正序排序
  3798. parentItems.sort((a, b) => (a.orderNum || 0) - (b.orderNum || 0))
  3799. // 将子项添加到对应的父项的children中
  3800. allRows.forEach((item) => {
  3801. if (item.isChild) {
  3802. const parentId = String(item.parentid)
  3803. const parent = rowMap.get(parentId)
  3804. if (parent) {
  3805. parent.children.push(item)
  3806. }
  3807. }
  3808. })
  3809. // 对子项进行排序
  3810. parentItems.forEach((parent) => {
  3811. parent.children.sort(
  3812. (a, b) =>
  3813. (a.fixedValues['序号'] || 0) - (b.fixedValues['序号'] || 0)
  3814. )
  3815. treeData.push(parent)
  3816. })
  3817. this.contentEditForm.fixedTable.fixedTables = treeData
  3818. },
  3819. /**
  3820. * 解析并回显动态表项目数据
  3821. * @param {Object} responseData - listByTemplateIdAndVersion接口返回的数据
  3822. */
  3823. parseAndDisplayDynamicTableData(responseData) {
  3824. if (responseData.value.fixedFields) {
  3825. this.contentEditForm.dynamicTable.dynamicTablesTitle =
  3826. this.stringToObjects(responseData.value.fixedFields || '')
  3827. } else {
  3828. let fixedFields = this.contentEditForm.dynamicTable.tableHeaders
  3829. .map((item) => item.fieldName)
  3830. .join(',')
  3831. this.contentEditForm.dynamicTable.dynamicTablesTitle =
  3832. this.stringToObjects(fixedFields || '')
  3833. }
  3834. const dynamicTitles =
  3835. this.contentEditForm.dynamicTable.dynamicTablesTitle
  3836. this.contentEditForm.dynamicTable.dynamicTableHeaders =
  3837. dynamicTitles.filter((title) => title.rkey !== '序号')
  3838. if (
  3839. !responseData ||
  3840. !responseData.value ||
  3841. !responseData.value.itemlist
  3842. ) {
  3843. return
  3844. }
  3845. const itemList = responseData.value.itemlist
  3846. const allRows = []
  3847. const rowMap = new Map()
  3848. // 清空现有数据
  3849. this.contentEditForm.dynamicTable.dynamicTables = []
  3850. // 遍历itemList,为每个项目创建一行数据
  3851. itemList.forEach((item, index) => {
  3852. // 判断是否为子项(parentid不为-1且不为"-1")
  3853. const isSubItem =
  3854. item.parentid && item.parentid !== -1 && item.parentid !== '-1'
  3855. const newRow = {
  3856. orderText: item.orderNum || '', // 显示用序号
  3857. orderNum: item.orderNum || '', // 保留原始序号用于发送后端
  3858. surveyTemplateId: item.surveyTemplateId,
  3859. dynamicValues: {},
  3860. itemId: item.id || null,
  3861. parentid: item.parentid || -1,
  3862. isChild: isSubItem,
  3863. isSubItem: isSubItem,
  3864. rowid: item.rowid || this.generateUUID(),
  3865. jsonstr: item.jsonstr || null,
  3866. children: [], // 添加children数组用于树形结构
  3867. }
  3868. // 确保orderNum是数字类型
  3869. if (item.orderNum) {
  3870. newRow.orderNum = parseInt(item.orderNum, 10) || 0
  3871. }
  3872. // 初始化dynamicValues并填充实际值
  3873. dynamicTitles.forEach((title) => {
  3874. // 特殊处理序号字段,需要保存到dynamicValues中供输入框使用
  3875. if (title.rkey === '序号') {
  3876. // 优先使用item中的序号值,如果没有则保持为空
  3877. newRow.dynamicValues[title.rkey] = item[title.rkey] || ''
  3878. }
  3879. // 排除其他序号相关字段,避免重复显示
  3880. else if (title.rkey !== 'ordernum' && title.rkey !== 'orderText') {
  3881. newRow.dynamicValues[title.rkey] = item[title.rkey] || ''
  3882. }
  3883. })
  3884. allRows.push(newRow)
  3885. // 构建rowMap用于快速查找
  3886. if (newRow.rowid) rowMap.set(String(newRow.rowid), newRow)
  3887. if (newRow.itemId) rowMap.set(String(newRow.itemId), newRow)
  3888. })
  3889. // 构建树形结构
  3890. const treeData = []
  3891. const parentItems = allRows.filter((item) => !item.isChild)
  3892. // 父级按orderNum正序排序
  3893. parentItems.sort((a, b) => (a.orderNum || 0) - (b.orderNum || 0))
  3894. // 将子项添加到对应的父项的children中
  3895. allRows.forEach((item) => {
  3896. if (item.isChild) {
  3897. const parentId = String(item.parentid)
  3898. const parent = rowMap.get(parentId)
  3899. if (parent) {
  3900. parent.children.push(item)
  3901. }
  3902. }
  3903. })
  3904. // 对子项进行排序
  3905. parentItems.forEach((parent) => {
  3906. parent.children.sort(
  3907. (a, b) =>
  3908. (Number(a.dynamicValues['序号']) || 0) -
  3909. (Number(b.dynamicValues['序号']) || 0)
  3910. )
  3911. treeData.push(parent)
  3912. })
  3913. this.contentEditForm.dynamicTable.dynamicTables = treeData
  3914. console.log('树形结构数据:', treeData)
  3915. },
  3916. //分割字符串
  3917. stringToObjects(str) {
  3918. const items = str.split(',')
  3919. return items.map((item) => ({
  3920. rkey: item,
  3921. rvalue: '',
  3922. }))
  3923. },
  3924. // 删除
  3925. handleDelete(row) {
  3926. this.$confirm('确定要删除该数据吗?', '提示', {
  3927. type: 'warning',
  3928. })
  3929. .then(() => {
  3930. this.loading = true
  3931. delSurveyTemplateVersionById(row.id)
  3932. .then((res) => {
  3933. if (res.code === 200) {
  3934. this.$message.success(res.message || '删除成功')
  3935. this.handleSearch()
  3936. this.loading = false
  3937. }
  3938. })
  3939. .catch((error) => {
  3940. console.error('删除失败:', error)
  3941. this.loading = false
  3942. })
  3943. })
  3944. .catch(() => {})
  3945. },
  3946. // 批量删除
  3947. handleBatchDelete() {
  3948. if (this.selectedRows.length === 0) {
  3949. this.$message.warning('请先选择要删除的数据')
  3950. return
  3951. }
  3952. this.$confirm(
  3953. `确定要删除选中的${this.selectedRows.length}条数据吗?`,
  3954. '提示',
  3955. {
  3956. type: 'warning',
  3957. }
  3958. )
  3959. .then(() => {
  3960. this.loading = true
  3961. const ids = this.selectedRows.map((row) => row.id)
  3962. batchDeleteCostForm(ids)
  3963. .then((res) => {
  3964. this.selectedRows = []
  3965. this.$message.success(res.message || '删除成功')
  3966. this.handleSearch()
  3967. this.loading = false
  3968. })
  3969. .catch((error) => {
  3970. console.error('批量删除失败:', error)
  3971. this.loading = false
  3972. })
  3973. })
  3974. .catch(() => {})
  3975. },
  3976. // 表格选择
  3977. handleSelectionChange(selection) {
  3978. this.selectedRows = selection
  3979. },
  3980. // 分页变化处理
  3981. handlePaginationChange({ currentPage, pageSize }) {
  3982. this.pagination.currentPage = currentPage
  3983. this.pagination.pageSize = pageSize
  3984. this.handleSearch()
  3985. },
  3986. // 提交表单
  3987. submitForm() {
  3988. this.$refs.dataForm.validate((valid) => {
  3989. if (valid) {
  3990. this.loading = true
  3991. const submitData = {
  3992. versionNo: this.dataForm.version,
  3993. status: this.dataForm.status,
  3994. createBy: this.dataForm.createBy,
  3995. createTime: this.dataForm.createTime,
  3996. remarks: this.dataForm.remarks,
  3997. templateType: this.currentRow.templateType,
  3998. surveyTemplateName: this.currentRow.surveyTemplateName,
  3999. surveyTemplateId: this.currentRow.surveyTemplateId,
  4000. }
  4001. if (this.dataForm.id) {
  4002. // 修改
  4003. submitData.formId = this.dataForm.id
  4004. editCostForm(submitData)
  4005. .then(() => {
  4006. this.loading = false
  4007. this.$message.success('修改成功')
  4008. this.dialogVisible = false
  4009. this.handleSearch() // 重新加载数据
  4010. })
  4011. .catch((error) => {
  4012. console.error('修改失败:', error)
  4013. // this.$message.error('修改失败,请重试')
  4014. this.loading = false
  4015. })
  4016. } else {
  4017. addSurveyTemplateVersion(submitData)
  4018. .then(() => {
  4019. this.loading = false
  4020. this.$message.success('添加成功')
  4021. this.dialogVisible = false
  4022. this.handleSearch() // 重新加载数据
  4023. })
  4024. .catch((error) => {
  4025. console.error('添加失败:', error)
  4026. // this.$message.error('添加失败,请重试')
  4027. this.loading = false
  4028. })
  4029. }
  4030. }
  4031. })
  4032. },
  4033. // 获取数据存储库表选项
  4034. loadDataStorageTableOptions() {
  4035. getDataStorageTableOptions()
  4036. .then((response) => {
  4037. this.dataStorageTableOptions = response.data || []
  4038. })
  4039. .catch((error) => {
  4040. console.error('获取数据存储库表选项失败:', error)
  4041. })
  4042. },
  4043. },
  4044. }
  4045. </script>
  4046. <style lang="scss" scoped>
  4047. @import '@/styles/costAudit.scss';
  4048. .top-wrapper {
  4049. display: flex;
  4050. align-items: center;
  4051. }
  4052. .data-form,
  4053. .detail-form {
  4054. ::v-deep .el-select {
  4055. width: 100%;
  4056. }
  4057. }
  4058. .content-edit-container {
  4059. overflow-y: auto;
  4060. .button-group {
  4061. margin: 10px 0;
  4062. .el-button {
  4063. margin-right: 10px;
  4064. }
  4065. }
  4066. .table-edit-container {
  4067. margin-top: 10px;
  4068. ::v-deep .el-table {
  4069. transition: height 0.3s ease;
  4070. }
  4071. ::v-deep .el-table__body-wrapper {
  4072. transition: scrollTop 0.3s ease;
  4073. }
  4074. }
  4075. .bind-dict-column {
  4076. display: flex;
  4077. flex-direction: column;
  4078. }
  4079. .table-actions {
  4080. display: flex;
  4081. justify-content: center;
  4082. align-items: center;
  4083. .el-button {
  4084. padding: 4px;
  4085. margin: 0 2px;
  4086. }
  4087. }
  4088. .format-input {
  4089. display: flex;
  4090. align-items: center;
  4091. .format-prefix {
  4092. font-size: 12px;
  4093. color: #606266;
  4094. margin-right: 5px;
  4095. white-space: nowrap;
  4096. }
  4097. }
  4098. }
  4099. .detail-info-container {
  4100. margin: 20px 0;
  4101. border-radius: 4px;
  4102. .detail-item {
  4103. display: inline-block;
  4104. margin-right: 30px;
  4105. margin-bottom: 10px;
  4106. .detail-label {
  4107. font-weight: bold;
  4108. color: #606266;
  4109. }
  4110. .detail-value {
  4111. color: #303133;
  4112. }
  4113. }
  4114. }
  4115. </style>