index.vue 49 KB

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