graphMap.js 22 KB

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