nanjingliujinyu 7 月之前
父節點
當前提交
553caf4a19

+ 1 - 0
ruoyi-ui/src/assets/icons/svg/分类.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1753923997559" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9073" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M136 232v560h752V360H525.255a104 104 0 0 1-73.54-30.46L354.178 232H136z m-40-72h274.745a32 32 0 0 1 22.628 9.373l109.254 109.254A32 32 0 0 0 525.255 288H928c17.673 0 32 14.327 32 32v512c0 17.673-14.327 32-32 32H96c-17.673 0-32-14.327-32-32V192c0-17.673 14.327-32 32-32z m296 464h240a8 8 0 0 1 8 8v48a8 8 0 0 1-8 8H392a8 8 0 0 1-8-8v-48a8 8 0 0 1 8-8z" fill="#5090F1" p-id="9074"></path></svg>

+ 1 - 0
ruoyi-ui/src/assets/icons/svg/模型2.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1753924356433" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="25310" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M511.9 325.12v248.55L727.15 449.4l-0.01-248.55z" fill="#83c5fd" p-id="25311"></path><path d="M296.65 200.85L511.9 325.12v248.56L296.65 449.4z" fill="#1892ff" p-id="25312"></path><path d="M511.9 325.12l215.25-124.27L511.9 76.57 296.65 200.85z" fill="#52adff" p-id="25313"></path><path d="M296.62 698.02v248.55L511.87 822.3l-0.01-248.56z" fill="#83c5fd" p-id="25314"></path><path d="M81.37 573.74l215.25 124.28v248.55L81.37 822.3z" fill="#1892ff" p-id="25315"></path><path d="M296.62 698.02l215.25-124.28-215.25-124.27L81.37 573.74z" fill="#52adff" p-id="25316"></path><path d="M727.03 698.02v248.55L942.28 822.3l-0.01-248.56z" fill="#83c5fd" p-id="25317"></path><path d="M511.78 573.74l215.25 124.28v248.55L511.78 822.3z" fill="#1892ff" p-id="25318"></path><path d="M727.03 698.02l215.25-124.28-215.25-124.27-215.25 124.27z" fill="#52adff" p-id="25319"></path></svg>

+ 1 - 0
ruoyi-ui/src/assets/icons/svg/模型管理.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1753924128626" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="19959" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M508.3136 165.376a33.4336 33.4336 0 0 0-33.792 0L193.024 330.24a34.3552 34.3552 0 0 0-16.9472 29.696v349.952c0 12.3904 6.656 23.808 17.2544 29.8496l281.6 160.1024c10.24 5.8368 22.784 5.8368 33.024 0l281.6-160.0512a34.3552 34.3552 0 0 0 17.3056-29.8496V359.7824a34.3552 34.3552 0 0 0-16.896-29.5936L508.2624 165.376z m310.1696 116.224c27.7504 16.384 44.8 46.1824 44.7488 78.336v349.9008c0 32.6656-17.4592 62.6688-45.7728 78.848l-281.6 160.0512a89.6512 89.6512 0 0 1-88.7296 0l-281.6-160.0512a90.6752 90.6752 0 0 1-45.7216-78.848V359.936c0-32.1536 16.9984-61.952 44.6976-78.336l281.4976-164.7616a89.7536 89.7536 0 0 1 90.7776 0l281.7024 164.864V281.6z" fill="#82A6FF" p-id="19960"></path><path d="M491.52 397.312a135.168 135.168 0 0 0 0 270.336 135.168 135.168 0 0 0 0-270.336z m0-56.32a191.488 191.488 0 0 1 0 382.976 191.488 191.488 0 0 1 0-382.976z" fill="#82A6FF" p-id="19961"></path></svg>

File diff suppressed because it is too large
+ 0 - 0
ruoyi-ui/src/assets/icons/svg/模型管理1.svg


+ 1 - 0
ruoyi-ui/src/components/TopNav/index.vue

@@ -4,6 +4,7 @@
     mode="horizontal"
     @select="handleSelect"
     :ellipsis="false"
+    
   >
     <template v-for="(item, index) in topMenus">
       <el-menu-item :style="{'--theme': theme}" :index="item.path" :key="index" v-if="index < visibleNumber">

+ 24 - 3
ruoyi-ui/src/layout/components/Sidebar/SidebarItem.vue

@@ -6,16 +6,16 @@
         <el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{ 'submenu-title-noDropdown': !isNest }">
           <svg-icon :icon-class="onlyOneChild.meta.icon || (item.meta && item.meta.icon)"/>
           <template #title><span class="menu-title"
-                                 :title="hasTitle(onlyOneChild.meta.title)">{{ onlyOneChild.meta.title }}</span>
+                                 :title="hasTitle(onlyOneChild.meta.title)"> &nbsp;{{ onlyOneChild.meta.title }}</span>
           </template>
         </el-menu-item>
       </app-link>
     </template>
 
-    <el-sub-menu v-else ref="subMenu" :index="resolvePath(item.path)" teleported>
+    <el-sub-menu v-else ref="subMenu" :index="resolvePath(item.path)" teleported class="subMenu">
       <template v-if="item.meta" #title>
         <svg-icon :icon-class="item.meta && item.meta.icon"/>
-        <span class="menu-title" :title="hasTitle(item.meta.title)">{{ item.meta.title }}</span>
+        <span class="menu-title" :title="hasTitle(item.meta.title)"> &nbsp;{{ item.meta.title }}</span>
       </template>
 
       <sidebar-item
@@ -107,4 +107,25 @@ function hasTitle(title) {
 // .menu{
 //   display: flex;
 // }
+.nest-menu{
+  font-size: 16px !important;
+}
+
 </style>
+<style scoped>
+/* 修改子菜单标题文字 */
+.subMenu :deep(.el-sub-menu__title) {
+  font-size: 16px !important;
+}
+
+/* 修改菜单项文字(含嵌套子菜单) */
+.subMenu :deep(.el-menu-item),
+.subMenu :deep(.el-sub-menu__title) {
+  font-size: 16px !important;
+}
+
+/* 修改标题文本(针对用户代码中的 .menu-title) */
+.subMenu :deep(.menu-title) {
+  font-size: 16px !important;
+}
+</style>

+ 9 - 1
ruoyi-ui/src/layout/components/Sidebar/index.vue

@@ -15,6 +15,7 @@
         <el-scrollbar :class="sideTheme" wrap-class="scrollbar-wrapper" style="margin-left: 6%;">
           <el-menu
               :default-active="activeMenu"
+              class="custom-menu"
               style="margin-top: 1%;"
               :collapse="isCollapse"
               :background-color="sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground"
@@ -25,7 +26,7 @@
               mode="horizontal"
           >
             <sidebar-item
-                style="margin-top: -0.5%;"
+                style="margin-top: -0.7%;"
                 v-for="(route, index) in sidebarRouters"
                 :key="route.path + index"
                 :item="route"
@@ -169,4 +170,11 @@ function handleCommand(command) {
   }
 }
 </style>
+<style scoped>
+/* 深度穿透修改 */
+:deep(.custom-menu .el-menu-item),
+:deep(.custom-menu .el-submenu__title) {
+  font-size: 16px !important;
+}
+</style>
 

+ 1372 - 0
ruoyi-ui/src/layout/components/editModel.vue

