graphMap.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678
  1. const echarts = require("echarts");
  2. const { post, api } = require('./api.js');
  3. const iconUp = require('./../resources/images/iconUp.png');
  4. const iconDown = require('./../resources/images/iconDown.png');
  5. const clientHei = $(window).height()
  6. const contentHei = clientHei - 80
  7. //关系图
  8. function getGraph(val, type){
  9. return post(api.getGraph,{
  10. "inputStr": val,
  11. "labelName": type
  12. }).then(res=>{
  13. if(res.data.code == 0) {
  14. // select_type = select_type_noSearch
  15. $('#searchInp').val(val)
  16. drawGraph(res.data.data)
  17. window.graphTxt = val
  18. window.refreshTree = true
  19. if(type != select_type){
  20. select_type = type
  21. let renderTabInfo = getTab(type)
  22. renderTab(renderTabInfo)
  23. }
  24. }else{
  25. let nodeStr
  26. nodeStr = '<li class="ellipsis">暂无符合数据</li>'
  27. $(".tabNameList").html(nodeStr)
  28. $(".tabNameList").show()
  29. window.refreshTree = false
  30. }
  31. })
  32. }
  33. function drawGraph(data,resultShowId) {
  34. // var colors = [
  35. // '#FB95AF','#788083','#B2CCCF','#68BDF6','#FFD86E','#6DCE9F','#9BB2F0','#DBB7AC'
  36. // ]
  37. var myChart = echarts.init(document.getElementById('main'));
  38. var categories = data['categories'];
  39. var legends = categories.slice(2, categories.length);
  40. var showLegendNum = 0;
  41. let sum = 0
  42. for(let i = 0; i < legends.length; i++){
  43. sum += 2+legends[i].name.length+1
  44. if(sum <= 60){
  45. showLegendNum ++
  46. }
  47. }
  48. var option = {
  49. title: {
  50. text: '医学知识图谱',
  51. top: '10',
  52. left: '10'
  53. },
  54. // color:colors,
  55. tooltip: {
  56. formatter: function (x) {
  57. return x.data.label;
  58. }
  59. },
  60. legend: [{
  61. type: 'scroll',
  62. bottom: 0,
  63. // left: 0,
  64. itemWidth: 8,
  65. itemHeight: 8,
  66. itemGap: 20,
  67. icon: 'circle',
  68. width: 766,
  69. verticalAlign:'top',
  70. borderColor:'#E6E6E6',
  71. borderTopWidth:1,
  72. padding:[20, 1000, 0, 1000],
  73. backgroundColor: "#FFFFFF",
  74. // orient: 'vertical',
  75. data: legends.slice(0,showLegendNum).map(function (a) {
  76. return a.name;
  77. }),
  78. }],
  79. series: [
  80. {
  81. type: 'graph',
  82. layout: 'force',
  83. cursor:'pointer',
  84. categories: categories,
  85. symbolSize: 80,
  86. roam: 'move',
  87. edgeSymbol: ['circle', 'arrow'],
  88. edgeSymbolSize: [1, 5],
  89. edgeLabel: {
  90. // cursor:'pointer',
  91. normal: {
  92. textStyle: {
  93. fontSize: 20
  94. }
  95. }
  96. },
  97. force: {
  98. repulsion: 500,
  99. gravity: 0.8,
  100. friction :0.2, //动画速度
  101. edgeLength: [4, 7],
  102. layoutAnimation : true
  103. },
  104. draggable: false,
  105. animation: true,
  106. hoverAnimation:false,
  107. animationDuration:5000,
  108. focusNodeAdjacency: true,
  109. itemStyle: {
  110. normal: {
  111. width: 2,
  112. // color: 'target',
  113. // cursor:'pointer',
  114. curveness: 0,
  115. opacity: 1
  116. }
  117. },
  118. lineStyle: {
  119. normal: {
  120. width: 2,
  121. cursor:'default',
  122. color: 'target'
  123. }
  124. },
  125. edgeLabel: {
  126. normal: {
  127. show: true,
  128. formatter: function (x) {
  129. return x.data.value; //横线关系
  130. }
  131. }
  132. },
  133. label: {
  134. normal: {
  135. show: true,
  136. textStyle: {
  137. cursor:'pointer',
  138. },
  139. color:'#1E1E1E', //label字体颜色
  140. formatter: function (x) {
  141. var tmp = x.data.label;
  142. if(tmp.length >= 12){
  143. tmp = tmp.substring(0,12);
  144. tmp = tmp + "...";
  145. }
  146. return tmp;
  147. }
  148. }
  149. },
  150. data: data.node,
  151. links: data.links
  152. }
  153. ]
  154. };
  155. $(window).resize(function(){
  156. myChart.resize();
  157. })
  158. myChart.on('click',dataClick);
  159. myChart.setOption(option);
  160. if(legends.length > showLegendNum){
  161. $('.legendSlideUp').toggleClass('legendSlideUp')
  162. $('.legendIcon').css('display',"block")
  163. }else{
  164. $('.legendSlideUp').toggleClass('legendSlideUp')
  165. $('.legendIcon').css('display',"none")
  166. }
  167. $('.legendIconImg').off("click").on('click',function(e){
  168. e.stopPropagation()
  169. $('.legendIconImg').toggleClass('legendSlideUp')
  170. if(option.legend[0].type=='scroll'){
  171. option.legend[0].type='plain'
  172. option.legend[0].data = legends
  173. }else{
  174. option.legend[0].type='scroll'
  175. option.legend[0].data = legends.slice(0,showLegendNum)
  176. }
  177. myChart.setOption(option);
  178. })
  179. }
  180. function dataClick(param){
  181. var data = param.data;
  182. const clientHei = $(window).height()
  183. const contentHei = clientHei - 80
  184. // console.log('data', data,select_type)
  185. // var nodes = option.series[0].nodes;
  186. if(data.category == 0){
  187. return
  188. }else{
  189. if(data.symbol != "circle"){
  190. return
  191. }else{
  192. if(data.type == select_type){
  193. $('#searchInp').val(data.label)
  194. updateTree(data.label)
  195. getGraph(data.label,select_type);
  196. }else {
  197. let renderTabInfo = getTab(data.type)
  198. renderTab(renderTabInfo)
  199. if(data.type == "疾病"){
  200. $(".radioList").show()
  201. $('.iconRadio').attr('src','/images/radioUnSelect.png')
  202. $('.ICD10 img').attr('src','/images/radioSelect.png')
  203. setTabBottomHei(1)
  204. }else{
  205. $(".radioList").hide()
  206. setTabBottomHei(2)
  207. }
  208. select_type_noSearch = data.type
  209. select_type = data.type
  210. setSelectName(select_type)
  211. $('#searchInp').val(data.label)
  212. if(data.type == "疾病"){
  213. getTree(1,1,data.label);
  214. getGraph(data.label,select_type);
  215. }else if(data.type == "药品通用名"){
  216. getTree(0,2,data.label);
  217. getGraph(data.label,select_type);
  218. }else if(data.type == "症状"){
  219. getTree(0,3,data.label);
  220. getGraph(data.label,select_type);
  221. }else if(data.type == "手术和操作"){
  222. getTree(0,4,data.label);
  223. getGraph(data.label,select_type);
  224. }else if(data.type == "实验室检查"){
  225. getTree(0,5,data.label);
  226. getGraph(data.label,select_type);
  227. }else if(data.type == "辅助检查"){
  228. getTree(0,6,data.label);
  229. getGraph(data.label,select_type);
  230. }
  231. }
  232. }
  233. }
  234. }
  235. function getTree(subType, type,showNodeName){
  236. post(api.getTree,
  237. {
  238. "subType": subType, //科室subType: 2, 疾病type:1
  239. "type": type
  240. }
  241. ).then(res=>{
  242. if(res.data.code == 0) {
  243. const data = res.data.data
  244. drawTree(data,showNodeName)
  245. }
  246. })
  247. }
  248. function drawTree(data, showNodeName){
  249. /**
  250. 属性说明 id 当前节点的唯一ID
  251. pId [必须大写] 代表当前节点的父节点id
  252. name:节点名称
  253. open:是否展开当前节点,默认为false
  254. isParent:true 标记当前节点是否为父节点 默认为如果当前节点下有子节点 则为true 否则为false
  255. icon:设置节点的图标地址
  256. iconOpen:设置节点展开时的图标地址 此节点必须是父节点 isParent:true
  257. iconClose:设置节点收起的的图标地地址 此节点必须是父节点 isParent:true
  258. url:点击节点打开的链接地址 如果想使用onClick:zTreeOnClick事件,就不要加url属性 或者改名字 href
  259. target:设置打开链接的方式 [在新窗口打开(_blank),要本窗口打开(_self)]
  260. **/
  261. var setting = {
  262. //数据格式的设置
  263. data:{
  264. simpleData: {
  265. enable: true, //使用简单的JSON格式
  266. idKey: "id",
  267. pIdKey: "pId",
  268. rootPId: ""
  269. },
  270. },
  271. //树的显示设置
  272. view:{
  273. showLine:true, //设置是否显示连线 默认为true
  274. showTitle: true,//设置是否显示鼠标悬浮时显示title的效果
  275. dblClickExpand: true,//设置是否支持双击展开树节点
  276. fontCss : {color:"#333"},//设置节点样式
  277. expandSpeed: "normal",//设置展开的速度 fast normal slow
  278. nameIsHTML: true,//名字是否是HTML
  279. selectedMulti: true,
  280. },
  281. //设置事件回调
  282. callback:{
  283. onClick: function (treeId, treeNode) {
  284. const selectPId = $('.curSelectedNode').attr('id')
  285. if(selectPId){
  286. const selectId = selectPId.substring(0,selectPId.length-1) + 'ico'
  287. $('#'+selectId).append('<img class="iconSelect" src="./images/iconSelect.png">')
  288. }
  289. },
  290. beforeClick: function (treeId, treeNode) {
  291. var zTree = $.fn.zTree.getZTreeObj("tree");
  292. if (treeNode.isParent) {
  293. zTree.expandNode(treeNode);
  294. return false;
  295. } else {
  296. const treeNodeName = treeNode.name
  297. let index = treeNodeName.indexOf(' ')
  298. const name = treeNodeName.substring(index+1)
  299. if(select_type != select_type_noSearch){
  300. select_type_noSearch = select_type
  301. setSelectName(select_type)
  302. }
  303. getGraph(name,select_type)
  304. const selectPId = $('.curSelectedNode').attr('id')
  305. if(selectPId){
  306. const selectId = selectPId.substring(0,selectPId.length-1) + 'ico'
  307. $('#'+selectId + ' .iconSelect').remove()
  308. }
  309. // showKnowledgeGraph(treeNode.name, 'graph', 0);
  310. return true;
  311. }
  312. }
  313. }
  314. };
  315. var zNodes = data.nodes;
  316. // var zNodes = zTreeData.nodes;
  317. $.fn.zTree.init($("#tree"), setting, zNodes);
  318. if(showNodeName) {
  319. updateTree(showNodeName)
  320. }
  321. }
  322. function getNode(val, type){
  323. post(api.getNode,
  324. {
  325. "inputStr": val,
  326. "labelName": type
  327. }
  328. ).then(res=>{
  329. if(res.data.code == 0) {
  330. const data = res.data.data
  331. let nodeStr =''
  332. if(data.length > 0){
  333. for(let i = 0; i < data.length; i++){
  334. nodeStr +=`<li class="ellipsis nodeItem" title=${data[i].name}>${data[i].name}</li>`
  335. }
  336. }else{
  337. nodeStr = '<li class="ellipsis">暂无符合数据</li>'
  338. }
  339. $(".tabNameList").html(nodeStr)
  340. $(".tabNameList").show()
  341. $(".tabNameList li").click(function(){
  342. const txt = $(this).text()
  343. if(txt !="暂无符合数据"){
  344. $('#searchInp').val(txt)
  345. }
  346. const clientHei = $(window).height()
  347. const contentHei = clientHei - 80
  348. $(".tabNameList").hide()
  349. getGraph(txt,select_type_noSearch).then(()=>{
  350. if(!window.refreshTree){
  351. return
  352. }
  353. select_type = select_type_noSearch
  354. if(select_type == '疾病'){
  355. // $('#searchInp').val("高血压3级")
  356. getTree(1,1,txt);
  357. }else if(select_type == '药品通用名'){
  358. getTree(0,2,txt);
  359. }else if(select_type == '症状'){
  360. getTree(0,3,txt);
  361. }else if(select_type == '手术和操作'){
  362. getTree(0,4,txt);
  363. }else if(select_type == '实验室检查'){
  364. getTree(0,5,txt);
  365. }else if(select_type == '辅助检查'){
  366. getTree(0,6,txt);
  367. }
  368. if(select_type == '疾病'){
  369. $('.iconRadio').attr('src','/images/radioUnSelect.png')
  370. $('.ICD10 img').attr('src','/images/radioSelect.png')
  371. $(".radioList").show()
  372. setTabBottomHei(1)
  373. }else{
  374. $(".radioList").hide()
  375. setTabBottomHei(2)
  376. }
  377. let renderTabInfo = getTab(select_type)
  378. renderTab(renderTabInfo)
  379. })
  380. })
  381. }
  382. })
  383. }
  384. function updateTree(keyWord, txt) {
  385. var t = $("#tree");
  386. // if(zNodes&& zNodes.length > 0 && zNodes[0]['name'].indexOf(txt) != -1){
  387. // $.fn.zTree.init(t, setting, zNodes);
  388. // var zTree = $.fn.zTree.getZTreeObj("tree");
  389. // zTree.selectNode(zTree.getNodeByParam("name", keyWord));
  390. // }else {
  391. var tree_select = document.getElementsByClassName("tree_selected");
  392. for(i = 0; i < tree_select.length; i++){
  393. tree_select[i].className = "tree_button";
  394. }
  395. var tree_button = document.getElementsByClassName("tree_button");
  396. for(i = 0; i < tree_button.length; i++){
  397. if(tree_button[i].text == txt){
  398. tree_button[i].className = "tree_selected";
  399. }
  400. }
  401. if(txt != "疾病"){
  402. $("#radio").hide();
  403. }else {
  404. $("#radio").show();
  405. }
  406. selectedNode = keyWord;
  407. var data = {"name":'tree'};
  408. var zTree = $.fn.zTree.getZTreeObj("tree");
  409. zTree.selectNode(zTree.getNodeByParam("name", keyWord));
  410. const selectPId = $('.curSelectedNode').attr('id')
  411. if(selectPId){
  412. const selectId = selectPId.substring(0,selectPId.length-1) + 'ico'
  413. $('.iconSelect').remove()
  414. $('#'+selectId).append('<img class="iconSelect" src="./images/iconSelect.png">')
  415. }
  416. }
  417. function isEmpty(obj){
  418. if(typeof obj == "undefined" || obj == null || obj == ""){
  419. return true;
  420. }else{
  421. return false;
  422. }
  423. }
  424. function getKeyEvent(evt) {
  425. var evt = (evt) ? evt : ((window.event) ? window.event : "");
  426. var key = evt.keyCode?evt.keyCode:evt.which;
  427. if(key==13){
  428. keyDown = true;
  429. queryGraph();
  430. evt.cancleBubble = true;
  431. evt.returnValue = false;
  432. return false;
  433. }else{
  434. return false;
  435. }
  436. }
  437. function getTab(tabName){
  438. let tabList = ["疾病","药品通用名","症状","手术和操作","实验室检查","辅助检查"]
  439. let tabListCopy = tabList.slice()
  440. const index = tabList.findIndex(item => item == tabName)
  441. if(index <= 3){
  442. return {
  443. activeIndex: index,
  444. showTabList:tabListCopy.slice(0,4),
  445. hideTabList:tabListCopy.slice(4)
  446. }
  447. }else{
  448. tabListCopy.splice(index,1)
  449. let hideTabList = tabListCopy.slice(3)
  450. return {
  451. activeIndex: 3,
  452. showTabList:tabListCopy.slice(0,3).concat(tabName),
  453. hideTabList:hideTabList
  454. }
  455. }
  456. }
  457. function renderTab(data){
  458. const showList = data.showTabList
  459. const hideList = data.hideTabList
  460. const activeIndex = data.activeIndex
  461. let showtabStr = ``
  462. let hidetabStr = ``
  463. for(let i = 0; i < showList.length; i++){
  464. showtabStr +=` <span class="tab ${i === activeIndex ? 'activeTab':''}" data-id="${showList[i]}">${showList[i] =="药品通用名" ?"药品":showList[i]}</span>`
  465. if(i === activeIndex){
  466. if(showList[i] =="药品通用名"){
  467. $("#searchInp").attr("placeholder",`请输入药品名称`)
  468. }else{
  469. $("#searchInp").attr("placeholder",`请输入${showList[i]}名称`)
  470. }
  471. }
  472. }
  473. for(let i = 0; i < hideList.length; i++){
  474. hidetabStr +=`<span class="tab " data-id="${hideList[i]}">${hideList[i]}</span>`
  475. }
  476. hidetabStr += `<div class="toggleTab">
  477. <span class="toggleTabTxt">收起</span>
  478. <img class="toggleArrow" src="./images/iconUp.png" alt="">
  479. </div>`
  480. // console.log('showtabStr',showtabStr)
  481. $('.showTabList').html(showtabStr)
  482. $('.hideTabList').html(hidetabStr)
  483. bindTabClick()
  484. ToggleTab()
  485. }
  486. ToggleTab()
  487. function ToggleTab(){
  488. $(".toggleTab").off("click").click(function(e){
  489. e.stopPropagation()
  490. hideSlide("hideTabList")
  491. const hideTabDis = $(".hideTabList").css("display")
  492. if(hideTabDis == "none"){
  493. showHideTab()
  494. }else{
  495. hideHideTab()
  496. }
  497. })
  498. }
  499. function showHideTab(){
  500. $(".hideTabList").show()
  501. $(".tabList").addClass("tabListShow")
  502. $(".toggleTab").css("display","none")
  503. $(".hideTabList .toggleTab").css("display","inline-block")
  504. // $(".toggleTabTxt").html("收起")
  505. // $(".toggleArrow").attr("src",iconUp)
  506. }
  507. function hideHideTab(e){
  508. $(".hideTabList").hide()
  509. // $(".toggleTabTxt").html("展开")
  510. // $(".toggleArrow").attr("src",iconDown)
  511. $(".toggleTab").css("display","block")
  512. $(".tabList").removeClass("tabListShow")
  513. }
  514. bindTabClick()
  515. //切换tab
  516. function bindTabClick(){
  517. $('.tabList .tab').click(function(){
  518. const id = $(this).attr('data-id')
  519. $(this).addClass("activeTab").siblings().removeClass('activeTab')
  520. let renderInfo = getTab(id)
  521. renderTab(renderInfo)
  522. if(id != select_type){
  523. if(id != "疾病"){
  524. $(".radioList").hide()
  525. setTabBottomHei(2)
  526. }else{
  527. $(".radioList").show()
  528. setTabBottomHei(1)
  529. }
  530. select_type_noSearch = id
  531. select_type = id
  532. setSelectName(select_type)
  533. if(id == "疾病"){
  534. $('#searchInp').val("急性胰腺炎")
  535. $('.iconRadio').attr('src','/images/radioUnSelect.png')
  536. $('.ICD10 img').attr('src','/images/radioSelect.png')
  537. getTree(1,1,"急性胰腺炎");
  538. getGraph("急性胰腺炎",select_type);
  539. }else if(id=="药品通用名"){
  540. $('#searchInp').val("地高辛(XC01AAD072A001010100372)")
  541. getTree(0,2,"地高辛(XC01AAD072A001010100372)");
  542. getGraph("地高辛(XC01AAD072A001010100372)",select_type);
  543. }else if(id == "症状"){
  544. $('#searchInp').val("背痛")
  545. getTree(0,3,"背痛");
  546. getGraph("背痛",select_type);
  547. }else if(id == "手术和操作"){
  548. $('#searchInp').val("动脉缝合术")
  549. getTree(0,4,"动脉缝合术");
  550. getGraph("动脉缝合术",select_type);
  551. }else if(id == "实验室检查"){
  552. $('#searchInp').val("白细胞计数(WBC)")
  553. getTree(0,5,"白细胞计数(WBC)");
  554. getGraph("白细胞计数(WBC)",select_type);
  555. }else if(id == "辅助检查"){
  556. $('#searchInp').val("肝彩超")
  557. getTree(0,6,"肝彩超");
  558. getGraph("肝彩超",select_type);
  559. }
  560. // getTree(1,1,""); //切换tab重新画菜单树
  561. }
  562. hideHideTab()
  563. })
  564. }
  565. function setTabBottomHei(type){
  566. const clientHei = $(window).height()
  567. const contentHei = clientHei - 80
  568. if(type==1){
  569. $(".tabBottom").css({
  570. 'margin': '0px 0px 0px 0px'
  571. })
  572. $(".tabBottom").css("height",contentHei-80-43-10+'px')
  573. $(".ztree").css("height",contentHei-80-43-60-20-24+'px')
  574. }else if(type == 2){
  575. $(".tabBottom").css("height",contentHei-80-43-10-20+'px')
  576. $(".tabBottom").css({
  577. 'margin': '20px 0px 0px 0px'
  578. })
  579. $(".ztree").css("height",contentHei-80-43-20-20-20+'px')
  580. }
  581. }
  582. function setSelectName(name){
  583. if(name=="药品通用名"){
  584. $('.selectedName').html("药品")
  585. $('.selectedName').attr("title","药品")
  586. $("#searchInp").attr("placeholder",`请输入药品名称`)
  587. }else{
  588. $('.selectedName').attr('title', name)
  589. $("#searchInp").attr("placeholder",`请输入${name}名称`)
  590. if(name.length > 4){
  591. $('.selectedName').html(name.slice(0,4)+'...')
  592. }else{
  593. $('.selectedName').html(name)
  594. }
  595. }
  596. }
  597. function hideSlide(expectClass){
  598. let hideSlideList = ['selectList', 'tabNameList','tabNameListNoSearch','hideTabList']
  599. let index = hideSlideList.findIndex(item => item == expectClass)
  600. for(let i = 0; i < hideSlideList.length; i++){
  601. if(i != index){
  602. if(hideSlideList[i] == "selectList"){
  603. $('.'+hideSlideList[i]).hide()
  604. $('.iconSlide').attr('src','./images/iconSlideDown.png')
  605. }else if(hideSlideList[i] == "hideTabList"){
  606. hideHideTab()
  607. }else{
  608. $('.'+hideSlideList[i]).hide()
  609. }
  610. }
  611. }
  612. }
  613. module.exports ={
  614. drawGraph,
  615. updateTree,
  616. getGraph,
  617. getTree,
  618. getNode,
  619. getTab,
  620. renderTab,
  621. setTabBottomHei,
  622. setSelectName,
  623. hideHideTab,
  624. hideSlide
  625. }