infoMaintain.vue 153 KB

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