@@ -0,0 +1,1372 @@
+<template>
+  <div style="width: 100%;;display: flex;">
+    <div style="width: 15%;;background-color: #F2F6FC;max-height: 85vh;overflow: auto;">
+      <div style="display: flex;padding-top: 1%;padding-top: 5%;">
+        <el-input
+          v-model="inputNode"
+          style="width:75%;margin-left: 5%;background-color: #ebeef5;"
+          class="w-50 m-2"
+          :prefix-icon="Search" 
+        />
+        <!-- <el-button style="margin-left: 2%;width: 10%;background-color: #F7F7F7" :icon="Filter"/> -->
+        <el-button type="primary" @click="showAdd" style="margin-left: 5%;width: 10%;" :icon="Plus"/>
+      </div>
+      <!-- <Plus style="width: 1em; height: 1em; margin-left:90%;cursor: pointer;color: #337ecc;" @click="showAddTree"/> -->
+      <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">
+          <template #default="{ node, data }">
+            <span  style="justify-content: space-between;display: flex;width: 100%;align-items: center;">
+              <div class="custom-tree-node">
+                  <!-- <el-tag v-if="data.nodeType=='MODEL'" class="ml-2" type="warning">模型</el-tag> -->
+                   <svg-icon icon-class="模型2" style="color: #eebe77;" v-if="data.nodeType=='MODEL'"/>
+                  <!-- <el-tag  class="ml-2">
+                    服务
+                  </el-tag> -->
+                  <svg-icon icon-class="模型" dstyle="color: #13E03B;" v-if="data.nodeType=='SERVICE'"/>
+                  <svg-icon icon-class="分类" style="color: red;" v-if="data.nodeType=='TREE'"/>
+                <span>{{ node.label }}</span>
+              </div>
+              <div style="margin-right: 1%;position: absolute;margin-left: 75%;">
+                <el-dropdown trigger="hover" @click.stop v-if="currentNodeKey === data.id&&data.nodeType!=='SERVICE'">
+                    <el-icon class="el-icon--right" style="color: black;">
+                      <plus />
+                    </el-icon>
+                  <template #dropdown>
+                    <el-dropdown-menu>
+                      <el-dropdown-item style="display: flex;" @click="add1Level">
+                        <el-icon class="el-icon--right" style="color: black;">
+                          <CirclePlus />
+                        </el-icon>
+                        <div>
+                          添加同级
+                        </div>
+                      </el-dropdown-item>
+                      <el-dropdown-item style="display: flex;"  @click="addNextLevel">
+                        <el-icon class="el-icon--right" style="color: black;">
+                          <Connection />
+                        </el-icon>
+                        <div>
+                          新建下级
+                        </div>
+                      </el-dropdown-item>
+                      <divider/>
+                      <el-dropdown-item style="display: flex;"  @click="delAll" divided>
+                        <el-icon class="el-icon--right" style="color: black;">
+                          <CircleClose />
+                        </el-icon>
+                        <div>
+                          删除节点
+                        </div>
+                      </el-dropdown-item>
+                    </el-dropdown-menu>
+                  </template>
+                </el-dropdown>
+              </div>
+            </span>
+          </template>
+        </el-tree>
+    </div>
+    <div style="width: 84%;margin-left: 1%;" class="tab-container">
+        <el-tabs style="" v-model="activeName" class="demo-tabs" @tab-click="handleClick" >
+            <el-tab-pane label="查看" name="first" style="">
+              <div style="height: 80vh;overflow: auto;">
+                <div style="display: flex;align-items: center;justify-content: space-between;">
+                    <div style="margin-left:1%;">{{detail.name}}</div>
+                    <div style="display: flex;">
+                        <!-- <el-button type="primary" size="mini" :icon="Promotion" @click="fetchData">运行</el-button>
+                        <el-button type="" size="mini">删除</el-button> -->
+                    </div>
+                </div>
+                <div style="display: flex;align-items: center;margin-left:1%;margin-top: 1%;">
+                    <el-tag v-if="formJi.type" class="ml-2">
+                      {{formJi.type}}
+                    </el-tag>
+                    <el-tag v-if="formJi.rqtype=='POST'||formJi.rqtype=='post'" style="margin-left:0.5%;" class="ml-2" type="warning">
+                      {{formJi.rqtype}}
+                    </el-tag>
+                    <el-tag v-if="formJi.rqtype=='GET'||formJi.rqtype=='get'" type="success" style="margin-left: 0.5%;" class="ml-2">
+                      {{formJi.rqtype}}
+                    </el-tag>
+                    <div style="margin-left: 1%;">
+                        {{detail.url}}
+                    </div>
+                    <el-icon style="margin-left: 1%;cursor: pointer;color:#909399" @click="copyUrl"><CopyDocument /></el-icon>
+                    <div style="margin-left: 0.5%;">
+                        <!-- <el-select class="transparent-select" v-model="valueSta" style="border-color: transparent;width: 100px;">
+                            <el-option
+                            v-for="item in options"
+                            :key="item.value"
+                            :label="item.label"
+                            :value="item.value"
+                            >
+                            <div class="flex items-center" style="display: flex;align-items: center;">
+                                <div v-if="item.label=='开发中'" style="width: 5px; height: 5px; background-color: #409EFF; border-radius: 50%;"></div>
+                                <div v-if="item.label=='运行中'" style="width: 5px; height: 5px; background-color: #67C23A; border-radius: 50%;"></div>
+                                <span style="margin-left:1%;">{{ item.label }}</span>
+                            </div>
+                            </el-option>
+                            <template #prefix>
+                                <div class="flex items-center" style="display: flex; align-items: center;">
+                                    <div v-if="valueSta && options.find(opt => opt.value === valueSta)?.label === '开发中'" 
+                                        style="width: 5px; height: 5px; background-color: #409EFF; border-radius: 50%; margin-right: 4px;"></div>
+                                    <div v-if="valueSta && options.find(opt => opt.value === valueSta)?.label === '运行中'" 
+                                        style="width: 5px; height: 5px; background-color: #67C23A; border-radius: 50%; margin-right: 4px;"></div>
+                                    <span>{{ valueSta ? options.find(opt => opt.value === valueSta)?.label : '请选择' }}</span>
+                                </div>
+                            </template>
+                        </el-select> -->
+                    </div>
+                </div>
+                <div style="display: flex;width: 100%;">
+                    <div style="display: flex;margin-left: 1%;font-size: 15px;color:#909399;width:100%;margin-top: 1%;">
+                        
+                    </div>
+                </div>
+                <div style="margin-left: 1%;font-size: 15px;color:#909399;width:100%;display: flex;margin-top: 0.5%;">
+                    <div style="margin-left: 0%;">
+                        服务说明:
+                    </div>
+                    <div style="margin-left: 0.5%;">
+                        {{detail.name}}
+                    </div>
+                </div>
+                <div style="margin-left: 1%;font-size: 15px;color:#909399;width:100%;display: flex;margin-top: 0.5%;">
+                    <!-- <div style="margin-left: 0%;">
+                        返回说明:
+                    </div>
+                    <div style="margin-left: 0.5%;">
+                        {{detail.name}}
+                    </div> -->
+                </div>
+                <div style="margin-top: 2.5%;margin-left: 1%;">
+                  <el-tabs type="card" style="margin-top: 1%;width: 90%;">
+                    <el-tab-pane label="请求参数">
+
+                    </el-tab-pane>
+                  </el-tabs>
+                    <el-table 
+                      style="margin-top: -1%;width: 90%;"
+                      :data="tableDataCan" 
+                      :cell-style="{ textAlign: 'center', }"
+                      :header-cell-style="{ textAlign: 'center'}"
+                      :row-style="{ height: heightAll*0.01+'px',fontSize: '16px',textAlign:'center'  }"
+                      border >
+                          <el-table-column prop="paramCode" label="参数字段">
+                          </el-table-column>
+                          <el-table-column prop="paramName" label="参数名称">
+                          </el-table-column>
+                          <el-table-column prop="paramType" label="参数类型" width="140">
+                          </el-table-column>
+                          <el-table-column prop="paramNote" label="参数说明">
+                          </el-table-column>
+                      </el-table>
+                </div>
+                <div style="margin-top: 2.5%;margin-left: 1%;">
+                    <el-tabs type="card" style="margin-top: 1%;width: 90%;">
+                        <el-tab-pane label="成功(200)">
+                            <div style="display: flex;align-items: center;line-height: 1.5;font-size: 14px;margin-left: 1%;color: #606266;">
+                                <!-- <div>HTTP状态码:</div>
+                                <div>200</div>
+                                <div style="margin-left: 5%;">内容格式:</div>
+                                <div>JSON</div> -->
+                            </div>
+                            <!-- <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>
+                                <template #default="{ node, data }">
+                                    <span style="display: flex;justify-content: space-between;width: 100%;align-items: center;">
+                                        <span>{{ node.label }}</span>
+                                        <span style="display: flex;align-items: center;">
+                                            <div style="color:#67C23A;">string</div>
+                                            <el-tooltip
+                                                class="box-item"
+                                                effect="light"
+                                                content="必填"
+                                                placement="top-start"
+                                            >
+                                                <el-button style="transform: scale(0.5);transform-origin: center;margin-left: 5%; " type="success" :icon="Check" circle size="mini" plain/>
+                                            </el-tooltip>
+                                        </span>
+                                    </span>
+                                </template>
+                            </el-tree> -->
+                            
+                        </el-tab-pane>
+                    </el-tabs>
+                    <div style="margin-top: -1%;width: 90%;">
+                      <json-viewer 
+                          :value="dataReturn" 
+                          :expand-depth="5" 
+                          copyable 
+                          theme="my-theme"
+                      />
+                      <!-- <JsonEditorVue
+                          v-model="dataReturn"
+                          style="height:98%;width: 100%;"
+                          :mode="'code'"
+                          :showBtns="false"
+                          :options="{
+                            navigationBar: false, // 隐藏顶部导航栏
+                            statusBar: false,     // 隐藏底部状态栏
+                            mode: 'code',          // 仅保留代码编辑模式
+                            mainMenuBar: false     // 隐藏主菜单栏
+                          }"
+                          lang="zh"
+                        /> -->
+                    </div>
+                </div>
+                <div style="margin-top: 2.5%;margin-left: 1%;padding-bottom: 1%;width: 90%;">
+                    <div>响应示例</div><el-tabs type="card" style="margin-top: 1%;">
+                        <el-tab-pane label="成功示例">
+                             <div style="overflow: auto;height: 30vh">
+                                <json-viewer 
+                                    :value="dataJsonXiang" 
+                                    :expand-depth="5" 
+                                    copyable 
+                                    theme="my-theme"
+                                />
+                             </div>
+                        </el-tab-pane>
+                    </el-tabs>
+                </div>
+            
+              </div>
+            </el-tab-pane>
+            <el-tab-pane label="修改" name="second" style="" :disabled="isEdit">
+                <div style="overflow: auto;height: 80vh;">
+                  <div style="display: flex;margin-top: 1%;">
+                    <el-button type="primary" @click="saveEditService" style="margin-left: 80%;z-index: 1000;" :disabled="isEdit">提交</el-button>
+                    <el-button type="danger" @click="delSer" style="margin-left: 1%;z-index: 1000;" :disabled="isEdit">删除</el-button>
+                  </div>
+                    <el-form size="mini" :key="tableKey" style="margin-top: -2%;width: 98%;"  :model="formJi" label-position="right" ref="formRefJi" label-width="120px" :rules="rulesJi">
+                      <el-row :gutter="48">
+                            <el-col :span="10">
+                              <el-form-item label="服务名称:" prop="name" style="">
+                                  <div style="display: flex;width: 100%;justify-content: space-between;">
+                                    <el-input :disabled="isEdit" v-model="formJi.name" style="width: 100%;"/>
+                                  </div>
+                              </el-form-item>
+                            </el-col>
+                            <el-col :span="6">
+                              <el-form-item label="接口类型:" prop="" style="">
+                                <div style="display: flex;width: 100%;justify-content: space-between;">
+                                  <el-select
+                                    v-model="formJi.type"
+                                    :disabled="isEdit"
+                                        style="width: 100%;margin-left: 0%;"
+                                    >
+                                        <el-option
+                                        v-for="item in optionsType"
+                                        :key="item.value"
+                                        :label="item.label"
+                                        :value="item.value"
+                                        />
+                                    </el-select>
+                                  <div style="display: flex;">
+                                    
+                                  </div>
+                                </div>
+                                    
+                                </el-form-item>
+                            </el-col>
+                      </el-row>
+                      <el-row :gutter="48">
+                            <el-col :span="10">
+                              <el-form-item label="接口地址:" prop="url" style=""> 
+                                  <el-input
+                                  v-model="formJi.url"
+                                  :disabled="isEdit"
+                                  style="width: 100%;"
+                                  placeholder=""
+                                  class="input-with-select"
+                                  >
+                                </el-input>
+                              </el-form-item>
+                            </el-col>
+                            <el-col :span="6">
+                                <el-form-item label="请求方式:" prop="" style="">
+                                    <el-select
+                                    v-model="formJi.rqtype"
+                                    :disabled="isEdit"
+                                        style="width: 100%;margin-left: 0%;"
+                                    >
+                                        <el-option
+                                        v-for="item in optionsRqtype"
+                                        :key="item.value"
+                                        :label="item.label"
+                                        :value="item.value"
+                                        />
+                                    </el-select>
+                                </el-form-item>
+                            </el-col>
+                      </el-row>
+                      <el-row :gutter="48">
+                            <el-col :span="10">
+                              <el-form-item label="响应类型:" prop="" style="display: flex; align-items: center;">
+                                <el-radio-group :disabled="isEdit" v-model="formJi.rptype" class="ml-4" style="display: inline-flex; align-items: center;">
+                                  <el-radio label="1" size="large" style="display: inline-flex; align-items: center;">
+                                    <span style="position: relative; top: -1px">JSON</span> <!-- 微调文字位置 -->
+                                  </el-radio>
+                                  <el-radio label="2" size="large" style="display: inline-flex; align-items: center;">
+                                    <span style="position: relative; top: -1px">XML</span>
+                                  </el-radio>
+                                  <el-radio label="3" size="large" style="display: inline-flex; align-items: center;">
+                                    <span style="position: relative; top: -1px">HTML</span>
+                                  </el-radio>
+                                </el-radio-group>
+                              </el-form-item>
+                            </el-col>
+                            <el-col :span="6">
+                                <el-form-item label="服务分类:" prop="cateCode" style="">
+                                    <el-cascader :disabled="isEdit" v-model="formJi.cateCode" :options="cascaderOptions" :props="props1" clearable style="width: 100%;"></el-cascader>
+                                </el-form-item>
+                            </el-col>
+                            <!-- <el-col :span="8">
+                                <el-form-item label="请求方式:" prop="name" style="">
+                                    <el-select
+                                    v-model="formJi.type"
+                                    :disabled="isEdit"
+                                        style="width: 100%;margin-left: 0%;"
+                                    >
+                                        <el-option
+                                        v-for="item in optionsType"
+                                        :key="item.value"
+                                        :label="item.label"
+                                        :value="item.value"
+                                        />
+                                    </el-select>
+                                </el-form-item>
+                            </el-col> -->
+                      </el-row>
+                      <el-row :gutter="48">
+                            <el-col :span="13">
+                              <el-form-item label="服务说明:">
+                                  <el-input :disabled="isEdit" v-model="formJi.intro" style="width: 100%;" :rows="3" resize="none" type="textarea"/>
+                              </el-form-item>
+                            </el-col>
+                      </el-row>
+                        
+                    </el-form>
+                    <div style="margin-top: 2%;">
+                        <div style="display: flex;justify-content: space-between;align-items: center;">
+                          <div>
+                            请求参数
+                          </div>
+                          <div style="display: flex;justify-content: flex-end;margin-right: 2%;">
+                            <el-button  @click="addPa" style="margin-top: 1%;" type="success" size="mini" plain>新增参数</el-button>
+                          </div>
+                        </div>
+                        <div>
+                            <el-table 
+                            style="margin-top: 1%;width: 98%;"
+                            :data="tableDataCan" 
+                            :cell-style="{ textAlign: 'center',padding:'2px 0' }"
+                            :header-cell-style="{ textAlign: 'center'}"
+                            :row-style="{ height: heightAll*0.01+'px',fontSize: '16px',textAlign:'center'  }"
+                            border >
+                                <el-table-column prop="itemName" label="参数字段">
+                                    <template #default="scope">
+                                        <div style="width: 100%;">
+                                            <el-input  placeholder="请填写参数编码" type="primary" class="noBor" v-model="scope.row.paramCode" size="mini" text style="margin-left: 0%;border: transparent;"></el-input>
+                                        </div>
+                                    </template>
+                                </el-table-column>
+                                <el-table-column prop="itemName" label="参数名称">
+                                    <template #default="scope">
+                                        <div style="width: 100%;">
+                                            <el-input placeholder="请填写参数名称" type="primary" class="noBor" v-model="scope.row.itemName" size="mini" text style="margin-left: 0%;"></el-input>
+                                        </div>
+                                    </template>
+                                </el-table-column>
+                                <el-table-column prop="itemName" label="参数类型" width="200">
+                                    <template #default="scope">
+                                        <div style="width: 100%;">
+                                            <el-select
+                                            v-model="scope.row.paramType"
+                                            class="noBorSel"
+                                            placeholder=""
+                                            style="width: 100%;margin-left: 0%;"
+                                            >
+                                                <el-option
+                                                v-for="item in optionsCan"
+                                                :key="item.value"
+                                                :label="item.label"
+                                                :value="item.value"
+                                                />
+                                    </el-select>
+                                        </div>
+                                    </template>
+                                </el-table-column>
+                                <el-table-column prop="itemName" label="参数说明" >
+                                    <template #default="scope">
+                                        <div style="width: 100%;">
+                                            <el-input type="primary" class="noBor" v-model="scope.row.paramNote" size="mini" text style="margin-left: 0%;"></el-input>
+                                        </div>
+                                    </template>
+                                </el-table-column>
+                                <el-table-column prop="address" label="操作" width="100">
+                                    <template #default="scope">
+                                        <div style="width: 100%;">
+                                            <el-button type="danger" @click="delCan(scope.$index)" size="mini" text style="margin-left: 0%;">删除</el-button>
+                                        </div>
+                                    </template>
+                                </el-table-column>
+                            </el-table>
+                            
+                        </div>
+                    </div>
+                    <div style="margin-top: 2%;">
+                        <!-- <div>返回响应</div> -->
+                        <div style="color: #909399;margin-left: 7%;margin-top:1%;">此处填写本服务接口响应信息描述</div>
+                        <el-tabs type="card" style="margin-top: -1.5%;width: 98%;">
+                            <el-tab-pane label="响应内容">
+                                <div style="display: flex; flex-direction: column;">
+                                    <!-- <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>
+                                        <template #default="{ node, data }">
+                                            <span style="display: flex;justify-content: space-between;width: 100%;align-items: center;">
+                                                <span><el-input v-model="node.label" size="mini"/></span>
+                                                <span style="display: flex;align-items: center;">
+                                                    <el-tooltip
+                                                        class="box-item"
+                                                        effect="light"
+                                                        content="是否必填"
+                                                        placement="top-start"
+                                                    >
+                                                    <el-checkbox v-model="checked1" label="" size="large" />
+                                                    </el-tooltip>
+                                                    <el-select
+                                                        v-model="formJi.type"
+                                                        :disabled="isEdit"
+                                                        style="width: 100%;margin-left: -1%;"
+                                                    >
+                                                        <el-option
+                                                        v-for="item in optionsType"
+                                                        :key="item.value"
+                                                        :label="item.label"
+                                                        :value="item.value"
+                                                        />
+                                                    </el-select>
+                                                    <el-tooltip
+                                                        class="box-item"
+                                                        effect="light"
+                                                        content="是否允许null"
+                                                        placement="top-start"
+                                                    >
+                                                    <el-checkbox v-model="checked1" label="" size="large" />
+                                                    </el-tooltip>
+                                                </span>
+                                            </span>
+                                        </template>
+                                    </el-tree> -->
+                                   </div>
+                            </el-tab-pane>
+                        </el-tabs>
+                        <div style="overflow: auto;height: 20vh;margin-top: -1%;">
+                          <!-- <JsonEditorVue
+                            v-model="dataJsonXiang"
+                            style="height:98%;width: 98%;"
+                            :mode="'code'"
+                            :showBtns="false"
+                            :options="{
+                              navigationBar: false, // 隐藏顶部导航栏
+                              statusBar: false,     // 隐藏底部状态栏
+                              mode: 'code',          // 仅保留代码编辑模式
+                              mainMenuBar: false     // 隐藏主菜单栏
+                            }"
+                            lang="zh"
+                          /> -->
+                          <el-input placeholder="请输入示例" :rows="8" type="textarea" v-model="dataJsonXiang" size="mini" text style="margin-top: 0%;width: 98%;" ></el-input>
+                        </div>
+                    </div>
+                    <div style="margin-top: 2.5%;margin-left: 0%;padding-bottom: 1%;">
+                    
+                    <el-tabs type="card" style="margin-top: -1.5%;width: 98%;">
+                        <el-tab-pane label="使用说明">
+                             
+                        </el-tab-pane>
+                    </el-tabs>
+                    <el-input placeholder="请输入示例" :rows="8" type="textarea" v-model="example" size="mini" text style="margin-top: -1%;width: 98%;" ></el-input>
+                </div>
+                </div>
+            </el-tab-pane>
+        </el-tabs>
+        <el-dialog @close="clearAdd" v-model="dialogVisible" title="新增节点" width="70%" destroy-on-close :key="tableKey">
+          <div style="overflow: auto;height: 80vh;">
+                    <el-form size="mini" :key="tableKey" style="margin-top: 1%;width: 98%;"  :model="formAdd" label-position="right" ref="formRefAdd" label-width="120px" :rules="rulesAdd">
+                      <el-row :gutter="48">
+                            <el-col :span="10">
+                              <el-form-item label="服务名称:" prop="name" style="">
+                                  <div style="display: flex;width: 100%;justify-content: space-between;">
+                                    <el-input v-model="formAdd.name" style="width: 100%;"/>
+                                  </div>
+                              </el-form-item>
+                            </el-col>
+                            <el-col :span="6">
+                              <el-form-item label="接口类型:" prop="" style="">
+                                <div style="display: flex;width: 100%;justify-content: space-between;">
+                                  <el-select
+                                    v-model="formAdd.type"
+                                    :disabled="isEdit"
+                                        style="width: 100%;margin-left: 0%;"
+                                    >
+                                        <el-option
+                                        v-for="item in optionsType"
+                                        :key="item.value"
+                                        :label="item.label"
+                                        :value="item.value"
+                                        />
+                                    </el-select>
+                                  <div style="display: flex;">
+                                    
+                                  </div>
+                                </div>
+                                    
+                                </el-form-item>
+                            </el-col>
+                      </el-row>
+                      <el-row :gutter="48">
+                            <el-col :span="10">
+                              <el-form-item label="接口地址:" prop="url" style=""> 
+                                  <el-input
+                                  v-model="formAdd.url"
+                                  style="width: 100%;"
+                                  placeholder=""
+                                  class="input-with-select"
+                                  >
+                                </el-input>
+                              </el-form-item>
+                            </el-col>
+                            <el-col :span="6">
+                                <el-form-item label="请求方式:" prop="" style="">
+                                    <el-select
+                                    v-model="formAdd.rqtype"
+                                    :disabled="isEdit"
+                                        style="width: 100%;margin-left: 0%;"
+                                    >
+                                        <el-option
+                                        v-for="item in optionsRqtype"
+                                        :key="item.value"
+                                        :label="item.label"
+                                        :value="item.value"
+                                        />
+                                    </el-select>
+                                </el-form-item>
+                            </el-col>
+                      </el-row>
+                      <el-row :gutter="48">
+                            <el-col :span="10">
+                              <el-form-item label="所属模型:" prop="mdid" style="">
+                                <el-tree-select
+                                  v-model="formAdd.mdid"
+                                  :data="optionsMdid"
+                                  check-strictly
+                                  :render-after-expand="false"
+                                  style="width: 100%"
+                                />
+                                <!-- <el-select
+                                v-model="formAdd.mdid"
+                                    style="width: 100%;margin-left: 0%;"
+                                >
+                                    <el-option
+                                    v-for="item in optionsMdid"
+                                    :key="item.value"
+                                    :label="item.label"
+                                    :value="item.id"
+                                    />
+                                </el-select> -->
+                      </el-form-item>
+                            </el-col>
+                      </el-row>
+                      <el-row :gutter="48">
+                            <el-col :span="10">
+                              <el-form-item label="响应类型:" prop="" style="display: flex; align-items: center;">
+                                <el-radio-group v-model="formAdd.rptype" class="ml-4" style="display: inline-flex; align-items: center;">
+                                  <el-radio label="1" size="large" style="display: inline-flex; align-items: center;">
+                                    <span style="position: relative; top: -1px">JSON</span> <!-- 微调文字位置 -->
+                                  </el-radio>
+                                  <el-radio label="2" size="large" style="display: inline-flex; align-items: center;">
+                                    <span style="position: relative; top: -1px">XML</span>
+                                  </el-radio>
+                                  <el-radio label="3" size="large" style="display: inline-flex; align-items: center;">
+                                    <span style="position: relative; top: -1px">HTML</span>
+                                  </el-radio>
+                                </el-radio-group>
+                              </el-form-item>
+                            </el-col>
+                            <el-col :span="6">
+                                <el-form-item label="服务分类:" prop="cateCode" style="">
+                                    <el-cascader v-model="formAdd.cateCode" :options="cascaderOptions" :props="props1" clearable style="width: 100%;"></el-cascader>
+                                </el-form-item>
+                            </el-col>
+                            <!-- <el-col :span="8">
+                                <el-form-item label="请求方式:" prop="name" style="">
+                                    <el-select
+                                    v-model="formJi.type"
+                                    :disabled="isEdit"
+                                        style="width: 100%;margin-left: 0%;"
+                                    >
+                                        <el-option
+                                        v-for="item in optionsType"
+                                        :key="item.value"
+                                        :label="item.label"
+                                        :value="item.value"
+                                        />
+                                    </el-select>
+                                </el-form-item>
+                            </el-col> -->
+                      </el-row>
+                      <el-row :gutter="48">
+                            <el-col :span="13">
+                              <el-form-item label="服务说明:">
+                                  <el-input v-model="formAdd.intro" style="width: 100%;" :rows="3" resize="none" type="textarea"/>
+                              </el-form-item>
+                            </el-col>
+                      </el-row>
+                        
+                    </el-form>
+                    <div style="margin-top: 2%;">
+                        <div style="display: flex;justify-content: space-between;align-items: center;">
+                          <div>
+                            请求参数
+                          </div>
+                          <div style="display: flex;justify-content: flex-end;margin-right: 2%;">
+                            <el-button  @click="addCanAdd" style="margin-top: 1%;" type="success" size="mini" plain>新增参数</el-button>
+                          </div>
+                        </div>
+                        <div>
+                            <el-table 
+                            style="margin-top: 1%;width: 98%;"
+                            :data="tableDataCanAdd" 
+                            :cell-style="{ textAlign: 'center',padding:'2px 0' }"
+                            :header-cell-style="{ textAlign: 'center'}"
+                            :row-style="{ height: heightAll*0.01+'px',fontSize: '16px',textAlign:'center'  }"
+                            border >
+                                <el-table-column prop="itemName" label="参数字段">
+                                    <template #default="scope">
+                                        <div style="width: 100%;">
+                                            <el-input placeholder="请填写参数编码" type="primary" class="noBor" v-model="scope.row.paramCode" size="mini" text style="margin-left: 0%;border: transparent;"></el-input>
+                                        </div>
+                                    </template>
+                                </el-table-column>
+                                <el-table-column prop="itemName" label="参数名称">
+                                    <template #default="scope">
+                                        <div style="width: 100%;">
+                                            <el-input placeholder="请填写参数名称" type="primary" class="noBor" v-model="scope.row.paramName" size="mini" text style="margin-left: 0%;"></el-input>
+                                        </div>
+                                    </template>
+                                </el-table-column>
+                                <el-table-column prop="itemName" label="参数类型" width="200">
+                                    <template #default="scope">
+                                        <div style="width: 100%;">
+                                            <el-select
+                                            v-model="scope.row.paramType"
+                                            class="noBorSel"
+                                            placeholder=""
+                                            style="width: 100%;margin-left: 0%;"
+                                            >
+                                                <el-option
+                                                v-for="item in optionsCan"
+                                                :key="item.value"
+                                                :label="item.label"
+                                                :value="item.value"
+                                                />
+                                    </el-select>
+                                        </div>
+                                    </template>
+                                </el-table-column>
+                                <el-table-column prop="itemName" label="参数说明" >
+                                    <template #default="scope">
+                                        <div style="width: 100%;">
+                                            <el-input type="primary" class="noBor" v-model="scope.row.paramNote" size="mini" text style="margin-left: 0%;"></el-input>
+                                        </div>
+                                    </template>
+                                </el-table-column>
+                                <el-table-column prop="address" label="操作" width="100">
+                                    <template #default="scope">
+                                        <div style="width: 100%;">
+                                            <el-button type="danger" @click="delCanAdd(scope.$index)" size="mini" text style="margin-left: 0%;">删除</el-button>
+                                        </div>
+                                    </template>
+                                </el-table-column>
+                            </el-table>
+                            
+                        </div>
+                    </div>
+                    <div style="margin-top: 2%;">
+                        <!-- <div>返回响应</div> -->
+                        <div style="color: #909399;margin-left: 8%;margin-top:1%;">此处填写本服务接口响应信息描述</div>
+                        <el-tabs type="card" style="margin-top: -2%;width: 98%;">
+                            <el-tab-pane label="响应内容">
+                                <div style="display: flex; flex-direction: column;">
+                                   </div>
+                            </el-tab-pane>
+                        </el-tabs>
+                        <div style="overflow: auto;height: 20vh;margin-top: -1%;">
+                          <el-input placeholder="请输入示例" :rows="8" type="textarea" v-model="JsonAdd" size="mini" text style="margin-top: 0%;width: 98%;" ></el-input>
+                        </div>
+                    </div>
+                    <div style="margin-top: 2.5%;margin-left: 0%;padding-bottom: 1%;">
+                    
+                    <el-tabs type="card" style="margin-top: -1.5%;width: 98%;">
+                        <el-tab-pane label="使用说明">
+                             
+                        </el-tab-pane>
+                    </el-tabs>
+                    <el-input placeholder="请输入示例" :rows="8" type="textarea" v-model="exampleAdd" size="mini" text style="margin-top: -1%;width: 98%;" ></el-input>
+                </div>
+                </div>
+                <template #footer>
+                  <span class="dialog-footer">
+                    <el-button size="mini" @click="dialogVisible = false">取消</el-button>
+                    <el-button type="primary" @click="addSer" size="mini">
+                      提交
+                    </el-button>
+                </span>
+              </template>
+        </el-dialog>
+        <el-dialog @close="clearFromLev" title="添加目录" v-model="dialogVisibleLevel" width="30%" destroy-on-close :key="tableKey">
+          <el-form size="mini" :key="tableKey" style="margin-top: 1%;width: 90%;"  :model="formLev" label-position="right" ref="formRefLev" label-width="120px" :rules="rulesLev">
+            <el-form-item label="名称:" prop="itemName" style="">
+              <el-input v-model="formLev.itemName" style="width: 100%;"/>
+            </el-form-item>
+            <el-form-item label="说明:" prop="itemNotes" style="">
+              <el-input v-model="formLev.itemNotes" style="width: 100%;"/>
+            </el-form-item>
+            <el-form-item label="排序:" prop="itemNo" style="">
+              <el-input-number v-model="formLev.itemNo" style="width: 100%;" :min="1" :max="10000" @change="handleChange" />
+            </el-form-item>
+          </el-form>
+          <template #footer>
+              <span class="dialog-footer">
+                <el-button size="mini" @click="dialogVisibleLevel = false">取消</el-button>
+                <el-button type="primary" @click="saveAdd1Level" size="mini" v-if="show1Lev">
+                  提交
+                </el-button>
+                <el-button type="primary" @click="saveAddNextLevel" size="mini" v-if="!show1Lev">
+                  提交
+                </el-button>
+            </span>
+          </template>
+        </el-dialog>
+    </div>
+  </div>
+</template>
+<script   setup>
+import {getCatalog} from "@/api/service/catalog";
+import { Plus,Search,Filter,Promotion,Check  } from '@element-plus/icons-vue'
+import { reactive } from 'vue'
+import { modelTreeSelect,getSerDe,addService,addParam,editService,editParam,addServiceParam,delService,getTreeDe,addTree,deTree } from "@/api/service/info";
+import { ref, onMounted, onUnmounted, nextTick,onBeforeMount } from 'vue';
+import JsonViewer from 'vue-json-viewer'
+import 'vue-json-viewer/style.css' 
+import  JsonEditorVue from 'json-editor-vue3'
+import { cloneDeep } from 'lodash'
+import { useClipboard } from "@vueuse/core";
+
+const { proxy } = getCurrentInstance();
+const JsonAdd= ref(JSON.stringify({ data: "初始值1" }))
+const exampleAdd = ref('')
+const dialogVisibleLevel = ref(false)
+const detail = ref({
+  name:'',
+  rqtype:'',
+  rptype:''
+})
+const show1Lev = ref(true)
+const inputNode =ref('')
+const isEdit = ref(true)
+const dataReturn = ref({})
+const optionsCan = ref([
+  {
+    label:"string",
+    value:'string'
+  },
+  {
+    label:"int",
+    value:'int'
+  },
+  {
+    label:"boolean",
+    value:'boolean'
+  },
+  {
+    label:"array",
+    value:'array'
+  },
+  {
+    label:"object",
+    value:'object'
+  },
+  {
+    label:"number",
+    value:'number'
+  },
+  {
+    label:"null",
+    value:'null'
+  },
+  {
+    label:"any",
+    value:'any'
+  },
+  
+])
+const currentNodeKey = ref('')
+const options =  ref([
+    {label:'开发中',
+    value:'1'
+    },
+    {label:'运行中',
+    value:'2'
+    },
+])
+const dataJsonXiang = ref([])
+const parTree = ref({})
+const valueKet = ref(0)
+const tableDataCan = ref([
+    {
+      itemName:'',
+      itemCode:'',
+      paramType:'',
+      paramNote:''
+    }
+])
+const optionsMdid = ref([])
+const optionsRqtype = ref([
+    {label:'GET',
+    value:'GET'
+    },
+    {label:'POST',
+    value:'POST'
+    },
+])
+const optionsType=  ref([
+    {label:'RESTful',
+    value:'RESTful'
+    },
+    {label:'WebService',
+    value:'WebService'
+    },
+    {label:'HTTP',
+    value:'HTTP'
+    },
+    {label:'WebSocket',
+    value:'WebSocket'
+    },
+])
+const data =  ref([])
+const select =  ref('1')
+const activeName =  ref('first')
+const title =  ref('')
+const titleTree =  ref('')
+const currentPage =  ref(1)
+const total =  ref(1)
+const tableData = ref([])
+const tableheight = window.innerHeight*0.7
+const heightAll = window.innerHeight
+const dialogVisible = ref(false)
+const dialogVisibleTree = ref(false)
+const isAdd = ref(false)
+const isAddTa = ref(false)
+const treeId = ref('');
+const valueSta = ref('1');
+const example = ref('');
+const tableDataCanAdd = ref([
+  {
+      itemName:'',
+      itemCode:'',
+      paramType:'',
+      paramNote:''
+    }
+])
+const formZu = ref({
+  itemName:'',
+  itemTp:'',
+  itemEn:'',
+  itemTp:'',
+  itemDataTp:'',
+  itemDefaultVal:'',
+  itemUnit:'',
+  itemNotes:'',
+});
+const parId= ref('')
+const formJi = ref({
+  name:'',
+  cateCode:'',
+  type:'',
+  url:'',
+  rqtype:'',
+  rptype:'',
+  intro:'',
+});
+const rulesJi = reactive({
+  name: [{ required: true, message: '必填', trigger: 'blur' }],
+  url: [{ required: true, message: '必填', trigger: 'blur' }],
+  cateCode: [{ required: true, message: '必填', trigger: 'blur' }],
+});
+const formRefJi = ref();
+const formAdd = ref({
+  name:'',
+  cateCode:'',
+  type:'',
+  url:'',
+  rqtype:'',
+  rptype:'',
+  intro:'',
+  mdid:''
+});
+const rulesAdd = reactive({
+  mdid: [{ required: true, message: '必填', trigger: 'blur' }],
+  name: [{ required: true, message: '必填', trigger: 'blur' }],
+  url: [{ required: true, message: '必填', trigger: 'blur' }],
+  cateCode: [{ required: true, message: '必填', trigger: 'blur' }],
+});
+const formRefAdd = ref();
+const treeRef = ref(null);
+const formTree = ref({
+  itemName:'',
+  catePid:'',
+  itemNo:'',
+  itemNotes:''
+});
+const rulesTree = reactive({
+  itemNo: [{ required: true, message: '必填', trigger: 'blur' }],
+  catePid: [{ required: true, message: '必填', trigger: 'blur' }],
+  itemName: [{ required: true, message: '必填', trigger: 'blur' }],
+});
+const formRefTree = ref();
+const formLev = ref({
+  itemName:'',
+  itemNo:'',
+  itemNotes:'',
+});
+const rulesLev = reactive({
+  itemNotes: [{ required: true, message: '必填', trigger: 'blur' }],
+  itemNo: [{ required: true, message: '必填', trigger: 'blur' }],
+  itemName: [{ required: true, message: '必填', trigger: 'blur' }],
+});
+const formRefLev = ref();
+const cascaderOptions = ref([])
+const props1 = ref({
+  checkStrictly: true,
+})
+const detailJson = ref([])
+
+watch(inputNode, (val) => {
+  treeRef.value?.filter(val); // 调用树的过滤方法
+});
+const filterNode = (value, data) => {
+  if (!value) return true; // 空搜索时显示所有节点
+  return data.label.includes(value); // 检查节点标签是否包含关键字
+};
+
+const copied = ref(false);
+
+async function copyUrl(){
+  try {
+    await navigator.clipboard.writeText(detail.value.url);
+    copied.value = true;
+    console.log(detail.url.value,copied.value)
+    setTimeout(() => (copied.value = false), 2000); // 2秒后提示消失
+  } catch (err) {
+    console.error("复制失败", err);
+  }
+};
+function filterModelNodes(nodes) {
+  if (!Array.isArray(nodes)) return [];
+  
+  const result = [];
+  for (const node of nodes) {
+    // 递归处理子节点(如果有)
+    const filteredChildren = node.children ? filterModelNodes(node.children) : [];
+    
+    if (node.nodeType === 'MODEL') {
+      // 保留当前节点,并更新其子节点
+      node.value = node.id
+      result.push({
+        ...node,
+        children: filteredChildren
+      });
+    } else {
+      // 删除当前节点,将其子节点提升到当前层级
+      result.push(...filteredChildren);
+    }
+  }
+  return result;
+}
+function clearAdd(){
+  formAdd.value = {
+    name:'',
+    cateCode:'',
+    type:'',
+    url:'',
+    rqtype:'',
+    rptype:'',
+    intro:'',
+    mdid:''
+  }
+  tableDataCanAdd.value = {
+    itemName:'',
+    itemCode:'',
+    paramType:'',
+    paramNote:''
+  }
+  JsonAdd.value = ''
+  exampleAdd.value = ''
+}
+function extractModelNodesDFSIterative(root) {
+  const result = [];
+  const stack = root;
+  
+  while (stack.length > 0) {
+    const node = stack.pop();
+    if (node.nodeType === 'MODEL') {
+      result.push(node);
+    }
+    
+    // 子节点逆序入栈(保证从左到右遍历)
+    if (node.children) {
+      for (let i = node.children.length - 1; i >= 0; i--) {
+        stack.push(node.children[i]);
+      }
+    }
+  }
+  return result;
+}
+function delAll(){
+  proxy.$modal.confirm('是否确认删除?').then(function () {
+    return deTree(parTree.value.id);
+  }).then(() => {
+    getTreeLeft();
+    proxy.$modal.msgSuccess("删除成功");
+    dialogVisibleLevel.value = false
+  }).catch(() => {});
+}
+function clearFromLev(){
+  formLev.value = {
+    itemName:'',
+    itemNo:'',
+    itemNotes:'',
+  }
+}
+function addNextLevel(){
+  dialogVisibleLevel.value = true
+  show1Lev.value = false
+}
+function saveAddNextLevel(){
+   formRefLev.value.validate((valid) => {
+    if(valid){
+      var par = formLev.value
+      par.treeType = parTree.value.nodeType
+      par.treePid = parTree.value.id
+      addTree(par).then(res=>{
+        if(res.code===200){
+          proxy.$modal.msgSuccess("新增成功");
+          getTreeLeft()
+          dialogVisibleLevel.value = false
+        }
+      })
+    }
+  });
+}
+function add1Level(){
+  dialogVisibleLevel.value = true
+  show1Lev.value = true
+}
+function saveAdd1Level(){
+  formRefLev.value.validate((valid) => {
+    if(valid){
+      var par = formLev.value
+      par.treeType = parTree.value.nodeType
+      par.treePid = parTree.value.pid
+      addTree(par).then(res=>{
+        if(res.code===200){
+          proxy.$modal.msgSuccess("新增成功");
+          getTreeLeft()
+          dialogVisibleLevel.value = false
+        }
+      })
+    }
+  });
+}
+async function delSer(){
+  proxy.$modal.confirm('是否确认删除?').then(function () {
+    return delService(parId.value.id);
+  }).then(() => {
+    getTreeLeft();
+    proxy.$modal.msgSuccess("删除成功");
+  }).catch(() => {});
+}
+async function saveEditService(){
+  console.log(JsonAdd.value)
+  var valid
+  await formRefJi.value.validate((valid1) => {
+    valid = valid1
+  });
+  console.log(valid)
+  if(valid){
+    var par = formJi.value
+    par.example = example.value
+    par.rpcontent = dataJsonXiang.value
+    par.cateCode = par.cateCode[0]
+    console.log(par)
+    await editService(par).then(res=>{
+      if(res.code===200){
+        var parCan = tableDataCan.value
+        // parCan.srvId = parId.value.srvId
+        addServiceParam(parCan).then(res1=>{
+          if(res1.code===200){
+            proxy.$modal.msgSuccess("修改成功");
+            getTreeLeft()
+          }
+        })
+      }
+    })
+  }
+}
+async function addSer(){
+  console.log(JsonAdd.value)
+  var valid
+  await formRefAdd.value.validate((valid1) => {
+    valid = valid1
+  });
+  console.log(valid) 
+  if(valid){
+    var par = formAdd.value
+    par.example = exampleAdd.value
+    par.rpcontent = JsonAdd.value
+    par.cateCode = par.cateCode[0]
+    console.log(par)
+
+    await addService(par).then(res=>{
+      if(res.code===200){
+        var parCan = tableDataCanAdd.value
+        parCan.srvId = res.data.srvId
+        addServiceParam(parCan).then(res1=>{
+          if(res1.code===200){
+            proxy.$modal.msgSuccess("新增成功");
+            getTreeLeft()
+          }
+        })
+      }
+    })
+    
+    
+  }
+
+}
+function showAdd(){
+  dialogVisible.value = true
+}
+async function handleNodeClick(node,data,event){
+  parTree.value = data.data
+  currentNodeKey.value = data.data.id
+  console.log(data.data.nodeType)
+  isEdit.value = false
+  parId.value = data.data
+  await getSerDe(data.data.id).then(res=>{
+    detail.value = res.data.ptService
+    tableDataCan.value = res.data.list
+    dataReturn.value = res.data.returnList
+    console.log(tableDataCan.value)
+    dataJsonXiang.value = res.data.ptService.rpcontent
+    formJi.value = res.data.ptService
+    example.value = res.data.ptService.example
+  })
+  detail.value.nodeType = data.data.nodeType
+  
+}
+async function getTreeLeft(){
+  var par
+  await modelTreeSelect().then(res=>{
+    par = res.data
+    data.value = res.data
+    
+  })
+  optionsMdid.value = filterModelNodes(par)
+  console.log(optionsMdid.value)
+}
+function renameTreeProperties(tree) {
+  // 深拷贝避免修改原始数据(可选,根据需求)
+  const newTree = cloneDeep(tree); // 使用 lodash
+  // 或:const newTree = JSON.parse(JSON.stringify(tree)); // 原生方法(不兼容函数等)
+
+  // 递归处理函数
+  const processNode = (node) => {
+    // 重命名属性
+    if ('cateName' in node) {
+      node.label = node.cateName;
+      delete node.cateName;
+    }
+    if ('cateCode' in node) {
+      node.value = node.cateCode;
+      delete node.cateCode;
+    }
+
+    // 递归处理子节点
+    if (node.children && node.children.length > 0) {
+      node.children.forEach(child => processNode(child));
+    }
+  };
+
+  // 遍历根节点
+  newTree.forEach(rootNode => processNode(rootNode));
+  return newTree;
+}
+function fetchData() {
+  getCatalog().then((r) => {
+    cascaderOptions.value = renameTreeProperties(buildTree(r.data))
+    console.log(cascaderOptions.value)
+  });
+}
+function buildTree(flatData, rootValue = '0') {
+      const nodeMap = new Map();
+      const tree = [];
+      flatData.forEach(item => {
+        nodeMap.set(item.cateCode, { ...item, children: [] });
+      });
+      for (const [code, node] of nodeMap) {
+        const parentCode = node.catePcode;
+        if (parentCode === rootValue || !parentCode) {
+          tree.push(node);
+          continue;
+        }
+        const parent = nodeMap.get(parentCode);
+        if (parent) {
+          parent.children.push(node);
+        } else {
+          console.warn(`Orphan node detected: ${code}. Parent ${parentCode} not found`);
+        }
+      }
+
+      return tree;
+    }
+function addPa(){
+    var par = {
+        itemName:''
+    }
+    tableDataCan.value.push(par)
+}
+function delCan(index){
+  tableDataCan.value.splice(index, 1)
+}
+function addCanAdd(){
+    var par = {
+        itemName:''
+    }
+    tableDataCanAdd.value.push(par)
+}
+function delCanAdd(index){
+  tableDataCanAdd.value.splice(index, 1)
+}
+onMounted(() => {
+  fetchData()
+  getTreeLeft()
+});
+
+</script>
+<style scoped>
+
+.noBorSel :deep(.el-select__wrapper){
+  box-shadow: none !important; /* 去除阴影边框 */
+  border: 1px solid transparent !important; /* 设置透明边框 */
+  background-color: transparent !important; /* 可选:透明背景 */
+}
+.noBor :deep(.el-input__wrapper) {
+  box-shadow: none !important; /* 去除阴影边框 */
+  border: 1px solid transparent !important; /* 设置透明边框 */
+  background-color: transparent !important; /* 可选:透明背景 */
+}
+/* 节点垂直间距 */
+:deep(.el-tree-node) {
+  margin-bottom:5px !important; /* 增大节点间距 */
+}
+.el-popover.custom-popover {
+  min-width: 50px;
+  padding: 8px; /* 可选:调整内边距 */
+}
+</style>
+<style>
+.dot {
+  width: 20px;          /* 控制圆点直径 */
+  height: 20px;
+  background-color: #333; /* 实心颜色 */
+  border-radius: 50%;    /* 关键属性 */
+  display: inline-block; /* 确保与其他元素并排 */
+}
+/* 全局透明样式(不使用 scoped) */
+.transparent-select .el-select__wrapper {
+  background-color: transparent !important;
+  border-color: transparent !important;
+  box-shadow: none !important;
+}
+
+.transparent-select .el-select__selection {
+  background-color: transparent;
+}
+
+/* 处理悬停和聚焦状态 */
+.transparent-select .el-select__wrapper:hover,
+.transparent-select .el-select__wrapper.is-focused {
+  border-color: transparent !important;
+  box-shadow: none !important;
+}
+
+/* 下拉箭头图标 */
+.transparent-select .el-select__caret {
+  color: rgba(0, 0, 0, 0.5); /* 半透明图标 */
+}
+</style>
+<style scoped>
+:deep(.treeLeft) .el-tree-node__content {
+  display: flex !important;
+  height: 28px;                  /* 按设计稿调整高度 */
+  align-items: center;
+  padding-top: 0 !important;
+}
+:deep(.treeLeft) .el-tree-node__content:hover {
+  background-color: #e9e9eb;
+}
+:deep(.treeLeft) .el-tree-node__content:active {
+    background-color: rgka(69,157,255,0.1) !important;
+  }
+
+  /* 选中态(Active) */
+:deep(.treeLeft) .el-tree-node.is-current > .el-tree-node__content {
+    background-color: #c6e2ff !important;
+  }
+
+.tab-container {
+  height: 100vh; /* 关键:父容器明确高度 */
+  display: flex;
+  flex-direction: column;
+}
+.drag-handle {
+  cursor: move;
+}
+
+.ghost {
+  opacity: 0.5;
+  background: #c8ebfb;
+}
+
+/* 防止文字选中 */
+:deep(.el-table__row) {
+  user-select: none;
+  -webkit-user-select: none;
+}
+</style>
+<style scoped lang="scss">
+
+.custom-tree-node {
+  display: flex;       /* 启用 Flex 布局 */
+  align-items: center; /* 垂直居中 */
+  gap: 8px;            /* 图标与文字间距 */
+  justify-content: space-between;
+}
+.el-table .el-table__row td {
+  height: 60px !important; /* 行高 */
+}
+.custom-tree-node {
+  display: flex;       /* 启用 Flex 布局 */
+  align-items: center; /* 垂直居中 */
+  gap: 8px;            /* 图标与文字间距 */
+}
+</style>

