index.vue 60 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372
  1. <template>
  2. <div style="width: 100%;;display: flex;">
  3. <div style="width: 15%;;background-color: #F2F6FC;max-height: 85vh;overflow: auto;">
  4. <div style="display: flex;padding-top: 1%;padding-top: 5%;">
  5. <el-input
  6. v-model="inputNode"
  7. style="width:75%;margin-left: 5%;background-color: #ebeef5;"
  8. class="w-50 m-2"
  9. :prefix-icon="Search"
  10. />
  11. <!-- <el-button style="margin-left: 2%;width: 10%;background-color: #F7F7F7" :icon="Filter"/> -->
  12. <el-button type="primary" @click="showAdd" style="margin-left: 5%;width: 10%;" :icon="Plus"/>
  13. </div>
  14. <!-- <Plus style="width: 1em; height: 1em; margin-left:90%;cursor: pointer;color: #337ecc;" @click="showAddTree"/> -->
  15. <el-tree :expand-on-click-node="false" ref="treeRef" :filter-node-method="filterNode" :current-node-key="currentNodeKey" class="treeLeft" :data="data" @node-click="handleNodeClick" node-key="id" style="margin-left: 5%;margin-top: 5%;width: 90%;background-color: transparent;" default-expand-all :key="valueKet">
  16. <template #default="{ node, data }">
  17. <span style="justify-content: space-between;display: flex;width: 100%;align-items: center;">
  18. <div class="custom-tree-node">
  19. <!-- <el-tag v-if="data.nodeType=='MODEL'" class="ml-2" type="warning">模型</el-tag> -->
  20. <svg-icon icon-class="service1" style="color: #eebe77;" v-if="data.nodeType=='MODEL'"/>
  21. <!-- <el-tag class="ml-2">
  22. 服务
  23. </el-tag> -->
  24. <svg-icon icon-class="接口" style="color: #13E03B;" v-if="data.nodeType=='SERVICE'"/>
  25. <svg-icon icon-class="模型" style="color: red;" v-if="data.nodeType=='TREE'"/>
  26. <span>{{ node.label }}</span>
  27. </div>
  28. <div style="margin-right: 1%;position: absolute;margin-left: 75%;">
  29. <el-dropdown trigger="hover" @click.stop v-if="currentNodeKey === data.id&&data.nodeType!=='SERVICE'">
  30. <el-icon class="el-icon--right" style="color: black;">
  31. <plus />
  32. </el-icon>
  33. <template #dropdown>
  34. <el-dropdown-menu>
  35. <el-dropdown-item style="display: flex;" @click="add1Level">
  36. <el-icon class="el-icon--right" style="color: black;">
  37. <CirclePlus />
  38. </el-icon>
  39. <div>
  40. 添加同级
  41. </div>
  42. </el-dropdown-item>
  43. <el-dropdown-item style="display: flex;" @click="addNextLevel">
  44. <el-icon class="el-icon--right" style="color: black;">
  45. <Connection />
  46. </el-icon>
  47. <div>
  48. 新建下级
  49. </div>
  50. </el-dropdown-item>
  51. <divider/>
  52. <el-dropdown-item style="display: flex;" @click="delAll" divided>
  53. <el-icon class="el-icon--right" style="color: black;">
  54. <CircleClose />
  55. </el-icon>
  56. <div>
  57. 删除节点
  58. </div>
  59. </el-dropdown-item>
  60. </el-dropdown-menu>
  61. </template>
  62. </el-dropdown>
  63. </div>
  64. </span>
  65. </template>
  66. </el-tree>
  67. </div>
  68. <div style="width: 84%;margin-left: 1%;" class="tab-container">
  69. <el-tabs style="" v-model="activeName" class="demo-tabs" @tab-click="handleClick" >
  70. <el-tab-pane label="查看" name="first" style="">
  71. <div style="height: 80vh;overflow: auto;">
  72. <div style="display: flex;align-items: center;justify-content: space-between;">
  73. <div style="margin-left:1%;">{{detail.name}}</div>
  74. <div style="display: flex;">
  75. <!-- <el-button type="primary" size="mini" :icon="Promotion" @click="fetchData">运行</el-button>
  76. <el-button type="" size="mini">删除</el-button> -->
  77. </div>
  78. </div>
  79. <div style="display: flex;align-items: center;margin-left:1%;margin-top: 1%;">
  80. <el-tag v-if="detail.nodeType=='MODEL'" class="ml-2" type="warning">模型</el-tag>
  81. <el-tag v-if="detail.nodeType=='SERVICE'" class="ml-2">
  82. 服务
  83. </el-tag>
  84. <el-tag v-if="detail.nodeType=='TREE'" class="ml-2" type="success">树</el-tag>
  85. <div style="margin-left: 0.5%;">
  86. {{detail.url}}
  87. </div>
  88. <div style="margin-left: 0.5%;">
  89. <!-- <el-select class="transparent-select" v-model="valueSta" style="border-color: transparent;width: 100px;">
  90. <el-option
  91. v-for="item in options"
  92. :key="item.value"
  93. :label="item.label"
  94. :value="item.value"
  95. >
  96. <div class="flex items-center" style="display: flex;align-items: center;">
  97. <div v-if="item.label=='开发中'" style="width: 5px; height: 5px; background-color: #409EFF; border-radius: 50%;"></div>
  98. <div v-if="item.label=='运行中'" style="width: 5px; height: 5px; background-color: #67C23A; border-radius: 50%;"></div>
  99. <span style="margin-left:1%;">{{ item.label }}</span>
  100. </div>
  101. </el-option>
  102. <template #prefix>
  103. <div class="flex items-center" style="display: flex; align-items: center;">
  104. <div v-if="valueSta && options.find(opt => opt.value === valueSta)?.label === '开发中'"
  105. style="width: 5px; height: 5px; background-color: #409EFF; border-radius: 50%; margin-right: 4px;"></div>
  106. <div v-if="valueSta && options.find(opt => opt.value === valueSta)?.label === '运行中'"
  107. style="width: 5px; height: 5px; background-color: #67C23A; border-radius: 50%; margin-right: 4px;"></div>
  108. <span>{{ valueSta ? options.find(opt => opt.value === valueSta)?.label : '请选择' }}</span>
  109. </div>
  110. </template>
  111. </el-select> -->
  112. </div>
  113. </div>
  114. <div style="display: flex;width: 100%;">
  115. <div style="display: flex;margin-left: 1%;font-size: 15px;color:#909399;width:100%;margin-top: 1%;">
  116. <!-- <div>
  117. 服务分类:
  118. </div>
  119. <div style="margin-left: 0.5%;">
  120. {{detail.cateCode}}
  121. </div> -->
  122. <div style="margin-left: 0%;">
  123. 请求方式:
  124. </div>
  125. <div style="margin-left: 0.5%;">
  126. {{detail.rqtype}}
  127. </div>
  128. <div style="margin-left: 5%;">
  129. 接口类型:
  130. </div>
  131. <div style="margin-left: 0.5%;">
  132. {{detail.name}}
  133. </div>
  134. <div style="margin-left: 5%;">
  135. 返回格式:
  136. </div>
  137. <div style="margin-left: 0.5%;">
  138. {{detail.rptype}}
  139. </div>
  140. </div>
  141. </div>
  142. <div style="margin-left: 1%;font-size: 15px;color:#909399;width:100%;display: flex;margin-top: 0.5%;">
  143. <div style="margin-left: 0%;">
  144. 服务说明:
  145. </div>
  146. <div style="margin-left: 0.5%;">
  147. {{detail.name}}
  148. </div>
  149. </div>
  150. <div style="margin-left: 1%;font-size: 15px;color:#909399;width:100%;display: flex;margin-top: 0.5%;">
  151. <!-- <div style="margin-left: 0%;">
  152. 返回说明:
  153. </div>
  154. <div style="margin-left: 0.5%;">
  155. {{detail.name}}
  156. </div> -->
  157. </div>
  158. <div style="margin-top: 2.5%;margin-left: 1%;">
  159. <div>请求参数</div>
  160. <el-table
  161. style="margin-top: 1%;width: 90%;"
  162. :data="tableDataCan"
  163. :cell-style="{ textAlign: 'center', }"
  164. :header-cell-style="{ textAlign: 'center'}"
  165. :row-style="{ height: heightAll*0.01+'px',fontSize: '16px',textAlign:'center' }"
  166. border >
  167. <el-table-column prop="paramCode" label="参数字段">
  168. </el-table-column>
  169. <el-table-column prop="paramName" label="参数名称">
  170. </el-table-column>
  171. <el-table-column prop="paramType" label="参数类型" width="140">
  172. </el-table-column>
  173. <el-table-column prop="paramNote" label="参数说明">
  174. </el-table-column>
  175. </el-table>
  176. </div>
  177. <div style="margin-top: 2.5%;margin-left: 1%;">
  178. <el-tabs type="card" style="margin-top: 1%;width: 98%;">
  179. <el-tab-pane label="成功(200)">
  180. <div style="display: flex;align-items: center;line-height: 1.5;font-size: 14px;margin-left: 1%;color: #606266;">
  181. <!-- <div>HTTP状态码:</div>
  182. <div>200</div>
  183. <div style="margin-left: 5%;">内容格式:</div>
  184. <div>JSON</div> -->
  185. </div>
  186. <!-- <el-tree :data="dataReturn" :props="defaultProps" @node-click="handleNodeClick" style="margin-top: 1%;margin-left: 2%;background-color: #F7F7F7;background-color: transparent;width: 15%;" default-expand-all>
  187. <template #default="{ node, data }">
  188. <span style="display: flex;justify-content: space-between;width: 100%;align-items: center;">
  189. <span>{{ node.label }}</span>
  190. <span style="display: flex;align-items: center;">
  191. <div style="color:#67C23A;">string</div>
  192. <el-tooltip
  193. class="box-item"
  194. effect="light"
  195. content="必填"
  196. placement="top-start"
  197. >
  198. <el-button style="transform: scale(0.5);transform-origin: center;margin-left: 5%; " type="success" :icon="Check" circle size="mini" plain/>
  199. </el-tooltip>
  200. </span>
  201. </span>
  202. </template>
  203. </el-tree> -->
  204. </el-tab-pane>
  205. </el-tabs>
  206. <div style="margin-top: -1%;">
  207. <json-viewer
  208. :value="dataReturn"
  209. :expand-depth="5"
  210. copyable
  211. theme="my-theme"
  212. />
  213. <!-- <JsonEditorVue
  214. v-model="dataReturn"
  215. style="height:98%;width: 100%;"
  216. :mode="'code'"
  217. :showBtns="false"
  218. :options="{
  219. navigationBar: false, // 隐藏顶部导航栏
  220. statusBar: false, // 隐藏底部状态栏
  221. mode: 'code', // 仅保留代码编辑模式
  222. mainMenuBar: false // 隐藏主菜单栏
  223. }"
  224. lang="zh"
  225. /> -->
  226. </div>
  227. </div>
  228. <div style="margin-top: 2.5%;margin-left: 1%;padding-bottom: 1%;">
  229. <div>响应示例</div><el-tabs type="card" style="margin-top: 1%;">
  230. <el-tab-pane label="成功示例">
  231. <div style="overflow: auto;height: 30vh">
  232. <json-viewer
  233. :value="dataJsonXiang"
  234. :expand-depth="5"
  235. copyable
  236. theme="my-theme"
  237. />
  238. </div>
  239. </el-tab-pane>
  240. </el-tabs>
  241. </div>
  242. </div>
  243. </el-tab-pane>
  244. <el-tab-pane label="修改" name="second" style="" :disabled="isEdit">
  245. <div style="overflow: auto;height: 80vh;">
  246. <div style="display: flex;margin-top: 1%;">
  247. <el-button type="primary" @click="saveEditService" style="margin-left: 80%;z-index: 1000;" :disabled="isEdit">提交</el-button>
  248. <el-button type="danger" @click="delSer" style="margin-left: 1%;z-index: 1000;" :disabled="isEdit">删除</el-button>
  249. </div>
  250. <el-form size="mini" :key="tableKey" style="margin-top: -2%;width: 98%;" :model="formJi" label-position="right" ref="formRefJi" label-width="120px" :rules="rulesJi">
  251. <el-row :gutter="48">
  252. <el-col :span="10">
  253. <el-form-item label="服务名称:" prop="name" style="">
  254. <div style="display: flex;width: 100%;justify-content: space-between;">
  255. <el-input :disabled="isEdit" v-model="formJi.name" style="width: 100%;"/>
  256. </div>
  257. </el-form-item>
  258. </el-col>
  259. <el-col :span="6">
  260. <el-form-item label="接口类型:" prop="" style="">
  261. <div style="display: flex;width: 100%;justify-content: space-between;">
  262. <el-select
  263. v-model="formJi.type"
  264. :disabled="isEdit"
  265. style="width: 100%;margin-left: 0%;"
  266. >
  267. <el-option
  268. v-for="item in optionsType"
  269. :key="item.value"
  270. :label="item.label"
  271. :value="item.value"
  272. />
  273. </el-select>
  274. <div style="display: flex;">
  275. </div>
  276. </div>
  277. </el-form-item>
  278. </el-col>
  279. </el-row>
  280. <el-row :gutter="48">
  281. <el-col :span="10">
  282. <el-form-item label="接口地址:" prop="url" style="">
  283. <el-input
  284. v-model="formJi.url"
  285. :disabled="isEdit"
  286. style="width: 100%;"
  287. placeholder=""
  288. class="input-with-select"
  289. >
  290. </el-input>
  291. </el-form-item>
  292. </el-col>
  293. <el-col :span="6">
  294. <el-form-item label="请求方式:" prop="" style="">
  295. <el-select
  296. v-model="formJi.rqtype"
  297. :disabled="isEdit"
  298. style="width: 100%;margin-left: 0%;"
  299. >
  300. <el-option
  301. v-for="item in optionsRqtype"
  302. :key="item.value"
  303. :label="item.label"
  304. :value="item.value"
  305. />
  306. </el-select>
  307. </el-form-item>
  308. </el-col>
  309. </el-row>
  310. <el-row :gutter="48">
  311. <el-col :span="10">
  312. <el-form-item label="响应类型:" prop="" style="display: flex; align-items: center;">
  313. <el-radio-group :disabled="isEdit" v-model="formJi.rptype" class="ml-4" style="display: inline-flex; align-items: center;">
  314. <el-radio label="1" size="large" style="display: inline-flex; align-items: center;">
  315. <span style="position: relative; top: -1px">JSON</span> <!-- 微调文字位置 -->
  316. </el-radio>
  317. <el-radio label="2" size="large" style="display: inline-flex; align-items: center;">
  318. <span style="position: relative; top: -1px">XML</span>
  319. </el-radio>
  320. <el-radio label="3" size="large" style="display: inline-flex; align-items: center;">
  321. <span style="position: relative; top: -1px">HTML</span>
  322. </el-radio>
  323. </el-radio-group>
  324. </el-form-item>
  325. </el-col>
  326. <el-col :span="6">
  327. <el-form-item label="服务分类:" prop="cateCode" style="">
  328. <el-cascader :disabled="isEdit" v-model="formJi.cateCode" :options="cascaderOptions" :props="props1" clearable style="width: 100%;"></el-cascader>
  329. </el-form-item>
  330. </el-col>
  331. <!-- <el-col :span="8">
  332. <el-form-item label="请求方式:" prop="name" style="">
  333. <el-select
  334. v-model="formJi.type"
  335. :disabled="isEdit"
  336. style="width: 100%;margin-left: 0%;"
  337. >
  338. <el-option
  339. v-for="item in optionsType"
  340. :key="item.value"
  341. :label="item.label"
  342. :value="item.value"
  343. />
  344. </el-select>
  345. </el-form-item>
  346. </el-col> -->
  347. </el-row>
  348. <el-row :gutter="48">
  349. <el-col :span="13">
  350. <el-form-item label="服务说明:">
  351. <el-input :disabled="isEdit" v-model="formJi.intro" style="width: 100%;" :rows="3" resize="none" type="textarea"/>
  352. </el-form-item>
  353. </el-col>
  354. </el-row>
  355. </el-form>
  356. <div style="margin-top: 2%;">
  357. <div style="display: flex;justify-content: space-between;align-items: center;">
  358. <div>
  359. 请求参数
  360. </div>
  361. <div style="display: flex;justify-content: flex-end;margin-right: 2%;">
  362. <el-button @click="addPa" style="margin-top: 1%;" type="success" size="mini" plain>新增参数</el-button>
  363. </div>
  364. </div>
  365. <div>
  366. <el-table
  367. style="margin-top: 1%;width: 98%;"
  368. :data="tableDataCan"
  369. :cell-style="{ textAlign: 'center',padding:'2px 0' }"
  370. :header-cell-style="{ textAlign: 'center'}"
  371. :row-style="{ height: heightAll*0.01+'px',fontSize: '16px',textAlign:'center' }"
  372. border >
  373. <el-table-column prop="itemName" label="参数字段">
  374. <template #default="scope">
  375. <div style="width: 100%;">
  376. <el-input placeholder="请填写参数编码" type="primary" class="noBor" v-model="scope.row.paramCode" size="mini" text style="margin-left: 0%;border: transparent;"></el-input>
  377. </div>
  378. </template>
  379. </el-table-column>
  380. <el-table-column prop="itemName" label="参数名称">
  381. <template #default="scope">
  382. <div style="width: 100%;">
  383. <el-input placeholder="请填写参数名称" type="primary" class="noBor" v-model="scope.row.itemName" size="mini" text style="margin-left: 0%;"></el-input>
  384. </div>
  385. </template>
  386. </el-table-column>
  387. <el-table-column prop="itemName" label="参数类型" width="200">
  388. <template #default="scope">
  389. <div style="width: 100%;">
  390. <el-select
  391. v-model="scope.row.paramType"
  392. class="noBorSel"
  393. placeholder=""
  394. style="width: 100%;margin-left: 0%;"
  395. >
  396. <el-option
  397. v-for="item in optionsCan"
  398. :key="item.value"
  399. :label="item.label"
  400. :value="item.value"
  401. />
  402. </el-select>
  403. </div>
  404. </template>
  405. </el-table-column>
  406. <el-table-column prop="itemName" label="参数说明" >
  407. <template #default="scope">
  408. <div style="width: 100%;">
  409. <el-input type="primary" class="noBor" v-model="scope.row.paramNote" size="mini" text style="margin-left: 0%;"></el-input>
  410. </div>
  411. </template>
  412. </el-table-column>
  413. <el-table-column prop="address" label="操作" width="100">
  414. <template #default="scope">
  415. <div style="width: 100%;">
  416. <el-button type="danger" @click="delCan(scope.$index)" size="mini" text style="margin-left: 0%;">删除</el-button>
  417. </div>
  418. </template>
  419. </el-table-column>
  420. </el-table>
  421. </div>
  422. </div>
  423. <div style="margin-top: 2%;">
  424. <!-- <div>返回响应</div> -->
  425. <div style="color: #909399;margin-left: 7%;margin-top:1%;">此处填写本服务接口响应信息描述</div>
  426. <el-tabs type="card" style="margin-top: -1.5%;width: 98%;">
  427. <el-tab-pane label="响应内容">
  428. <div style="display: flex; flex-direction: column;">
  429. <!-- <el-tree :data="data" :props="defaultProps" @node-click="handleNodeClick" style="margin-top: 1%;margin-left: 2%;background-color: #F7F7F7;background-color: transparent;width: 15%;" default-expand-all>
  430. <template #default="{ node, data }">
  431. <span style="display: flex;justify-content: space-between;width: 100%;align-items: center;">
  432. <span><el-input v-model="node.label" size="mini"/></span>
  433. <span style="display: flex;align-items: center;">
  434. <el-tooltip
  435. class="box-item"
  436. effect="light"
  437. content="是否必填"
  438. placement="top-start"
  439. >
  440. <el-checkbox v-model="checked1" label="" size="large" />
  441. </el-tooltip>
  442. <el-select
  443. v-model="formJi.type"
  444. :disabled="isEdit"
  445. style="width: 100%;margin-left: -1%;"
  446. >
  447. <el-option
  448. v-for="item in optionsType"
  449. :key="item.value"
  450. :label="item.label"
  451. :value="item.value"
  452. />
  453. </el-select>
  454. <el-tooltip
  455. class="box-item"
  456. effect="light"
  457. content="是否允许null"
  458. placement="top-start"
  459. >
  460. <el-checkbox v-model="checked1" label="" size="large" />
  461. </el-tooltip>
  462. </span>
  463. </span>
  464. </template>
  465. </el-tree> -->
  466. </div>
  467. </el-tab-pane>
  468. </el-tabs>
  469. <div style="overflow: auto;height: 20vh;margin-top: -1%;">
  470. <!-- <JsonEditorVue
  471. v-model="dataJsonXiang"
  472. style="height:98%;width: 98%;"
  473. :mode="'code'"
  474. :showBtns="false"
  475. :options="{
  476. navigationBar: false, // 隐藏顶部导航栏
  477. statusBar: false, // 隐藏底部状态栏
  478. mode: 'code', // 仅保留代码编辑模式
  479. mainMenuBar: false // 隐藏主菜单栏
  480. }"
  481. lang="zh"
  482. /> -->
  483. <el-input placeholder="请输入示例" :rows="8" type="textarea" v-model="dataJsonXiang" size="mini" text style="margin-top: 0%;width: 98%;" ></el-input>
  484. </div>
  485. </div>
  486. <div style="margin-top: 2.5%;margin-left: 0%;padding-bottom: 1%;">
  487. <el-tabs type="card" style="margin-top: -1.5%;width: 98%;">
  488. <el-tab-pane label="使用说明">
  489. </el-tab-pane>
  490. </el-tabs>
  491. <el-input placeholder="请输入示例" :rows="8" type="textarea" v-model="example" size="mini" text style="margin-top: -1%;width: 98%;" ></el-input>
  492. </div>
  493. </div>
  494. </el-tab-pane>
  495. </el-tabs>
  496. <el-dialog @close="clearAdd" v-model="dialogVisible" title="新增节点" width="70%" destroy-on-close :key="tableKey">
  497. <div style="overflow: auto;height: 80vh;">
  498. <el-form size="mini" :key="tableKey" style="margin-top: 1%;width: 98%;" :model="formAdd" label-position="right" ref="formRefAdd" label-width="120px" :rules="rulesAdd">
  499. <el-row :gutter="48">
  500. <el-col :span="10">
  501. <el-form-item label="服务名称:" prop="name" style="">
  502. <div style="display: flex;width: 100%;justify-content: space-between;">
  503. <el-input v-model="formAdd.name" style="width: 100%;"/>
  504. </div>
  505. </el-form-item>
  506. </el-col>
  507. <el-col :span="6">
  508. <el-form-item label="接口类型:" prop="" style="">
  509. <div style="display: flex;width: 100%;justify-content: space-between;">
  510. <el-select
  511. v-model="formAdd.type"
  512. :disabled="isEdit"
  513. style="width: 100%;margin-left: 0%;"
  514. >
  515. <el-option
  516. v-for="item in optionsType"
  517. :key="item.value"
  518. :label="item.label"
  519. :value="item.value"
  520. />
  521. </el-select>
  522. <div style="display: flex;">
  523. </div>
  524. </div>
  525. </el-form-item>
  526. </el-col>
  527. </el-row>
  528. <el-row :gutter="48">
  529. <el-col :span="10">
  530. <el-form-item label="接口地址:" prop="url" style="">
  531. <el-input
  532. v-model="formAdd.url"
  533. style="width: 100%;"
  534. placeholder=""
  535. class="input-with-select"
  536. >
  537. </el-input>
  538. </el-form-item>
  539. </el-col>
  540. <el-col :span="6">
  541. <el-form-item label="请求方式:" prop="" style="">
  542. <el-select
  543. v-model="formAdd.rqtype"
  544. :disabled="isEdit"
  545. style="width: 100%;margin-left: 0%;"
  546. >
  547. <el-option
  548. v-for="item in optionsRqtype"
  549. :key="item.value"
  550. :label="item.label"
  551. :value="item.value"
  552. />
  553. </el-select>
  554. </el-form-item>
  555. </el-col>
  556. </el-row>
  557. <el-row :gutter="48">
  558. <el-col :span="10">
  559. <el-form-item label="所属模型:" prop="mdid" style="">
  560. <el-tree-select
  561. v-model="formAdd.mdid"
  562. :data="optionsMdid"
  563. check-strictly
  564. :render-after-expand="false"
  565. style="width: 100%"
  566. />
  567. <!-- <el-select
  568. v-model="formAdd.mdid"
  569. style="width: 100%;margin-left: 0%;"
  570. >
  571. <el-option
  572. v-for="item in optionsMdid"
  573. :key="item.value"
  574. :label="item.label"
  575. :value="item.id"
  576. />
  577. </el-select> -->
  578. </el-form-item>
  579. </el-col>
  580. </el-row>
  581. <el-row :gutter="48">
  582. <el-col :span="10">
  583. <el-form-item label="响应类型:" prop="" style="display: flex; align-items: center;">
  584. <el-radio-group v-model="formAdd.rptype" class="ml-4" style="display: inline-flex; align-items: center;">
  585. <el-radio label="1" size="large" style="display: inline-flex; align-items: center;">
  586. <span style="position: relative; top: -1px">JSON</span> <!-- 微调文字位置 -->
  587. </el-radio>
  588. <el-radio label="2" size="large" style="display: inline-flex; align-items: center;">
  589. <span style="position: relative; top: -1px">XML</span>
  590. </el-radio>
  591. <el-radio label="3" size="large" style="display: inline-flex; align-items: center;">
  592. <span style="position: relative; top: -1px">HTML</span>
  593. </el-radio>
  594. </el-radio-group>
  595. </el-form-item>
  596. </el-col>
  597. <el-col :span="6">
  598. <el-form-item label="服务分类:" prop="cateCode" style="">
  599. <el-cascader v-model="formAdd.cateCode" :options="cascaderOptions" :props="props1" clearable style="width: 100%;"></el-cascader>
  600. </el-form-item>
  601. </el-col>
  602. <!-- <el-col :span="8">
  603. <el-form-item label="请求方式:" prop="name" style="">
  604. <el-select
  605. v-model="formJi.type"
  606. :disabled="isEdit"
  607. style="width: 100%;margin-left: 0%;"
  608. >
  609. <el-option
  610. v-for="item in optionsType"
  611. :key="item.value"
  612. :label="item.label"
  613. :value="item.value"
  614. />
  615. </el-select>
  616. </el-form-item>
  617. </el-col> -->
  618. </el-row>
  619. <el-row :gutter="48">
  620. <el-col :span="13">
  621. <el-form-item label="服务说明:">
  622. <el-input v-model="formAdd.intro" style="width: 100%;" :rows="3" resize="none" type="textarea"/>
  623. </el-form-item>
  624. </el-col>
  625. </el-row>
  626. </el-form>
  627. <div style="margin-top: 2%;">
  628. <div style="display: flex;justify-content: space-between;align-items: center;">
  629. <div>
  630. 请求参数
  631. </div>
  632. <div style="display: flex;justify-content: flex-end;margin-right: 2%;">
  633. <el-button @click="addCanAdd" style="margin-top: 1%;" type="success" size="mini" plain>新增参数</el-button>
  634. </div>
  635. </div>
  636. <div>
  637. <el-table
  638. style="margin-top: 1%;width: 98%;"
  639. :data="tableDataCanAdd"
  640. :cell-style="{ textAlign: 'center',padding:'2px 0' }"
  641. :header-cell-style="{ textAlign: 'center'}"
  642. :row-style="{ height: heightAll*0.01+'px',fontSize: '16px',textAlign:'center' }"
  643. border >
  644. <el-table-column prop="itemName" label="参数字段">
  645. <template #default="scope">
  646. <div style="width: 100%;">
  647. <el-input placeholder="请填写参数编码" type="primary" class="noBor" v-model="scope.row.paramCode" size="mini" text style="margin-left: 0%;border: transparent;"></el-input>
  648. </div>
  649. </template>
  650. </el-table-column>
  651. <el-table-column prop="itemName" label="参数名称">
  652. <template #default="scope">
  653. <div style="width: 100%;">
  654. <el-input placeholder="请填写参数名称" type="primary" class="noBor" v-model="scope.row.paramName" size="mini" text style="margin-left: 0%;"></el-input>
  655. </div>
  656. </template>
  657. </el-table-column>
  658. <el-table-column prop="itemName" label="参数类型" width="200">
  659. <template #default="scope">
  660. <div style="width: 100%;">
  661. <el-select
  662. v-model="scope.row.paramType"
  663. class="noBorSel"
  664. placeholder=""
  665. style="width: 100%;margin-left: 0%;"
  666. >
  667. <el-option
  668. v-for="item in optionsCan"
  669. :key="item.value"
  670. :label="item.label"
  671. :value="item.value"
  672. />
  673. </el-select>
  674. </div>
  675. </template>
  676. </el-table-column>
  677. <el-table-column prop="itemName" label="参数说明" >
  678. <template #default="scope">
  679. <div style="width: 100%;">
  680. <el-input type="primary" class="noBor" v-model="scope.row.paramNote" size="mini" text style="margin-left: 0%;"></el-input>
  681. </div>
  682. </template>
  683. </el-table-column>
  684. <el-table-column prop="address" label="操作" width="100">
  685. <template #default="scope">
  686. <div style="width: 100%;">
  687. <el-button type="danger" @click="delCanAdd(scope.$index)" size="mini" text style="margin-left: 0%;">删除</el-button>
  688. </div>
  689. </template>
  690. </el-table-column>
  691. </el-table>
  692. </div>
  693. </div>
  694. <div style="margin-top: 2%;">
  695. <!-- <div>返回响应</div> -->
  696. <div style="color: #909399;margin-left: 8%;margin-top:1%;">此处填写本服务接口响应信息描述</div>
  697. <el-tabs type="card" style="margin-top: -2%;width: 98%;">
  698. <el-tab-pane label="响应内容">
  699. <div style="display: flex; flex-direction: column;">
  700. </div>
  701. </el-tab-pane>
  702. </el-tabs>
  703. <div style="overflow: auto;height: 20vh;margin-top: -1%;">
  704. <el-input placeholder="请输入示例" :rows="8" type="textarea" v-model="JsonAdd" size="mini" text style="margin-top: 0%;width: 98%;" ></el-input>
  705. </div>
  706. </div>
  707. <div style="margin-top: 2.5%;margin-left: 0%;padding-bottom: 1%;">
  708. <el-tabs type="card" style="margin-top: -1.5%;width: 98%;">
  709. <el-tab-pane label="使用说明">
  710. </el-tab-pane>
  711. </el-tabs>
  712. <el-input placeholder="请输入示例" :rows="8" type="textarea" v-model="exampleAdd" size="mini" text style="margin-top: -1%;width: 98%;" ></el-input>
  713. </div>
  714. </div>
  715. <template #footer>
  716. <span class="dialog-footer">
  717. <el-button size="mini" @click="dialogVisible = false">取消</el-button>
  718. <el-button type="primary" @click="addSer" size="mini">
  719. 提交
  720. </el-button>
  721. </span>
  722. </template>
  723. </el-dialog>
  724. <el-dialog @close="clearFromLev" title="添加目录" v-model="dialogVisibleLevel" width="30%" destroy-on-close :key="tableKey">
  725. <el-form size="mini" :key="tableKey" style="margin-top: 1%;width: 90%;" :model="formLev" label-position="right" ref="formRefLev" label-width="120px" :rules="rulesLev">
  726. <el-form-item label="名称:" prop="itemName" style="">
  727. <el-input v-model="formLev.itemName" style="width: 100%;"/>
  728. </el-form-item>
  729. <el-form-item label="说明:" prop="itemNotes" style="">
  730. <el-input v-model="formLev.itemNotes" style="width: 100%;"/>
  731. </el-form-item>
  732. <el-form-item label="排序:" prop="itemNo" style="">
  733. <el-input-number v-model="formLev.itemNo" style="width: 100%;" :min="1" :max="10000" @change="handleChange" />
  734. </el-form-item>
  735. </el-form>
  736. <template #footer>
  737. <span class="dialog-footer">
  738. <el-button size="mini" @click="dialogVisibleLevel = false">取消</el-button>
  739. <el-button type="primary" @click="saveAdd1Level" size="mini" v-if="show1Lev">
  740. 提交
  741. </el-button>
  742. <el-button type="primary" @click="saveAddNextLevel" size="mini" v-if="!show1Lev">
  743. 提交
  744. </el-button>
  745. </span>
  746. </template>
  747. </el-dialog>
  748. </div>
  749. </div>
  750. </template>
  751. <script setup>
  752. import {getCatalog} from "@/api/service/catalog";
  753. import { Plus,Search,Filter,Promotion,Check } from '@element-plus/icons-vue'
  754. import { reactive } from 'vue'
  755. import { modelTreeSelect,getSerDe,addService,addParam,editService,editParam,addServiceParam,delService,getTreeDe,addTree,deTree } from "@/api/service/info";
  756. import { ref, onMounted, onUnmounted, nextTick,onBeforeMount } from 'vue';
  757. import JsonViewer from 'vue-json-viewer'
  758. import 'vue-json-viewer/style.css'
  759. import JsonEditorVue from 'json-editor-vue3'
  760. import { cloneDeep } from 'lodash'
  761. const { proxy } = getCurrentInstance();
  762. const JsonAdd= ref(JSON.stringify({ data: "初始值1" }))
  763. const exampleAdd = ref('')
  764. const dialogVisibleLevel = ref(false)
  765. const detail = ref({
  766. name:'',
  767. rqtype:'',
  768. rptype:''
  769. })
  770. const show1Lev = ref(true)
  771. const inputNode =ref('')
  772. const isEdit = ref(true)
  773. const dataReturn = ref({})
  774. const optionsCan = ref([
  775. {
  776. label:"string",
  777. value:'string'
  778. },
  779. {
  780. label:"int",
  781. value:'int'
  782. },
  783. {
  784. label:"boolean",
  785. value:'boolean'
  786. },
  787. {
  788. label:"array",
  789. value:'array'
  790. },
  791. {
  792. label:"object",
  793. value:'object'
  794. },
  795. {
  796. label:"number",
  797. value:'number'
  798. },
  799. {
  800. label:"null",
  801. value:'null'
  802. },
  803. {
  804. label:"any",
  805. value:'any'
  806. },
  807. ])
  808. const currentNodeKey = ref('')
  809. const options = ref([
  810. {label:'开发中',
  811. value:'1'
  812. },
  813. {label:'运行中',
  814. value:'2'
  815. },
  816. ])
  817. const dataJsonXiang = ref([])
  818. const parTree = ref({})
  819. const valueKet = ref(0)
  820. const tableDataCan = ref([
  821. {
  822. itemName:'',
  823. itemCode:'',
  824. paramType:'',
  825. paramNote:''
  826. }
  827. ])
  828. const optionsMdid = ref([])
  829. const optionsRqtype = ref([
  830. {label:'GET',
  831. value:'GET'
  832. },
  833. {label:'POST',
  834. value:'POST'
  835. },
  836. ])
  837. const optionsType= ref([
  838. {label:'RESTful',
  839. value:'RESTful'
  840. },
  841. {label:'WebService',
  842. value:'WebService'
  843. },
  844. {label:'HTTP',
  845. value:'HTTP'
  846. },
  847. {label:'WebSocket',
  848. value:'WebSocket'
  849. },
  850. ])
  851. const data = ref([])
  852. const select = ref('1')
  853. const activeName = ref('first')
  854. const title = ref('')
  855. const titleTree = ref('')
  856. const currentPage = ref(1)
  857. const total = ref(1)
  858. const tableData = ref([])
  859. const tableheight = window.innerHeight*0.7
  860. const heightAll = window.innerHeight
  861. const dialogVisible = ref(false)
  862. const dialogVisibleTree = ref(false)
  863. const isAdd = ref(false)
  864. const isAddTa = ref(false)
  865. const treeId = ref('');
  866. const valueSta = ref('1');
  867. const example = ref('');
  868. const tableDataCanAdd = ref([
  869. {
  870. itemName:'',
  871. itemCode:'',
  872. paramType:'',
  873. paramNote:''
  874. }
  875. ])
  876. const formZu = ref({
  877. itemName:'',
  878. itemTp:'',
  879. itemEn:'',
  880. itemTp:'',
  881. itemDataTp:'',
  882. itemDefaultVal:'',
  883. itemUnit:'',
  884. itemNotes:'',
  885. });
  886. const parId= ref('')
  887. const formJi = ref({
  888. name:'',
  889. cateCode:'',
  890. type:'',
  891. url:'',
  892. rqtype:'',
  893. rptype:'',
  894. intro:'',
  895. });
  896. const rulesJi = reactive({
  897. name: [{ required: true, message: '必填', trigger: 'blur' }],
  898. url: [{ required: true, message: '必填', trigger: 'blur' }],
  899. cateCode: [{ required: true, message: '必填', trigger: 'blur' }],
  900. });
  901. const formRefJi = ref();
  902. const formAdd = ref({
  903. name:'',
  904. cateCode:'',
  905. type:'',
  906. url:'',
  907. rqtype:'',
  908. rptype:'',
  909. intro:'',
  910. mdid:''
  911. });
  912. const rulesAdd = reactive({
  913. mdid: [{ required: true, message: '必填', trigger: 'blur' }],
  914. name: [{ required: true, message: '必填', trigger: 'blur' }],
  915. url: [{ required: true, message: '必填', trigger: 'blur' }],
  916. cateCode: [{ required: true, message: '必填', trigger: 'blur' }],
  917. });
  918. const formRefAdd = ref();
  919. const treeRef = ref(null);
  920. const formTree = ref({
  921. itemName:'',
  922. catePid:'',
  923. itemNo:'',
  924. itemNotes:''
  925. });
  926. const rulesTree = reactive({
  927. itemNo: [{ required: true, message: '必填', trigger: 'blur' }],
  928. catePid: [{ required: true, message: '必填', trigger: 'blur' }],
  929. itemName: [{ required: true, message: '必填', trigger: 'blur' }],
  930. });
  931. const formRefTree = ref();
  932. const formLev = ref({
  933. itemName:'',
  934. itemNo:'',
  935. itemNotes:'',
  936. });
  937. const rulesLev = reactive({
  938. itemNotes: [{ required: true, message: '必填', trigger: 'blur' }],
  939. itemNo: [{ required: true, message: '必填', trigger: 'blur' }],
  940. itemName: [{ required: true, message: '必填', trigger: 'blur' }],
  941. });
  942. const formRefLev = ref();
  943. const cascaderOptions = ref([])
  944. const props1 = ref({
  945. checkStrictly: true,
  946. })
  947. const detailJson = ref([])
  948. watch(inputNode, (val) => {
  949. treeRef.value?.filter(val); // 调用树的过滤方法
  950. });
  951. const filterNode = (value, data) => {
  952. if (!value) return true; // 空搜索时显示所有节点
  953. return data.label.includes(value); // 检查节点标签是否包含关键字
  954. };
  955. function filterModelNodes(nodes) {
  956. if (!Array.isArray(nodes)) return [];
  957. const result = [];
  958. for (const node of nodes) {
  959. // 递归处理子节点(如果有)
  960. const filteredChildren = node.children ? filterModelNodes(node.children) : [];
  961. if (node.nodeType === 'MODEL') {
  962. // 保留当前节点,并更新其子节点
  963. node.value = node.id
  964. result.push({
  965. ...node,
  966. children: filteredChildren
  967. });
  968. } else {
  969. // 删除当前节点,将其子节点提升到当前层级
  970. result.push(...filteredChildren);
  971. }
  972. }
  973. return result;
  974. }
  975. function clearAdd(){
  976. formAdd.value = {
  977. name:'',
  978. cateCode:'',
  979. type:'',
  980. url:'',
  981. rqtype:'',
  982. rptype:'',
  983. intro:'',
  984. mdid:''
  985. }
  986. tableDataCanAdd.value = {
  987. itemName:'',
  988. itemCode:'',
  989. paramType:'',
  990. paramNote:''
  991. }
  992. JsonAdd.value = ''
  993. exampleAdd.value = ''
  994. }
  995. function extractModelNodesDFSIterative(root) {
  996. const result = [];
  997. const stack = root;
  998. while (stack.length > 0) {
  999. const node = stack.pop();
  1000. if (node.nodeType === 'MODEL') {
  1001. result.push(node);
  1002. }
  1003. // 子节点逆序入栈(保证从左到右遍历)
  1004. if (node.children) {
  1005. for (let i = node.children.length - 1; i >= 0; i--) {
  1006. stack.push(node.children[i]);
  1007. }
  1008. }
  1009. }
  1010. return result;
  1011. }
  1012. function delAll(){
  1013. proxy.$modal.confirm('是否确认删除?').then(function () {
  1014. return deTree(parTree.value.id);
  1015. }).then(() => {
  1016. getTreeLeft();
  1017. proxy.$modal.msgSuccess("删除成功");
  1018. dialogVisibleLevel.value = false
  1019. }).catch(() => {});
  1020. }
  1021. function clearFromLev(){
  1022. formLev.value = {
  1023. itemName:'',
  1024. itemNo:'',
  1025. itemNotes:'',
  1026. }
  1027. }
  1028. function addNextLevel(){
  1029. dialogVisibleLevel.value = true
  1030. show1Lev.value = false
  1031. }
  1032. function saveAddNextLevel(){
  1033. formRefLev.value.validate((valid) => {
  1034. if(valid){
  1035. var par = formLev.value
  1036. par.treeType = parTree.value.nodeType
  1037. par.treePid = parTree.value.id
  1038. addTree(par).then(res=>{
  1039. if(res.code===200){
  1040. proxy.$modal.msgSuccess("新增成功");
  1041. getTreeLeft()
  1042. dialogVisibleLevel.value = false
  1043. }
  1044. })
  1045. }
  1046. });
  1047. }
  1048. function add1Level(){
  1049. dialogVisibleLevel.value = true
  1050. show1Lev.value = true
  1051. }
  1052. function saveAdd1Level(){
  1053. formRefLev.value.validate((valid) => {
  1054. if(valid){
  1055. var par = formLev.value
  1056. par.treeType = parTree.value.nodeType
  1057. par.treePid = parTree.value.pid
  1058. addTree(par).then(res=>{
  1059. if(res.code===200){
  1060. proxy.$modal.msgSuccess("新增成功");
  1061. getTreeLeft()
  1062. dialogVisibleLevel.value = false
  1063. }
  1064. })
  1065. }
  1066. });
  1067. }
  1068. async function delSer(){
  1069. proxy.$modal.confirm('是否确认删除?').then(function () {
  1070. return delService(parId.value.id);
  1071. }).then(() => {
  1072. getTreeLeft();
  1073. proxy.$modal.msgSuccess("删除成功");
  1074. }).catch(() => {});
  1075. }
  1076. async function saveEditService(){
  1077. console.log(JsonAdd.value)
  1078. var valid
  1079. await formRefJi.value.validate((valid1) => {
  1080. valid = valid1
  1081. });
  1082. console.log(valid)
  1083. if(valid){
  1084. var par = formJi.value
  1085. par.example = example.value
  1086. par.rpcontent = dataJsonXiang.value
  1087. par.cateCode = par.cateCode[0]
  1088. console.log(par)
  1089. await editService(par).then(res=>{
  1090. if(res.code===200){
  1091. var parCan = tableDataCan.value
  1092. // parCan.srvId = parId.value.srvId
  1093. addServiceParam(parCan).then(res1=>{
  1094. if(res1.code===200){
  1095. proxy.$modal.msgSuccess("修改成功");
  1096. getTreeLeft()
  1097. }
  1098. })
  1099. }
  1100. })
  1101. }
  1102. }
  1103. async function addSer(){
  1104. console.log(JsonAdd.value)
  1105. var valid
  1106. await formRefAdd.value.validate((valid1) => {
  1107. valid = valid1
  1108. });
  1109. console.log(valid)
  1110. if(valid){
  1111. var par = formAdd.value
  1112. par.example = exampleAdd.value
  1113. par.rpcontent = JsonAdd.value
  1114. par.cateCode = par.cateCode[0]
  1115. console.log(par)
  1116. await addService(par).then(res=>{
  1117. if(res.code===200){
  1118. var parCan = tableDataCanAdd.value
  1119. parCan.srvId = res.data.srvId
  1120. addServiceParam(parCan).then(res1=>{
  1121. if(res1.code===200){
  1122. proxy.$modal.msgSuccess("新增成功");
  1123. getTreeLeft()
  1124. }
  1125. })
  1126. }
  1127. })
  1128. }
  1129. }
  1130. function showAdd(){
  1131. dialogVisible.value = true
  1132. }
  1133. async function handleNodeClick(node,data,event){
  1134. parTree.value = data.data
  1135. currentNodeKey.value = data.data.id
  1136. console.log(data.data.nodeType)
  1137. isEdit.value = false
  1138. parId.value = data.data
  1139. await getSerDe(data.data.id).then(res=>{
  1140. detail.value = res.data.ptService
  1141. tableDataCan.value = res.data.list
  1142. dataReturn.value = res.data.returnList
  1143. console.log(tableDataCan.value)
  1144. dataJsonXiang.value = res.data.ptService.rpcontent
  1145. formJi.value = res.data.ptService
  1146. example.value = res.data.ptService.example
  1147. })
  1148. detail.value.nodeType = data.data.nodeType
  1149. }
  1150. async function getTreeLeft(){
  1151. var par
  1152. await modelTreeSelect().then(res=>{
  1153. par = res.data
  1154. data.value = res.data
  1155. })
  1156. optionsMdid.value = filterModelNodes(par)
  1157. console.log(optionsMdid.value)
  1158. }
  1159. function renameTreeProperties(tree) {
  1160. // 深拷贝避免修改原始数据(可选,根据需求)
  1161. const newTree = cloneDeep(tree); // 使用 lodash
  1162. // 或:const newTree = JSON.parse(JSON.stringify(tree)); // 原生方法(不兼容函数等)
  1163. // 递归处理函数
  1164. const processNode = (node) => {
  1165. // 重命名属性
  1166. if ('cateName' in node) {
  1167. node.label = node.cateName;
  1168. delete node.cateName;
  1169. }
  1170. if ('cateCode' in node) {
  1171. node.value = node.cateCode;
  1172. delete node.cateCode;
  1173. }
  1174. // 递归处理子节点
  1175. if (node.children && node.children.length > 0) {
  1176. node.children.forEach(child => processNode(child));
  1177. }
  1178. };
  1179. // 遍历根节点
  1180. newTree.forEach(rootNode => processNode(rootNode));
  1181. return newTree;
  1182. }
  1183. function fetchData() {
  1184. getCatalog().then((r) => {
  1185. cascaderOptions.value = renameTreeProperties(buildTree(r.data))
  1186. console.log(cascaderOptions.value)
  1187. });
  1188. }
  1189. function buildTree(flatData, rootValue = '0') {
  1190. const nodeMap = new Map();
  1191. const tree = [];
  1192. flatData.forEach(item => {
  1193. nodeMap.set(item.cateCode, { ...item, children: [] });
  1194. });
  1195. for (const [code, node] of nodeMap) {
  1196. const parentCode = node.catePcode;
  1197. if (parentCode === rootValue || !parentCode) {
  1198. tree.push(node);
  1199. continue;
  1200. }
  1201. const parent = nodeMap.get(parentCode);
  1202. if (parent) {
  1203. parent.children.push(node);
  1204. } else {
  1205. console.warn(`Orphan node detected: ${code}. Parent ${parentCode} not found`);
  1206. }
  1207. }
  1208. return tree;
  1209. }
  1210. function addPa(){
  1211. var par = {
  1212. itemName:''
  1213. }
  1214. tableDataCan.value.push(par)
  1215. }
  1216. function delCan(index){
  1217. tableDataCan.value.splice(index, 1)
  1218. }
  1219. function addCanAdd(){
  1220. var par = {
  1221. itemName:''
  1222. }
  1223. tableDataCanAdd.value.push(par)
  1224. }
  1225. function delCanAdd(index){
  1226. tableDataCanAdd.value.splice(index, 1)
  1227. }
  1228. onMounted(() => {
  1229. fetchData()
  1230. getTreeLeft()
  1231. });
  1232. </script>
  1233. <style scoped>
  1234. .noBorSel :deep(.el-select__wrapper){
  1235. box-shadow: none !important; /* 去除阴影边框 */
  1236. border: 1px solid transparent !important; /* 设置透明边框 */
  1237. background-color: transparent !important; /* 可选:透明背景 */
  1238. }
  1239. .noBor :deep(.el-input__wrapper) {
  1240. box-shadow: none !important; /* 去除阴影边框 */
  1241. border: 1px solid transparent !important; /* 设置透明边框 */
  1242. background-color: transparent !important; /* 可选:透明背景 */
  1243. }
  1244. /* 节点垂直间距 */
  1245. :deep(.el-tree-node) {
  1246. margin-bottom:5px !important; /* 增大节点间距 */
  1247. }
  1248. .el-popover.custom-popover {
  1249. min-width: 50px;
  1250. padding: 8px; /* 可选:调整内边距 */
  1251. }
  1252. </style>
  1253. <style>
  1254. .dot {
  1255. width: 20px; /* 控制圆点直径 */
  1256. height: 20px;
  1257. background-color: #333; /* 实心颜色 */
  1258. border-radius: 50%; /* 关键属性 */
  1259. display: inline-block; /* 确保与其他元素并排 */
  1260. }
  1261. /* 全局透明样式(不使用 scoped) */
  1262. .transparent-select .el-select__wrapper {
  1263. background-color: transparent !important;
  1264. border-color: transparent !important;
  1265. box-shadow: none !important;
  1266. }
  1267. .transparent-select .el-select__selection {
  1268. background-color: transparent;
  1269. }
  1270. /* 处理悬停和聚焦状态 */
  1271. .transparent-select .el-select__wrapper:hover,
  1272. .transparent-select .el-select__wrapper.is-focused {
  1273. border-color: transparent !important;
  1274. box-shadow: none !important;
  1275. }
  1276. /* 下拉箭头图标 */
  1277. .transparent-select .el-select__caret {
  1278. color: rgba(0, 0, 0, 0.5); /* 半透明图标 */
  1279. }
  1280. </style>
  1281. <style scoped>
  1282. :deep(.treeLeft) .el-tree-node__content {
  1283. display: flex !important;
  1284. height: 28px; /* 按设计稿调整高度 */
  1285. align-items: center;
  1286. padding-top: 0 !important;
  1287. }
  1288. :deep(.treeLeft) .el-tree-node__content:hover {
  1289. background-color: #e9e9eb;
  1290. }
  1291. :deep(.treeLeft) .el-tree-node__content:active {
  1292. background-color: rgka(69,157,255,0.1) !important;
  1293. }
  1294. /* 选中态(Active) */
  1295. :deep(.treeLeft) .el-tree-node.is-current > .el-tree-node__content {
  1296. background-color: #c6e2ff !important;
  1297. }
  1298. .tab-container {
  1299. height: 100vh; /* 关键:父容器明确高度 */
  1300. display: flex;
  1301. flex-direction: column;
  1302. }
  1303. .drag-handle {
  1304. cursor: move;
  1305. }
  1306. .ghost {
  1307. opacity: 0.5;
  1308. background: #c8ebfb;
  1309. }
  1310. /* 防止文字选中 */
  1311. :deep(.el-table__row) {
  1312. user-select: none;
  1313. -webkit-user-select: none;
  1314. }
  1315. </style>
  1316. <style scoped lang="scss">
  1317. .custom-tree-node {
  1318. display: flex; /* 启用 Flex 布局 */
  1319. align-items: center; /* 垂直居中 */
  1320. gap: 8px; /* 图标与文字间距 */
  1321. justify-content: space-between;
  1322. }
  1323. .el-table .el-table__row td {
  1324. height: 60px !important; /* 行高 */
  1325. }
  1326. .custom-tree-node {
  1327. display: flex; /* 启用 Flex 布局 */
  1328. align-items: center; /* 垂直居中 */
  1329. gap: 8px; /* 图标与文字间距 */
  1330. }
  1331. </style>