editModel.vue 60 KB

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