File diff suppressed because it is too large
+ 401 - 500
ruoyi-ui/src/views/register/componentReg/index.vue


+ 1206 - 0
ruoyi-ui/src/views/service/info/editModel.vue

@@ -0,0 +1,1206 @@
+<template>
+  <div style="width: 100%;;display: flex;">
+    <div style="width: 15%;;background-color: #F2F6FC;max-height: 85vh;overflow: auto;">
+      <div style="display: flex;padding-top: 1%;padding-top: 5%;">
+        <el-input
+          v-model="inputNode"
+          style="width:75%;margin-left: 5%;background-color: #ebeef5;"
+          class="w-50 m-2"
+          :prefix-icon="Search" 
+        />
+        <!-- <el-button style="margin-left: 2%;width: 10%;background-color: #F7F7F7" :icon="Filter"/> -->
+        <el-button type="primary" @click="showAdd" style="margin-left: 5%;width: 10%;" :icon="Plus"/>
+      </div>
+      <!-- <Plus style="width: 1em; height: 1em; margin-left:90%;cursor: pointer;color: #337ecc;" @click="showAddTree"/> -->
+      <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">
+          <template #default="{ node, data }">
+            <span  style="justify-content: space-between;display: flex;width: 100%;align-items: center;">
+              <div class="custom-tree-node">
+                  <!-- <el-tag v-if="data.nodeType=='MODEL'" class="ml-2" type="warning">模型</el-tag> -->
+                   <svg-icon icon-class="模型2" style="color: #eebe77;" v-if="data.nodeType=='MODEL'"/>
+                  <!-- <el-tag  class="ml-2">
+                    服务
+                  </el-tag> -->
+                  <svg-icon icon-class="模型" dstyle="color: #13E03B;" v-if="data.nodeType=='SERVICE'"/>
+                  <svg-icon icon-class="分类" style="color: red;" v-if="data.nodeType=='TREE'"/>
+                <span>{{ node.label }}</span>
+              </div>
+              <div style="margin-right: 1%;position: absolute;margin-left: 75%;">
+                <el-dropdown trigger="hover" @click.stop v-if="currentNodeKey === data.id&&data.nodeType!=='SERVICE'">
+                    <el-icon class="el-icon--right" style="color: black;">
+                      <plus />
+                    </el-icon>
+                  <template #dropdown>
+                    <el-dropdown-menu>
+                      <el-dropdown-item style="display: flex;" @click="add1Level">
+                        <el-icon class="el-icon--right" style="color: black;">
+                          <CirclePlus />
+                        </el-icon>
+                        <div>
+                          添加同级
+                        </div>
+                      </el-dropdown-item>
+                      <el-dropdown-item style="display: flex;"  @click="addNextLevel">
+                        <el-icon class="el-icon--right" style="color: black;">
+                          <Connection />
+                        </el-icon>
+                        <div>
+                          新建下级
+                        </div>
+                      </el-dropdown-item>
+                      <divider/>
+                      <el-dropdown-item style="display: flex;"  @click="delAll" divided>
+                        <el-icon class="el-icon--right" style="color: black;">
+                          <CircleClose />
+                        </el-icon>
+                        <div>
+                          删除节点
+                        </div>
+                      </el-dropdown-item>
+                    </el-dropdown-menu>
+                  </template>
+                </el-dropdown>
+              </div>
+            </span>
+          </template>
+        </el-tree>
+    </div>
+    <div style="width: 84%;margin-left: 1%;padding-top: 1%;" class="tab-container">
+        <div style="overflow: auto;height: 80vh;">
+                  <div style="display: flex;margin-top: 1%;">
+                    <el-button type="primary" @click="saveEditService" style="margin-left: 80%;z-index: 1000;" :disabled="isEdit">提交</el-button>
+                    <el-button type="danger" @click="delSer" style="margin-left: 1%;z-index: 1000;" :disabled="isEdit">删除</el-button>
+                  </div>
+                    <el-form size="mini" :key="tableKey" style="margin-top: -2%;width: 98%;"  :model="formJi" label-position="right" ref="formRefJi" label-width="120px" :rules="rulesJi">
+                      <el-row :gutter="48">
+                            <el-col :span="10">
+                              <el-form-item label="服务名称:" prop="name" style="">
+                                  <div style="display: flex;width: 100%;justify-content: space-between;">
+                                    <el-input :disabled="isEdit" v-model="formJi.name" style="width: 100%;"/>
+                                  </div>
+                              </el-form-item>
+                            </el-col>
+                            <el-col :span="6">
+                              <el-form-item label="接口类型:" prop="" style="">
+                                <div style="display: flex;width: 100%;justify-content: space-between;">
+                                  <el-select
+                                    v-model="formJi.type"
+                                    :disabled="isEdit"
+                                        style="width: 100%;margin-left: 0%;"
+                                    >
+                                        <el-option
+                                        v-for="item in optionsType"
+                                        :key="item.value"
+                                        :label="item.label"
+                                        :value="item.value"
+                                        />
+                                    </el-select>
+                                  <div style="display: flex;">
+                                    
+                                  </div>
+                                </div>
+                                    
+                                </el-form-item>
+                            </el-col>
+                      </el-row>
+                      <el-row :gutter="48">
+                            <el-col :span="10">
+                              <el-form-item label="接口地址:" prop="url" style=""> 
+                                  <el-input
+                                  v-model="formJi.url"
+                                  :disabled="isEdit"
+                                  style="width: 100%;"
+                                  placeholder=""
+                                  class="input-with-select"
+                                  >
+                                </el-input>
+                              </el-form-item>
+                            </el-col>
+                            <el-col :span="6">
+                                <el-form-item label="请求方式:" prop="" style="">
+                                    <el-select
+                                    v-model="formJi.rqtype"
+                                    :disabled="isEdit"
+                                        style="width: 100%;margin-left: 0%;"
+                                    >
+                                        <el-option
+                                        v-for="item in optionsRqtype"
+                                        :key="item.value"
+                                        :label="item.label"
+                                        :value="item.value"
+                                        />
+                                    </el-select>
+                                </el-form-item>
+                            </el-col>
+                      </el-row>
+                      <el-row :gutter="48">
+                            <el-col :span="10">
+                              <el-form-item label="响应类型:" prop="" style="display: flex; align-items: center;">
+                                <el-radio-group :disabled="isEdit" v-model="formJi.rptype" class="ml-4" style="display: inline-flex; align-items: center;">
+                                  <el-radio label="1" size="large" style="display: inline-flex; align-items: center;">
+                                    <span style="position: relative; top: -1px">JSON</span> <!-- 微调文字位置 -->
+                                  </el-radio>
+                                  <el-radio label="2" size="large" style="display: inline-flex; align-items: center;">
+                                    <span style="position: relative; top: -1px">XML</span>
+                                  </el-radio>
+                                  <el-radio label="3" size="large" style="display: inline-flex; align-items: center;">
+                                    <span style="position: relative; top: -1px">HTML</span>
+                                  </el-radio>
+                                </el-radio-group>
+                              </el-form-item>
+                            </el-col>
+                            <el-col :span="6">
+                                <el-form-item label="服务分类:" prop="cateCode" style="">
+                                    <el-cascader :disabled="isEdit" v-model="formJi.cateCode" :options="cascaderOptions" :props="props1" clearable style="width: 100%;"></el-cascader>
+                                </el-form-item>
+                            </el-col>
+                            <!-- <el-col :span="8">
+                                <el-form-item label="请求方式:" prop="name" style="">
+                                    <el-select
+                                    v-model="formJi.type"
+                                    :disabled="isEdit"
+                                        style="width: 100%;margin-left: 0%;"
+                                    >
+                                        <el-option
+                                        v-for="item in optionsType"
+                                        :key="item.value"
+                                        :label="item.label"
+                                        :value="item.value"
+                                        />
+                                    </el-select>
+                                </el-form-item>
+                            </el-col> -->
+                      </el-row>
+                      <el-row :gutter="48">
+                            <el-col :span="13">
+                              <el-form-item label="服务说明:">
+                                  <el-input :disabled="isEdit" v-model="formJi.intro" style="width: 100%;" :rows="3" resize="none" type="textarea"/>
+                              </el-form-item>
+                            </el-col>
+                      </el-row>
+                        
+                    </el-form>
+                    <div style="margin-top: 2%;">
+                        <div style="display: flex;justify-content: space-between;align-items: center;">
+                          <div>
+                            请求参数
+                          </div>
+                          <div style="display: flex;justify-content: flex-end;margin-right: 2%;">
+                            <el-button  @click="addPa" style="margin-top: 1%;" type="success" size="mini" plain>新增参数</el-button>
+                          </div>
+                        </div>
+                        <div>
+                            <el-table 
+                            style="margin-top: 1%;width: 98%;"
+                            :data="tableDataCan" 
+                            :cell-style="{ textAlign: 'center',padding:'2px 0' }"
+                            :header-cell-style="{ textAlign: 'center'}"
+                            :row-style="{ height: heightAll*0.01+'px',fontSize: '16px',textAlign:'center'  }"
+                            border >
+                                <el-table-column prop="itemName" label="参数字段">
+                                    <template #default="scope">
+                                        <div style="width: 100%;">
+                                            <el-input  placeholder="请填写参数编码" type="primary" class="noBor" v-model="scope.row.paramCode" size="mini" text style="margin-left: 0%;border: transparent;"></el-input>
+                                        </div>
+                                    </template>
+                                </el-table-column>
+                                <el-table-column prop="itemName" label="参数名称">
+                                    <template #default="scope">
+                                        <div style="width: 100%;">
+                                            <el-input placeholder="请填写参数名称" type="primary" class="noBor" v-model="scope.row.itemName" size="mini" text style="margin-left: 0%;"></el-input>
+                                        </div>
+                                    </template>
+                                </el-table-column>
+                                <el-table-column prop="itemName" label="参数类型" width="200">
+                                    <template #default="scope">
+                                        <div style="width: 100%;">
+                                            <el-select
+                                            v-model="scope.row.paramType"
+                                            class="noBorSel"
+                                            placeholder=""
+                                            style="width: 100%;margin-left: 0%;"
+                                            >
+                                                <el-option
+                                                v-for="item in optionsCan"
+                                                :key="item.value"
+                                                :label="item.label"
+                                                :value="item.value"
+                                                />
+                                    </el-select>
+                                        </div>
+                                    </template>
+                                </el-table-column>
+                                <el-table-column prop="itemName" label="参数说明" >
+                                    <template #default="scope">
+                                        <div style="width: 100%;">
+                                            <el-input type="primary" class="noBor" v-model="scope.row.paramNote" size="mini" text style="margin-left: 0%;"></el-input>
+                                        </div>
+                                    </template>
+                                </el-table-column>
+                                <el-table-column prop="address" label="操作" width="100">
+                                    <template #default="scope">
+                                        <div style="width: 100%;">
+                                            <el-button type="danger" @click="delCan(scope.$index)" size="mini" text style="margin-left: 0%;">删除</el-button>
+                                        </div>
+                                    </template>
+                                </el-table-column>
+                            </el-table>
+                            
+                        </div>
+                    </div>
+                    <div style="margin-top: 2%;">
+                        <!-- <div>返回响应</div> -->
+                        <div style="color: #909399;margin-left: 7%;margin-top:1%;">此处填写本服务接口响应信息描述</div>
+                        <el-tabs type="card" style="margin-top: -1.5%;width: 98%;">
+                            <el-tab-pane label="响应内容">
+                                <div style="display: flex; flex-direction: column;">
+                                    <!-- <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>
+                                        <template #default="{ node, data }">
+                                            <span style="display: flex;justify-content: space-between;width: 100%;align-items: center;">
+                                                <span><el-input v-model="node.label" size="mini"/></span>
+                                                <span style="display: flex;align-items: center;">
+                                                    <el-tooltip
+                                                        class="box-item"
+                                                        effect="light"
+                                                        content="是否必填"
+                                                        placement="top-start"
+                                                    >
+                                                    <el-checkbox v-model="checked1" label="" size="large" />
+                                                    </el-tooltip>
+                                                    <el-select
+                                                        v-model="formJi.type"
+                                                        :disabled="isEdit"
+                                                        style="width: 100%;margin-left: -1%;"
+                                                    >
+                                                        <el-option
+                                                        v-for="item in optionsType"
+                                                        :key="item.value"
+                                                        :label="item.label"
+                                                        :value="item.value"
+                                                        />
+                                                    </el-select>
+                                                    <el-tooltip
+                                                        class="box-item"
+                                                        effect="light"
+                                                        content="是否允许null"
+                                                        placement="top-start"
+                                                    >
+                                                    <el-checkbox v-model="checked1" label="" size="large" />
+                                                    </el-tooltip>
+                                                </span>
+                                            </span>
+                                        </template>
+                                    </el-tree> -->
+                                   </div>
+                            </el-tab-pane>
+                        </el-tabs>
+                        <div style="overflow: auto;height: 20vh;margin-top: -1%;">
+                          <!-- <JsonEditorVue
+                            v-model="dataJsonXiang"
+                            style="height:98%;width: 98%;"
+                            :mode="'code'"
+                            :showBtns="false"
+                            :options="{
+                              navigationBar: false, // 隐藏顶部导航栏
+                              statusBar: false,     // 隐藏底部状态栏
+                              mode: 'code',          // 仅保留代码编辑模式
+                              mainMenuBar: false     // 隐藏主菜单栏
+                            }"
+                            lang="zh"
+                          /> -->
+                          <el-input placeholder="请输入示例" :rows="8" type="textarea" v-model="dataJsonXiang" size="mini" text style="margin-top: 0%;width: 98%;" ></el-input>
+                        </div>
+                    </div>
+                    <div style="margin-top: 2.5%;margin-left: 0%;padding-bottom: 1%;">
+                    
+                    <el-tabs type="card" style="margin-top: -1.5%;width: 98%;">
+                        <el-tab-pane label="使用说明">
+                             
+                        </el-tab-pane>
+                    </el-tabs>
+                    <el-input placeholder="请输入示例" :rows="8" type="textarea" v-model="example" size="mini" text style="margin-top: -1%;width: 98%;" ></el-input>
+                </div>
+                </div>
+        <el-dialog @close="clearAdd" v-model="dialogVisible" title="新增节点" width="70%" destroy-on-close :key="tableKey">
+          <div style="overflow: auto;height: 80vh;">
+                    <el-form size="mini" :key="tableKey" style="margin-top: 1%;width: 98%;"  :model="formAdd" label-position="right" ref="formRefAdd" label-width="120px" :rules="rulesAdd">
+                      <el-row :gutter="48">
+                            <el-col :span="10">
+                              <el-form-item label="服务名称:" prop="name" style="">
+                                  <div style="display: flex;width: 100%;justify-content: space-between;">
+                                    <el-input v-model="formAdd.name" style="width: 100%;"/>
+                                  </div>
+                              </el-form-item>
+                            </el-col>
+                            <el-col :span="6">
+                              <el-form-item label="接口类型:" prop="" style="">
+                                <div style="display: flex;width: 100%;justify-content: space-between;">
+                                  <el-select
+                                    v-model="formAdd.type"
+                                    :disabled="isEdit"
+                                        style="width: 100%;margin-left: 0%;"
+                                    >
+                                        <el-option
+                                        v-for="item in optionsType"
+                                        :key="item.value"
+                                        :label="item.label"
+                                        :value="item.value"
+                                        />
+                                    </el-select>
+                                  <div style="display: flex;">
+                                    
+                                  </div>
+                                </div>
+                                    
+                                </el-form-item>
+                            </el-col>
+                      </el-row>
+                      <el-row :gutter="48">
+                            <el-col :span="10">
+                              <el-form-item label="接口地址:" prop="url" style=""> 
+                                  <el-input
+                                  v-model="formAdd.url"
+                                  style="width: 100%;"
+                                  placeholder=""
+                                  class="input-with-select"
+                                  >
+                                </el-input>
+                              </el-form-item>
+                            </el-col>
+                            <el-col :span="6">
+                                <el-form-item label="请求方式:" prop="" style="">
+                                    <el-select
+                                    v-model="formAdd.rqtype"
+                                    :disabled="isEdit"
+                                        style="width: 100%;margin-left: 0%;"
+                                    >
+                                        <el-option
+                                        v-for="item in optionsRqtype"
+                                        :key="item.value"
+                                        :label="item.label"
+                                        :value="item.value"
+                                        />
+                                    </el-select>
+                                </el-form-item>
+                            </el-col>
+                      </el-row>
+                      <el-row :gutter="48">
+                            <el-col :span="10">
+                              <el-form-item label="所属模型:" prop="mdid" style="">
+                                <el-tree-select
+                                  v-model="formAdd.mdid"
+                                  :data="optionsMdid"
+                                  check-strictly
+                                  :render-after-expand="false"
+                                  style="width: 100%"
+                                />
+                                <!-- <el-select
+                                v-model="formAdd.mdid"
+                                    style="width: 100%;margin-left: 0%;"
+                                >
+                                    <el-option
+                                    v-for="item in optionsMdid"
+                                    :key="item.value"
+                                    :label="item.label"
+                                    :value="item.id"
+                                    />
+                                </el-select> -->
+                      </el-form-item>
+                            </el-col>
+                      </el-row>
+                      <el-row :gutter="48">
+                            <el-col :span="10">
+                              <el-form-item label="响应类型:" prop="" style="display: flex; align-items: center;">
+                                <el-radio-group v-model="formAdd.rptype" class="ml-4" style="display: inline-flex; align-items: center;">
+                                  <el-radio label="1" size="large" style="display: inline-flex; align-items: center;">
+                                    <span style="position: relative; top: -1px">JSON</span> <!-- 微调文字位置 -->
+                                  </el-radio>
+                                  <el-radio label="2" size="large" style="display: inline-flex; align-items: center;">
+                                    <span style="position: relative; top: -1px">XML</span>
+                                  </el-radio>
+                                  <el-radio label="3" size="large" style="display: inline-flex; align-items: center;">
+                                    <span style="position: relative; top: -1px">HTML</span>
+                                  </el-radio>
+                                </el-radio-group>
+                              </el-form-item>
+                            </el-col>
+                            <el-col :span="6">
+                                <el-form-item label="服务分类:" prop="cateCode" style="">
+                                    <el-cascader v-model="formAdd.cateCode" :options="cascaderOptions" :props="props1" clearable style="width: 100%;"></el-cascader>
+                                </el-form-item>
+                            </el-col>
+                            <!-- <el-col :span="8">
+                                <el-form-item label="请求方式:" prop="name" style="">
+                                    <el-select
+                                    v-model="formJi.type"
+                                    :disabled="isEdit"
+                                        style="width: 100%;margin-left: 0%;"
+                                    >
+                                        <el-option
+                                        v-for="item in optionsType"
+                                        :key="item.value"
+                                        :label="item.label"
+                                        :value="item.value"
+                                        />
+                                    </el-select>
+                                </el-form-item>
+                            </el-col> -->
+                      </el-row>
+                      <el-row :gutter="48">
+                            <el-col :span="13">
+                              <el-form-item label="服务说明:">
+                                  <el-input v-model="formAdd.intro" style="width: 100%;" :rows="3" resize="none" type="textarea"/>
+                              </el-form-item>
+                            </el-col>
+                      </el-row>
+                        
+                    </el-form>
+                    <div style="margin-top: 2%;">
+                        <div style="display: flex;justify-content: space-between;align-items: center;">
+                          <div>
+                            请求参数
+                          </div>
+                          <div style="display: flex;justify-content: flex-end;margin-right: 2%;">
+                            <el-button  @click="addCanAdd" style="margin-top: 1%;" type="success" size="mini" plain>新增参数</el-button>
+                          </div>
+                        </div>
+                        <div>
+                            <el-table 
+                            style="margin-top: 1%;width: 98%;"
+                            :data="tableDataCanAdd" 
+                            :cell-style="{ textAlign: 'center',padding:'2px 0' }"
+                            :header-cell-style="{ textAlign: 'center'}"
+                            :row-style="{ height: heightAll*0.01+'px',fontSize: '16px',textAlign:'center'  }"
+                            border >
+                                <el-table-column prop="itemName" label="参数字段">
+                                    <template #default="scope">
+                                        <div style="width: 100%;">
+                                            <el-input placeholder="请填写参数编码" type="primary" class="noBor" v-model="scope.row.paramCode" size="mini" text style="margin-left: 0%;border: transparent;"></el-input>
+                                        </div>
+                                    </template>
+                                </el-table-column>
+                                <el-table-column prop="itemName" label="参数名称">
+                                    <template #default="scope">
+                                        <div style="width: 100%;">
+                                            <el-input placeholder="请填写参数名称" type="primary" class="noBor" v-model="scope.row.paramName" size="mini" text style="margin-left: 0%;"></el-input>
+                                        </div>
+                                    </template>
+                                </el-table-column>
+                                <el-table-column prop="itemName" label="参数类型" width="200">
+                                    <template #default="scope">
+                                        <div style="width: 100%;">
+                                            <el-select
+                                            v-model="scope.row.paramType"
+                                            class="noBorSel"
+                                            placeholder=""
+                                            style="width: 100%;margin-left: 0%;"
+                                            >
+                                                <el-option
+                                                v-for="item in optionsCan"
+                                                :key="item.value"
+                                                :label="item.label"
+                                                :value="item.value"
+                                                />
+                                    </el-select>
+                                        </div>
+                                    </template>
+                                </el-table-column>
+                                <el-table-column prop="itemName" label="参数说明" >
+                                    <template #default="scope">
+                                        <div style="width: 100%;">
+                                            <el-input type="primary" class="noBor" v-model="scope.row.paramNote" size="mini" text style="margin-left: 0%;"></el-input>
+                                        </div>
+                                    </template>
+                                </el-table-column>
+                                <el-table-column prop="address" label="操作" width="100">
+                                    <template #default="scope">
+                                        <div style="width: 100%;">
+                                            <el-button type="danger" @click="delCanAdd(scope.$index)" size="mini" text style="margin-left: 0%;">删除</el-button>
+                                        </div>
+                                    </template>
+                                </el-table-column>
+                            </el-table>
+                            
+                        </div>
+                    </div>
+                    <div style="margin-top: 2%;">
+                        <!-- <div>返回响应</div> -->
+                        <div style="color: #909399;margin-left: 8%;margin-top:1%;">此处填写本服务接口响应信息描述</div>
+                        <el-tabs type="card" style="margin-top: -2%;width: 98%;">
+                            <el-tab-pane label="响应内容">
+                                <div style="display: flex; flex-direction: column;">
+                                   </div>
+                            </el-tab-pane>
+                        </el-tabs>
+                        <div style="overflow: auto;height: 20vh;margin-top: -1%;">
+                          <el-input placeholder="请输入示例" :rows="8" type="textarea" v-model="JsonAdd" size="mini" text style="margin-top: 0%;width: 98%;" ></el-input>
+                        </div>
+                    </div>
+                    <div style="margin-top: 2.5%;margin-left: 0%;padding-bottom: 1%;">
+                    
+                    <el-tabs type="card" style="margin-top: -1.5%;width: 98%;">
+                        <el-tab-pane label="使用说明">
+                             
+                        </el-tab-pane>
+                    </el-tabs>
+                    <el-input placeholder="请输入示例" :rows="8" type="textarea" v-model="exampleAdd" size="mini" text style="margin-top: -1%;width: 98%;" ></el-input>
+                </div>
+                </div>
+                <template #footer>
+                  <span class="dialog-footer">
+                    <el-button size="mini" @click="dialogVisible = false">取消</el-button>
+                    <el-button type="primary" @click="addSer" size="mini">
+                      提交
+                    </el-button>
+                </span>
+              </template>
+        </el-dialog>
+        <el-dialog @close="clearFromLev" title="添加目录" v-model="dialogVisibleLevel" width="30%" destroy-on-close :key="tableKey">
+          <el-form size="mini" :key="tableKey" style="margin-top: 1%;width: 90%;"  :model="formLev" label-position="right" ref="formRefLev" label-width="120px" :rules="rulesLev">
+            <el-form-item label="名称:" prop="itemName" style="">
+              <el-input v-model="formLev.itemName" style="width: 100%;"/>
+            </el-form-item>
+            <el-form-item label="说明:" prop="itemNotes" style="">
+              <el-input v-model="formLev.itemNotes" style="width: 100%;"/>
+            </el-form-item>
+            <el-form-item label="排序:" prop="itemNo" style="">
+              <el-input-number v-model="formLev.itemNo" style="width: 100%;" :min="1" :max="10000" @change="handleChange" />
+            </el-form-item>
+          </el-form>
+          <template #footer>
+              <span class="dialog-footer">
+                <el-button size="mini" @click="dialogVisibleLevel = false">取消</el-button>
+                <el-button type="primary" @click="saveAdd1Level" size="mini" v-if="show1Lev">
+                  提交
+                </el-button>
+                <el-button type="primary" @click="saveAddNextLevel" size="mini" v-if="!show1Lev">
+                  提交
+                </el-button>
+            </span>
+          </template>
+        </el-dialog>
+    </div>
+  </div>
+</template>
+<script   setup>
+import {getCatalog} from "@/api/service/catalog";
+import { Plus,Search,Filter,Promotion,Check  } from '@element-plus/icons-vue'
+import { reactive } from 'vue'
+import { modelTreeSelect,getSerDe,addService,addParam,editService,editParam,addServiceParam,delService,getTreeDe,addTree,deTree } from "@/api/service/info";
+import { ref, onMounted, onUnmounted, nextTick,onBeforeMount } from 'vue';
+import JsonViewer from 'vue-json-viewer'
+import 'vue-json-viewer/style.css' 
+import  JsonEditorVue from 'json-editor-vue3'
+import { cloneDeep } from 'lodash'
+import { useClipboard } from "@vueuse/core";
+
+const { proxy } = getCurrentInstance();
+const JsonAdd= ref(JSON.stringify({ data: "初始值1" }))
+const exampleAdd = ref('')
+const dialogVisibleLevel = ref(false)
+const detail = ref({
+  name:'',
+  rqtype:'',
+  rptype:''
+})
+const show1Lev = ref(true)
+const inputNode =ref('')
+const isEdit = ref(true)
+const dataReturn = ref({})
+const optionsCan = ref([
+  {
+    label:"string",
+    value:'string'
+  },
+  {
+    label:"int",
+    value:'int'
+  },
+  {
+    label:"boolean",
+    value:'boolean'
+  },
+  {
+    label:"array",
+    value:'array'
+  },
+  {
+    label:"object",
+    value:'object'
+  },
+  {
+    label:"number",
+    value:'number'
+  },
+  {
+    label:"null",
+    value:'null'
+  },
+  {
+    label:"any",
+    value:'any'
+  },
+  
+])
+const currentNodeKey = ref('')
+const options =  ref([
+    {label:'开发中',
+    value:'1'
+    },
+    {label:'运行中',
+    value:'2'
+    },
+])
+const dataJsonXiang = ref([])
+const parTree = ref({})
+const valueKet = ref(0)
+const tableDataCan = ref([
+    {
+      itemName:'',
+      itemCode:'',
+      paramType:'',
+      paramNote:''
+    }
+])
+const optionsMdid = ref([])
+const optionsRqtype = ref([
+    {label:'GET',
+    value:'GET'
+    },
+    {label:'POST',
+    value:'POST'
+    },
+])
+const optionsType=  ref([
+    {label:'RESTful',
+    value:'RESTful'
+    },
+    {label:'WebService',
+    value:'WebService'
+    },
+    {label:'HTTP',
+    value:'HTTP'
+    },
+    {label:'WebSocket',
+    value:'WebSocket'
+    },
+])
+const data =  ref([])
+const select =  ref('1')
+const activeName =  ref('first')
+const title =  ref('')
+const titleTree =  ref('')
+const currentPage =  ref(1)
+const total =  ref(1)
+const tableData = ref([])
+const tableheight = window.innerHeight*0.7
+const heightAll = window.innerHeight
+const dialogVisible = ref(false)
+const dialogVisibleTree = ref(false)
+const isAdd = ref(false)
+const isAddTa = ref(false)
+const treeId = ref('');
+const valueSta = ref('1');
+const example = ref('');
+const tableDataCanAdd = ref([
+  {
+      itemName:'',
+      itemCode:'',
+      paramType:'',
+      paramNote:''
+    }
+])
+const formZu = ref({
+  itemName:'',
+  itemTp:'',
+  itemEn:'',
+  itemTp:'',
+  itemDataTp:'',
+  itemDefaultVal:'',
+  itemUnit:'',
+  itemNotes:'',
+});
+const parId= ref('')
+const formJi = ref({
+  name:'',
+  cateCode:'',
+  type:'',
+  url:'',
+  rqtype:'',
+  rptype:'',
+  intro:'',
+});
+const rulesJi = reactive({
+  name: [{ required: true, message: '必填', trigger: 'blur' }],
+  url: [{ required: true, message: '必填', trigger: 'blur' }],
+  cateCode: [{ required: true, message: '必填', trigger: 'blur' }],
+});
+const formRefJi = ref();
+const formAdd = ref({
+  name:'',
+  cateCode:'',
+  type:'',
+  url:'',
+  rqtype:'',
+  rptype:'',
+  intro:'',
+  mdid:''
+});
+const rulesAdd = reactive({
+  mdid: [{ required: true, message: '必填', trigger: 'blur' }],
+  name: [{ required: true, message: '必填', trigger: 'blur' }],
+  url: [{ required: true, message: '必填', trigger: 'blur' }],
+  cateCode: [{ required: true, message: '必填', trigger: 'blur' }],
+});
+const formRefAdd = ref();
+const treeRef = ref(null);
+const formTree = ref({
+  itemName:'',
+  catePid:'',
+  itemNo:'',
+  itemNotes:''
+});
+const rulesTree = reactive({
+  itemNo: [{ required: true, message: '必填', trigger: 'blur' }],
+  catePid: [{ required: true, message: '必填', trigger: 'blur' }],
+  itemName: [{ required: true, message: '必填', trigger: 'blur' }],
+});
+const formRefTree = ref();
+const formLev = ref({
+  itemName:'',
+  itemNo:'',
+  itemNotes:'',
+});
+const rulesLev = reactive({
+  itemNotes: [{ required: true, message: '必填', trigger: 'blur' }],
+  itemNo: [{ required: true, message: '必填', trigger: 'blur' }],
+  itemName: [{ required: true, message: '必填', trigger: 'blur' }],
+});
+const formRefLev = ref();
+const cascaderOptions = ref([])
+const props1 = ref({
+  checkStrictly: true,
+})
+const detailJson = ref([])
+
+watch(inputNode, (val) => {
+  treeRef.value?.filter(val); // 调用树的过滤方法
+});
+const filterNode = (value, data) => {
+  if (!value) return true; // 空搜索时显示所有节点
+  return data.label.includes(value); // 检查节点标签是否包含关键字
+};
+
+const copied = ref(false);
+
+async function copyUrl(){
+  try {
+    await navigator.clipboard.writeText(detail.value.url);
+    copied.value = true;
+    console.log(detail.url.value,copied.value)
+    setTimeout(() => (copied.value = false), 2000); // 2秒后提示消失
+  } catch (err) {
+    console.error("复制失败", err);
+  }
+};
+function filterModelNodes(nodes) {
+  if (!Array.isArray(nodes)) return [];
+  
+  const result = [];
+  for (const node of nodes) {
+    // 递归处理子节点(如果有)
+    const filteredChildren = node.children ? filterModelNodes(node.children) : [];
+    
+    if (node.nodeType === 'MODEL') {
+      // 保留当前节点,并更新其子节点
+      node.value = node.id
+      result.push({
+        ...node,
+        children: filteredChildren
+      });
+    } else {
+      // 删除当前节点,将其子节点提升到当前层级
+      result.push(...filteredChildren);
+    }
+  }
+  return result;
+}
+function clearAdd(){
+  formAdd.value = {
+    name:'',
+    cateCode:'',
+    type:'',
+    url:'',
+    rqtype:'',
+    rptype:'',
+    intro:'',
+    mdid:''
+  }
+  tableDataCanAdd.value = {
+    itemName:'',
+    itemCode:'',
+    paramType:'',
+    paramNote:''
+  }
+  JsonAdd.value = ''
+  exampleAdd.value = ''
+}
+function extractModelNodesDFSIterative(root) {
+  const result = [];
+  const stack = root;
+  
+  while (stack.length > 0) {
+    const node = stack.pop();
+    if (node.nodeType === 'MODEL') {
+      result.push(node);
+    }
+    
+    // 子节点逆序入栈(保证从左到右遍历)
+    if (node.children) {
+      for (let i = node.children.length - 1; i >= 0; i--) {
+        stack.push(node.children[i]);
+      }
+    }
+  }
+  return result;
+}
+function delAll(){
+  proxy.$modal.confirm('是否确认删除?').then(function () {
+    return deTree(parTree.value.id);
+  }).then(() => {
+    getTreeLeft();
+    proxy.$modal.msgSuccess("删除成功");
+    dialogVisibleLevel.value = false
+  }).catch(() => {});
+}
+function clearFromLev(){
+  formLev.value = {
+    itemName:'',
+    itemNo:'',
+    itemNotes:'',
+  }
+}
+function addNextLevel(){
+  dialogVisibleLevel.value = true
+  show1Lev.value = false
+}
+function saveAddNextLevel(){
+   formRefLev.value.validate((valid) => {
+    if(valid){
+      var par = formLev.value
+      par.treeType = parTree.value.nodeType
+      par.treePid = parTree.value.id
+      addTree(par).then(res=>{
+        if(res.code===200){
+          proxy.$modal.msgSuccess("新增成功");
+          getTreeLeft()
+          dialogVisibleLevel.value = false
+        }
+      })
+    }
+  });
+}
+function add1Level(){
+  dialogVisibleLevel.value = true
+  show1Lev.value = true
+}
+function saveAdd1Level(){
+  formRefLev.value.validate((valid) => {
+    if(valid){
+      var par = formLev.value
+      par.treeType = parTree.value.nodeType
+      par.treePid = parTree.value.pid
+      addTree(par).then(res=>{
+        if(res.code===200){
+          proxy.$modal.msgSuccess("新增成功");
+          getTreeLeft()
+          dialogVisibleLevel.value = false
+        }
+      })
+    }
+  });
+}
+async function delSer(){
+  proxy.$modal.confirm('是否确认删除?').then(function () {
+    return delService(parId.value.id);
+  }).then(() => {
+    getTreeLeft();
+    proxy.$modal.msgSuccess("删除成功");
+  }).catch(() => {});
+}
+async function saveEditService(){
+  console.log(JsonAdd.value)
+  var valid
+  await formRefJi.value.validate((valid1) => {
+    valid = valid1
+  });
+  console.log(valid)
+  if(valid){
+    var par = formJi.value
+    par.example = example.value
+    par.rpcontent = dataJsonXiang.value
+    par.cateCode = par.cateCode[0]
+    console.log(par)
+    await editService(par).then(res=>{
+      if(res.code===200){
+        var parCan = tableDataCan.value
+        // parCan.srvId = parId.value.srvId
+        addServiceParam(parCan).then(res1=>{
+          if(res1.code===200){
+            proxy.$modal.msgSuccess("修改成功");
+            getTreeLeft()
+          }
+        })
+      }
+    })
+  }
+}
+async function addSer(){
+  console.log(JsonAdd.value)
+  var valid
+  await formRefAdd.value.validate((valid1) => {
+    valid = valid1
+  });
+  console.log(valid) 
+  if(valid){
+    var par = formAdd.value
+    par.example = exampleAdd.value
+    par.rpcontent = JsonAdd.value
+    par.cateCode = par.cateCode[0]
+    console.log(par)
+
+    await addService(par).then(res=>{
+      if(res.code===200){
+        var parCan = tableDataCanAdd.value
+        parCan.srvId = res.data.srvId
+        addServiceParam(parCan).then(res1=>{
+          if(res1.code===200){
+            proxy.$modal.msgSuccess("新增成功");
+            getTreeLeft()
+          }
+        })
+      }
+    })
+    
+    
+  }
+
+}
+function showAdd(){
+  dialogVisible.value = true
+}
+async function handleNodeClick(node,data,event){
+  parTree.value = data.data
+  currentNodeKey.value = data.data.id
+  console.log(data.data.nodeType)
+  isEdit.value = false
+  parId.value = data.data
+  await getSerDe(data.data.id).then(res=>{
+    detail.value = res.data.ptService
+    tableDataCan.value = res.data.list
+    dataReturn.value = res.data.returnList
+    console.log(tableDataCan.value)
+    dataJsonXiang.value = res.data.ptService.rpcontent
+    formJi.value = res.data.ptService
+    example.value = res.data.ptService.example
+  })
+  detail.value.nodeType = data.data.nodeType
+  
+}
+async function getTreeLeft(){
+  var par
+  await modelTreeSelect().then(res=>{
+    par = res.data
+    data.value = res.data
+    
+  })
+  optionsMdid.value = filterModelNodes(par)
+  console.log(optionsMdid.value)
+}
+function renameTreeProperties(tree) {
+  // 深拷贝避免修改原始数据(可选,根据需求)
+  const newTree = cloneDeep(tree); // 使用 lodash
+  // 或:const newTree = JSON.parse(JSON.stringify(tree)); // 原生方法(不兼容函数等)
+
+  // 递归处理函数
+  const processNode = (node) => {
+    // 重命名属性
+    if ('cateName' in node) {
+      node.label = node.cateName;
+      delete node.cateName;
+    }
+    if ('cateCode' in node) {
+      node.value = node.cateCode;
+      delete node.cateCode;
+    }
+
+    // 递归处理子节点
+    if (node.children && node.children.length > 0) {
+      node.children.forEach(child => processNode(child));
+    }
+  };
+
+  // 遍历根节点
+  newTree.forEach(rootNode => processNode(rootNode));
+  return newTree;
+}
+function fetchData() {
+  getCatalog().then((r) => {
+    cascaderOptions.value = renameTreeProperties(buildTree(r.data))
+    console.log(cascaderOptions.value)
+  });
+}
+function buildTree(flatData, rootValue = '0') {
+      const nodeMap = new Map();
+      const tree = [];
+      flatData.forEach(item => {
+        nodeMap.set(item.cateCode, { ...item, children: [] });
+      });
+      for (const [code, node] of nodeMap) {
+        const parentCode = node.catePcode;
+        if (parentCode === rootValue || !parentCode) {
+          tree.push(node);
+          continue;
+        }
+        const parent = nodeMap.get(parentCode);
+        if (parent) {
+          parent.children.push(node);
+        } else {
+          console.warn(`Orphan node detected: ${code}. Parent ${parentCode} not found`);
+        }
+      }
+
+      return tree;
+    }
+function addPa(){
+    var par = {
+        itemName:''
+    }
+    tableDataCan.value.push(par)
+}
+function delCan(index){
+  tableDataCan.value.splice(index, 1)
+}
+function addCanAdd(){
+    var par = {
+        itemName:''
+    }
+    tableDataCanAdd.value.push(par)
+}
+function delCanAdd(index){
+  tableDataCanAdd.value.splice(index, 1)
+}
+onMounted(() => {
+  fetchData()
+  getTreeLeft()
+});
+
+</script>
+<style scoped>
+
+.noBorSel :deep(.el-select__wrapper){
+  box-shadow: none !important; /* 去除阴影边框 */
+  border: 1px solid transparent !important; /* 设置透明边框 */
+  background-color: transparent !important; /* 可选:透明背景 */
+}
+.noBor :deep(.el-input__wrapper) {
+  box-shadow: none !important; /* 去除阴影边框 */
+  border: 1px solid transparent !important; /* 设置透明边框 */
+  background-color: transparent !important; /* 可选:透明背景 */
+}
+/* 节点垂直间距 */
+:deep(.el-tree-node) {
+  margin-bottom:5px !important; /* 增大节点间距 */
+}
+.el-popover.custom-popover {
+  min-width: 50px;
+  padding: 8px; /* 可选:调整内边距 */
+}
+</style>
+<style>
+.dot {
+  width: 20px;          /* 控制圆点直径 */
+  height: 20px;
+  background-color: #333; /* 实心颜色 */
+  border-radius: 50%;    /* 关键属性 */
+  display: inline-block; /* 确保与其他元素并排 */
+}
+/* 全局透明样式(不使用 scoped) */
+.transparent-select .el-select__wrapper {
+  background-color: transparent !important;
+  border-color: transparent !important;
+  box-shadow: none !important;
+}
+
+.transparent-select .el-select__selection {
+  background-color: transparent;
+}
+
+/* 处理悬停和聚焦状态 */
+.transparent-select .el-select__wrapper:hover,
+.transparent-select .el-select__wrapper.is-focused {
+  border-color: transparent !important;
+  box-shadow: none !important;
+}
+
+/* 下拉箭头图标 */
+.transparent-select .el-select__caret {
+  color: rgba(0, 0, 0, 0.5); /* 半透明图标 */
+}
+</style>
+<style scoped>
+:deep(.treeLeft) .el-tree-node__content {
+  display: flex !important;
+  height: 28px;                  /* 按设计稿调整高度 */
+  align-items: center;
+  padding-top: 0 !important;
+}
+:deep(.treeLeft) .el-tree-node__content:hover {
+  background-color: #e9e9eb;
+}
+:deep(.treeLeft) .el-tree-node__content:active {
+    background-color: rgka(69,157,255,0.1) !important;
+  }
+
+  /* 选中态(Active) */
+:deep(.treeLeft) .el-tree-node.is-current > .el-tree-node__content {
+    background-color: #c6e2ff !important;
+  }
+
+.tab-container {
+  height: 100vh; /* 关键:父容器明确高度 */
+  display: flex;
+  flex-direction: column;
+}
+.drag-handle {
+  cursor: move;
+}
+
+.ghost {
+  opacity: 0.5;
+  background: #c8ebfb;
+}
+
+/* 防止文字选中 */
+:deep(.el-table__row) {
+  user-select: none;
+  -webkit-user-select: none;
+}
+</style>
+<style scoped lang="scss">
+
+.custom-tree-node {
+  display: flex;       /* 启用 Flex 布局 */
+  align-items: center; /* 垂直居中 */
+  gap: 8px;            /* 图标与文字间距 */
+  justify-content: space-between;
+}
+.el-table .el-table__row td {
+  height: 60px !important; /* 行高 */
+}
+.custom-tree-node {
+  display: flex;       /* 启用 Flex 布局 */
+  align-items: center; /* 垂直居中 */
+  gap: 8px;            /* 图标与文字间距 */
+}
+</style>

