graphMap.js 20 KB

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