+ 61 - 315
ruoyi-ui/src/views/service/info/index.vue

@@ -17,12 +17,12 @@
             <span  style="justify-content: space-between;display: flex;width: 100%;align-items: center;">
               <div class="custom-tree-node">
                   <!-- <el-tag v-if="data.nodeType=='MODEL'" class="ml-2" type="warning">模型</el-tag> -->
-                   <svg-icon icon-class="service1" style="color: #eebe77;" v-if="data.nodeType=='MODEL'"/>
+                   <svg-icon icon-class="模型2" style="color: #eebe77;" v-if="data.nodeType=='MODEL'"/>
                   <!-- <el-tag  class="ml-2">
                     服务
                   </el-tag> -->
-                  <svg-icon icon-class="接口" style="color: #13E03B;" v-if="data.nodeType=='SERVICE'"/>
-                  <svg-icon icon-class="模型" style="color: red;" v-if="data.nodeType=='TREE'"/>
+                  <svg-icon icon-class="模型" dstyle="color: #13E03B;" v-if="data.nodeType=='SERVICE'"/>
+                  <svg-icon icon-class="分类" style="color: red;" v-if="data.nodeType=='TREE'"/>
                 <span>{{ node.label }}</span>
               </div>
               <div style="margin-right: 1%;position: absolute;margin-left: 75%;">
@@ -65,10 +65,8 @@
           </template>
         </el-tree>
     </div>
-    <div style="width: 84%;margin-left: 1%;" class="tab-container">
-        <el-tabs style="" v-model="activeName" class="demo-tabs" @tab-click="handleClick" >
-            <el-tab-pane label="查看" name="first" style="">
-              <div style="height: 80vh;overflow: auto;">
+    <div style="width: 84%;margin-left: 1%;padding-top: 0.5%;" class="tab-container">
+              <div style="height: 90vh;overflow: auto;">
                 <div style="display: flex;align-items: center;justify-content: space-between;">
                     <div style="margin-left:1%;">{{detail.name}}</div>
                     <div style="display: flex;">
@@ -77,14 +75,19 @@
                     </div>
                 </div>
                 <div style="display: flex;align-items: center;margin-left:1%;margin-top: 1%;">
-                    <el-tag v-if="detail.nodeType=='MODEL'" class="ml-2" type="warning">模型</el-tag>
-                    <el-tag v-if="detail.nodeType=='SERVICE'" class="ml-2">
-                      服务
+                    <el-tag v-if="formJi.type" class="ml-2">
+                      {{formJi.type}}
                     </el-tag>
-                    <el-tag v-if="detail.nodeType=='TREE'" class="ml-2" type="success">树</el-tag>
-                    <div style="margin-left: 0.5%;">
+                    <el-tag v-if="formJi.rqtype=='POST'||formJi.rqtype=='post'" style="margin-left:0.5%;" class="ml-2" type="warning">
+                      {{formJi.rqtype}}
+                    </el-tag>
+                    <el-tag v-if="formJi.rqtype=='GET'||formJi.rqtype=='get'" type="success" style="margin-left: 0.5%;" class="ml-2">
+                      {{formJi.rqtype}}
+                    </el-tag>
+                    <div style="margin-left: 1%;">
                         {{detail.url}}
                     </div>
+                    <el-icon style="margin-left: 1%;cursor: pointer;color:#909399" @click="copyUrl"><CopyDocument /></el-icon>
                     <div style="margin-left: 0.5%;">
                         <!-- <el-select class="transparent-select" v-model="valueSta" style="border-color: transparent;width: 100px;">
                             <el-option
@@ -113,30 +116,6 @@
                 </div>
                 <div style="display: flex;width: 100%;">
                     <div style="display: flex;margin-left: 1%;font-size: 15px;color:#909399;width:100%;margin-top: 1%;">
-                        <!-- <div>
-                            服务分类:
-                        </div>
-                        <div style="margin-left: 0.5%;">
-                            {{detail.cateCode}}
-                        </div> -->
-                        <div style="margin-left: 0%;">
-                            请求方式:
-                        </div>
-                        <div style="margin-left: 0.5%;">
-                            {{detail.rqtype}}
-                        </div>
-                        <div style="margin-left: 5%;">
-                            接口类型:
-                        </div>
-                        <div style="margin-left: 0.5%;">
-                            {{detail.name}}
-                        </div>
-                        <div style="margin-left: 5%;">
-                            返回格式:
-                        </div>
-                        <div style="margin-left: 0.5%;">
-                            {{detail.rptype}}
-                        </div>
                         
                     </div>
                 </div>
@@ -157,9 +136,13 @@
                     </div> -->
                 </div>
                 <div style="margin-top: 2.5%;margin-left: 1%;">
-                    <div>请求参数</div>
+                  <el-tabs type="card" style="margin-top: 1%;width: 90%;">
+                    <el-tab-pane label="请求参数">
+
+                    </el-tab-pane>
+                  </el-tabs>
                     <el-table 
-                      style="margin-top: 1%;width: 90%;"
+                      style="margin-top: -1%;width: 90%;"
                       :data="tableDataCan" 
                       :cell-style="{ textAlign: 'center', }"
                       :header-cell-style="{ textAlign: 'center'}"
@@ -176,7 +159,7 @@
                       </el-table>
                 </div>
                 <div style="margin-top: 2.5%;margin-left: 1%;">
-                    <el-tabs type="card" style="margin-top: 1%;width: 98%;">
+                    <el-tabs type="card" style="margin-top: 1%;width: 90%;">
                         <el-tab-pane label="成功(200)">
                             <div style="display: flex;align-items: center;line-height: 1.5;font-size: 14px;margin-left: 1%;color: #606266;">
                                 <!-- <div>HTTP状态码:</div>
@@ -205,7 +188,7 @@
                             
                         </el-tab-pane>
                     </el-tabs>
-                    <div style="margin-top: -1%;">
+                    <div style="margin-top: -1%;width: 90%;">
                       <json-viewer 
                           :value="dataReturn" 
                           :expand-depth="5" 
@@ -227,7 +210,7 @@
                         /> -->
                     </div>
                 </div>
-                <div style="margin-top: 2.5%;margin-left: 1%;padding-bottom: 1%;">
+                <div style="margin-top: 2.5%;margin-left: 1%;padding-bottom: 1%;width: 90%;">
                     <div>响应示例</div><el-tabs type="card" style="margin-top: 1%;">
                         <el-tab-pane label="成功示例">
                              <div style="overflow: auto;height: 30vh">
@@ -243,265 +226,7 @@
                 </div>
             
               </div>
-            </el-tab-pane>
-            <el-tab-pane label="修改" name="second" style="" :disabled="isEdit">
-                <div style="overflow: auto;height: 80vh;">
-                  <div style="display: flex;margin-top: 1%;">
-                    <el-button type="primary" @click="saveEditService" style="margin-left: 80%;z-index: 1000;" :disabled="isEdit">提交</el-button>
-                    <el-button type="danger" @click="delSer" style="margin-left: 1%;z-index: 1000;" :disabled="isEdit">删除</el-button>
-                  </div>
-                    <el-form size="mini" :key="tableKey" style="margin-top: -2%;width: 98%;"  :model="formJi" label-position="right" ref="formRefJi" label-width="120px" :rules="rulesJi">
-                      <el-row :gutter="48">
-                            <el-col :span="10">
-                              <el-form-item label="服务名称:" prop="name" style="">
-                                  <div style="display: flex;width: 100%;justify-content: space-between;">
-                                    <el-input :disabled="isEdit" v-model="formJi.name" style="width: 100%;"/>
-                                  </div>
-                              </el-form-item>
-                            </el-col>
-                            <el-col :span="6">
-                              <el-form-item label="接口类型:" prop="" style="">
-                                <div style="display: flex;width: 100%;justify-content: space-between;">
-                                  <el-select
-                                    v-model="formJi.type"
-                                    :disabled="isEdit"
-                                        style="width: 100%;margin-left: 0%;"
-                                    >
-                                        <el-option
-                                        v-for="item in optionsType"
-                                        :key="item.value"
-                                        :label="item.label"
-                                        :value="item.value"
-                                        />
-                                    </el-select>
-                                  <div style="display: flex;">
-                                    
-                                  </div>
-                                </div>
-                                    
-                                </el-form-item>
-                            </el-col>
-                      </el-row>
-                      <el-row :gutter="48">
-                            <el-col :span="10">
-                              <el-form-item label="接口地址:" prop="url" style=""> 
-                                  <el-input
-                                  v-model="formJi.url"
-                                  :disabled="isEdit"
-                                  style="width: 100%;"
-                                  placeholder=""
-                                  class="input-with-select"
-                                  >
-                                </el-input>
-                              </el-form-item>
-                            </el-col>
-                            <el-col :span="6">
-                                <el-form-item label="请求方式:" prop="" style="">
-                                    <el-select
-                                    v-model="formJi.rqtype"
-                                    :disabled="isEdit"
-                                        style="width: 100%;margin-left: 0%;"
-                                    >
-                                        <el-option
-                                        v-for="item in optionsRqtype"
-                                        :key="item.value"
-                                        :label="item.label"
-                                        :value="item.value"
-                                        />
-                                    </el-select>
-                                </el-form-item>
-                            </el-col>
-                      </el-row>
-                      <el-row :gutter="48">
-                            <el-col :span="10">
-                              <el-form-item label="响应类型:" prop="" style="display: flex; align-items: center;">
-                                <el-radio-group :disabled="isEdit" v-model="formJi.rptype" class="ml-4" style="display: inline-flex; align-items: center;">
-                                  <el-radio label="1" size="large" style="display: inline-flex; align-items: center;">
-                                    <span style="position: relative; top: -1px">JSON</span> <!-- 微调文字位置 -->
-                                  </el-radio>
-                                  <el-radio label="2" size="large" style="display: inline-flex; align-items: center;">
-                                    <span style="position: relative; top: -1px">XML</span>
-                                  </el-radio>
-                                  <el-radio label="3" size="large" style="display: inline-flex; align-items: center;">
-                                    <span style="position: relative; top: -1px">HTML</span>
-                                  </el-radio>
-                                </el-radio-group>
-                              </el-form-item>
-                            </el-col>
-                            <el-col :span="6">
-                                <el-form-item label="服务分类:" prop="cateCode" style="">
-                                    <el-cascader :disabled="isEdit" v-model="formJi.cateCode" :options="cascaderOptions" :props="props1" clearable style="width: 100%;"></el-cascader>
-                                </el-form-item>
-                            </el-col>
-                            <!-- <el-col :span="8">
-                                <el-form-item label="请求方式:" prop="name" style="">
-                                    <el-select
-                                    v-model="formJi.type"
-                                    :disabled="isEdit"
-                                        style="width: 100%;margin-left: 0%;"
-                                    >
-                                        <el-option
-                                        v-for="item in optionsType"
-                                        :key="item.value"
-                                        :label="item.label"
-                                        :value="item.value"
-                                        />
-                                    </el-select>
-                                </el-form-item>
-                            </el-col> -->
-                      </el-row>
-                      <el-row :gutter="48">
-                            <el-col :span="13">
-                              <el-form-item label="服务说明:">
-                                  <el-input :disabled="isEdit" v-model="formJi.intro" style="width: 100%;" :rows="3" resize="none" type="textarea"/>
-                              </el-form-item>
-                            </el-col>
-                      </el-row>
-                        
-                    </el-form>
-                    <div style="margin-top: 2%;">
-                        <div style="display: flex;justify-content: space-between;align-items: center;">
-                          <div>
-                            请求参数
-                          </div>
-                          <div style="display: flex;justify-content: flex-end;margin-right: 2%;">
-                            <el-button  @click="addPa" style="margin-top: 1%;" type="success" size="mini" plain>新增参数</el-button>
-                          </div>
-                        </div>
-                        <div>
-                            <el-table 
-                            style="margin-top: 1%;width: 98%;"
-                            :data="tableDataCan" 
-                            :cell-style="{ textAlign: 'center',padding:'2px 0' }"
-                            :header-cell-style="{ textAlign: 'center'}"
-                            :row-style="{ height: heightAll*0.01+'px',fontSize: '16px',textAlign:'center'  }"
-                            border >
-                                <el-table-column prop="itemName" label="参数字段">
-                                    <template #default="scope">
-                                        <div style="width: 100%;">
-                                            <el-input  placeholder="请填写参数编码" type="primary" class="noBor" v-model="scope.row.paramCode" size="mini" text style="margin-left: 0%;border: transparent;"></el-input>
-                                        </div>
-                                    </template>
-                                </el-table-column>
-                                <el-table-column prop="itemName" label="参数名称">
-                                    <template #default="scope">
-                                        <div style="width: 100%;">
-                                            <el-input placeholder="请填写参数名称" type="primary" class="noBor" v-model="scope.row.itemName" size="mini" text style="margin-left: 0%;"></el-input>
-                                        </div>
-                                    </template>
-                                </el-table-column>
-                                <el-table-column prop="itemName" label="参数类型" width="200">
-                                    <template #default="scope">
-                                        <div style="width: 100%;">
-                                            <el-select
-                                            v-model="scope.row.paramType"
-                                            class="noBorSel"
-                                            placeholder=""
-                                            style="width: 100%;margin-left: 0%;"
-                                            >
-                                                <el-option
-                                                v-for="item in optionsCan"
-                                                :key="item.value"
-                                                :label="item.label"
-                                                :value="item.value"
-                                                />
-                                    </el-select>
-                                        </div>
-                                    </template>
-                                </el-table-column>
-                                <el-table-column prop="itemName" label="参数说明" >
-                                    <template #default="scope">
-                                        <div style="width: 100%;">
-                                            <el-input type="primary" class="noBor" v-model="scope.row.paramNote" size="mini" text style="margin-left: 0%;"></el-input>
-                                        </div>
-                                    </template>
-                                </el-table-column>
-                                <el-table-column prop="address" label="操作" width="100">
-                                    <template #default="scope">
-                                        <div style="width: 100%;">
-                                            <el-button type="danger" @click="delCan(scope.$index)" size="mini" text style="margin-left: 0%;">删除</el-button>
-                                        </div>
-                                    </template>
-                                </el-table-column>
-                            </el-table>
-                            
-                        </div>
-                    </div>
-                    <div style="margin-top: 2%;">
-                        <!-- <div>返回响应</div> -->
-                        <div style="color: #909399;margin-left: 7%;margin-top:1%;">此处填写本服务接口响应信息描述</div>
-                        <el-tabs type="card" style="margin-top: -1.5%;width: 98%;">
-                            <el-tab-pane label="响应内容">
-                                <div style="display: flex; flex-direction: column;">
-                                    <!-- <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>
-                                        <template #default="{ node, data }">
-                                            <span style="display: flex;justify-content: space-between;width: 100%;align-items: center;">
-                                                <span><el-input v-model="node.label" size="mini"/></span>
-                                                <span style="display: flex;align-items: center;">
-                                                    <el-tooltip
-                                                        class="box-item"
-                                                        effect="light"
-                                                        content="是否必填"
-                                                        placement="top-start"
-                                                    >
-                                                    <el-checkbox v-model="checked1" label="" size="large" />
-                                                    </el-tooltip>
-                                                    <el-select
-                                                        v-model="formJi.type"
-                                                        :disabled="isEdit"
-                                                        style="width: 100%;margin-left: -1%;"
-                                                    >
-                                                        <el-option
-                                                        v-for="item in optionsType"
-                                                        :key="item.value"
-                                                        :label="item.label"
-                                                        :value="item.value"
-                                                        />
-                                                    </el-select>
-                                                    <el-tooltip
-                                                        class="box-item"
-                                                        effect="light"
-                                                        content="是否允许null"
-                                                        placement="top-start"
-                                                    >
-                                                    <el-checkbox v-model="checked1" label="" size="large" />
-                                                    </el-tooltip>
-                                                </span>
-                                            </span>
-                                        </template>
-                                    </el-tree> -->
-                                   </div>
-                            </el-tab-pane>
-                        </el-tabs>
-                        <div style="overflow: auto;height: 20vh;margin-top: -1%;">
-                          <!-- <JsonEditorVue
-                            v-model="dataJsonXiang"
-                            style="height:98%;width: 98%;"
-                            :mode="'code'"
-                            :showBtns="false"
-                            :options="{
-                              navigationBar: false, // 隐藏顶部导航栏
-                              statusBar: false,     // 隐藏底部状态栏
-                              mode: 'code',          // 仅保留代码编辑模式
-                              mainMenuBar: false     // 隐藏主菜单栏
-                            }"
-                            lang="zh"
-                          /> -->
-                          <el-input placeholder="请输入示例" :rows="8" type="textarea" v-model="dataJsonXiang" size="mini" text style="margin-top: 0%;width: 98%;" ></el-input>
-                        </div>
-                    </div>
-                    <div style="margin-top: 2.5%;margin-left: 0%;padding-bottom: 1%;">
-                    
-                    <el-tabs type="card" style="margin-top: -1.5%;width: 98%;">
-                        <el-tab-pane label="使用说明">
-                             
-                        </el-tab-pane>
-                    </el-tabs>
-                    <el-input placeholder="请输入示例" :rows="8" type="textarea" v-model="example" size="mini" text style="margin-top: -1%;width: 98%;" ></el-input>
-                </div>
-                </div>
-            </el-tab-pane>
-        </el-tabs>
+            
         <el-dialog @close="clearAdd" v-model="dialogVisible" title="新增节点" width="70%" destroy-on-close :key="tableKey">
           <div style="overflow: auto;height: 80vh;">
                     <el-form size="mini" :key="tableKey" style="margin-top: 1%;width: 98%;"  :model="formAdd" label-position="right" ref="formRefAdd" label-width="120px" :rules="rulesAdd">
@@ -714,7 +439,7 @@
                             </el-tab-pane>
                         </el-tabs>
                         <div style="overflow: auto;height: 20vh;margin-top: -1%;">
-                          <el-input placeholder="请输入示例" :rows="8" type="textarea" v-model="JsonAdd" size="mini" text style="margin-top: 0%;width: 98%;" ></el-input>
+                          <el-input placeholder="请输入示例" :rows="8" type="textarea" v-model="JsonAdd" size="mini" text style="margin-top: 0%;width: 98%;height: 99%;" ></el-input>
                         </div>
                     </div>
                     <div style="margin-top: 2.5%;margin-left: 0%;padding-bottom: 1%;">
@@ -773,6 +498,8 @@ import JsonViewer from 'vue-json-viewer'
 import 'vue-json-viewer/style.css' 
 import  JsonEditorVue from 'json-editor-vue3'
 import { cloneDeep } from 'lodash'
+import { useClipboard } from "@vueuse/core";
+
 const { proxy } = getCurrentInstance();
 const JsonAdd= ref(JSON.stringify({ data: "初始值1" }))
 const exampleAdd = ref('')
@@ -969,6 +696,19 @@ const filterNode = (value, data) => {
   if (!value) return true; // 空搜索时显示所有节点
   return data.label.includes(value); // 检查节点标签是否包含关键字
 };
+
+const copied = ref(false);
+
+async function copyUrl(){
+  try {
+    await navigator.clipboard.writeText(detail.value.url);
+    copied.value = true;
+    console.log(detail.url.value,copied.value)
+    setTimeout(() => (copied.value = false), 2000); // 2秒后提示消失
+  } catch (err) {
+    console.error("复制失败", err);
+  }
+};
 function filterModelNodes(nodes) {
   if (!Array.isArray(nodes)) return [];
   
@@ -1002,13 +742,16 @@ function clearAdd(){
     intro:'',
     mdid:''
   }
-  tableDataCanAdd.value = {
-    itemName:'',
-    itemCode:'',
-    paramType:'',
-    paramNote:''
-  }
+  tableDataCanAdd.value = [
+    {
+      itemName:'',
+      itemCode:'',
+      paramType:'',
+      paramNote:''
+    }
+  ]
   JsonAdd.value = ''
+  dialogVisible.value = false
   exampleAdd.value = ''
 }
 function extractModelNodesDFSIterative(root) {
@@ -1127,7 +870,7 @@ async function addSer(){
   await formRefAdd.value.validate((valid1) => {
     valid = valid1
   });
-  console.log(valid)
+  console.log(valid) 
   if(valid){
     var par = formAdd.value
     par.example = exampleAdd.value
@@ -1162,13 +905,16 @@ async function handleNodeClick(node,data,event){
   isEdit.value = false
   parId.value = data.data
   await getSerDe(data.data.id).then(res=>{
-    detail.value = res.data.ptService
-    tableDataCan.value = res.data.list
-    dataReturn.value = res.data.returnList
-    console.log(tableDataCan.value)
-    dataJsonXiang.value = res.data.ptService.rpcontent
-    formJi.value = res.data.ptService
-    example.value = res.data.ptService.example
+    if(res.data.ptService){
+      detail.value = res.data.ptService
+      tableDataCan.value = res.data.list
+      dataReturn.value = res.data.returnList
+      console.log(tableDataCan.value)
+      dataJsonXiang.value = res.data.ptService.rpcontent
+      formJi.value = res.data.ptService
+      example.value = res.data.ptService.example
+    }
+    
   })
   detail.value.nodeType = data.data.nodeType
   

Some files were not shown because too many files changed in this diff