home.js 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111
  1. require("../css/home.less")
  2. require("./../css/common.less");
  3. const { post, api, getUrlArgObject } = require('./api.js');
  4. const Vue = require("vue/dist/vue.esm.js").default;
  5. const ElementUI = require("../public/elementUI/2.7.2/index");
  6. console.log(ElementUI)
  7. const $ = require('jquery')
  8. const dayjs = require('dayjs')
  9. // 引入dayjs的中文
  10. require('dayjs/locale/zh-cn')
  11. const echarts = require("echarts");
  12. Vue.use(ElementUI)
  13. let myChart = null
  14. let timer = null //计时器标志
  15. const vm = new Vue({
  16. el: "#app",
  17. name: "home",
  18. data() {
  19. return {
  20. username: "管理员",
  21. simpleUpdataPage: false,
  22. mergeEntity: { //实体合并的数据
  23. "firstId": -1,
  24. "firstLabel": "",
  25. "firstName": "",
  26. "newLabel": "",
  27. "newName": "",
  28. "secondId": -1,
  29. "secondLabel": "",
  30. "secondName": ""
  31. },
  32. dialogVisible: false,
  33. dialogData: { title: "提示", opType: "", showFooter: true, width: "" },
  34. modifyProperty: { //右键修改属性
  35. "label": "",
  36. "newPropertyName": "",
  37. "newPropertyValue": "",
  38. "nodeId": -1,
  39. "oldPropertyName": "",
  40. "oldPropertyValue": "",
  41. },
  42. modifyPropertyDropdown: { //下拉框修改属性
  43. name: "",
  44. label: "疾病",
  45. properties: []
  46. },
  47. deleteProperty: {//右键删除属性
  48. "label": "",
  49. "nodeId": -1,
  50. "name": "",
  51. "propertyName": ""
  52. },
  53. addRelationship: {//右键新增关系
  54. "endId": null,
  55. "endLabel": "疾病",
  56. "endName": "",
  57. "property": {},
  58. "relationshipType": "",
  59. "startId": null,
  60. "startLabel": "",
  61. "startName": ""
  62. },
  63. modifyEntityName: { // 修改关系实体名称-右键 的值
  64. "oldName": "",
  65. "name": "",
  66. "nodeId": -1,
  67. "label": "",
  68. },
  69. deleteEntity: { name: "", nodeId: "" },//右键删除实体
  70. deleteRelationship: {
  71. "endId": null,
  72. "endLabel": "",
  73. "endName": "",
  74. "property": {},
  75. "relationshipType": "",
  76. "startId": null,
  77. "startLabel": "",
  78. "startName": "",
  79. },
  80. entityLink: { //实体链接数据
  81. nodes: [],
  82. links: []
  83. },
  84. modifyRelationship: { oldVal: "", newVal: "" },//右键修改关系名称
  85. tableData: [
  86. { "label": "疾病", "name": "" }
  87. ],
  88. options: [
  89. { "label": "疾病", "value": "疾病" },
  90. { "label": "药品", "value": "药品" },
  91. { "label": "症状", "value": "症状" },
  92. // { "label": "手术和操作", "value": "手术和操作" },
  93. { "label": "实验室检查", "value": "实验室检查" },
  94. { "label": "辅助检查", "value": "辅助检查" },
  95. ],
  96. addPropertyDropdown: {
  97. "label": "疾病",
  98. "nodeId": null,
  99. "name": "",
  100. "property": [{ key: "", value: "" }]
  101. },
  102. addPropertyDropdownOptions: [],
  103. addProperty: { //右键属性新增的数据
  104. "label": "",
  105. "nodeId": -1,
  106. "name": "",
  107. "property": [{ key: "", value: "" }]
  108. },
  109. addRelationshipDropdown: [{ //下拉框添加关系
  110. "endId": null,
  111. "endName": "",
  112. "endLabel": "疾病",
  113. "property": {},
  114. "relationshipType": "",
  115. "startId": null,
  116. "startName": "",
  117. "startLabel": "疾病"
  118. }],
  119. modifyRelationshipNameDropdown: [],//下拉框的修改关系名称
  120. searchRelationshipName: "",
  121. selectedName: "",
  122. searchInp: "",
  123. nodeTable: [],
  124. nowDate: "", //当前的日期时间
  125. isCollapse: false,
  126. editableTabsValue: 'knowledgeGraph',
  127. editableTabs: [
  128. {
  129. title: '知识图谱查询',
  130. name: 'knowledgeGraph',
  131. content: './knowledgeGraph.html'
  132. }
  133. ],
  134. currentPage: {
  135. id: "knowledgeGraph",
  136. url: "./knowledgeGraph.html",
  137. title: "知识图谱查询",
  138. children: null
  139. },
  140. menuData: [
  141. {
  142. id: "1",
  143. url: "",
  144. title: "知识图谱查询",
  145. label: "/images/layer8@2x.png",
  146. children: [
  147. {
  148. id: "knowledgeGraph",
  149. url: "./knowledgeGraph.html",
  150. title: "知识图谱查询",
  151. children: null
  152. },
  153. {
  154. id: "selfKnowledgeGraph",
  155. // url: "./knowledgeGraph.html?self=true&input=头痛&label=症状",
  156. url: "./selfKnowledgeGraph.html",
  157. title: '自构建图谱查询',
  158. children: null
  159. },
  160. ]
  161. },
  162. {
  163. id: "2",
  164. url: "",
  165. title: "图谱知识管理",
  166. label: "./images/layer9@2x.png",
  167. children: [
  168. {
  169. id: "knowledgeUpdate",
  170. url: "./knowledgeUpdate.html",
  171. title: "知识更新",
  172. children: null
  173. },
  174. {
  175. id: "selfKnowledgeUpdate",
  176. url: "",
  177. title: '自构建图谱更新',
  178. children: null
  179. },
  180. ]
  181. },
  182. // {
  183. // id: "3",
  184. // url: "",
  185. // title: "系统管理",
  186. // label: "./images/layer10@2x.png",
  187. // children: [
  188. // {
  189. // id: "userManage",
  190. // url: "",
  191. // title: "用户管理",
  192. // children: null
  193. // },
  194. // {
  195. // id: "permissionManage",
  196. // url: "",
  197. // title: "权限管理",
  198. // children: null
  199. // }
  200. // ]
  201. // },
  202. {
  203. id: "4",
  204. url: "",
  205. title: "统计分析",
  206. label: "./images/layer11@2x.png",
  207. children: [
  208. {
  209. id: "graphDataStatistics",
  210. url: "./graphDataStatistics.html",
  211. title: "图谱数据统计",
  212. children: null
  213. },
  214. {
  215. id: "operationLog",
  216. url: "",
  217. title: "操作日志",
  218. children: null
  219. },
  220. ]
  221. },
  222. ]
  223. }
  224. },
  225. methods: {
  226. menuSelect: function (item) {
  227. this.currentPage = { ...item }
  228. const { id, title, url } = item
  229. this.editableTabsValue = id
  230. const isExist = this.editableTabs.some((el) => {
  231. if (el.name == id) return true;
  232. })
  233. if (!isExist) {
  234. this.editableTabs.push({
  235. name: id,
  236. title: title,
  237. content: url,
  238. })
  239. }
  240. },
  241. removeTab(tabIndex) {
  242. //console.log("removeTab", tabIndex)
  243. //判断删除的是否是当前页面
  244. const isActiveTab = this.editableTabs[tabIndex].name === this.editableTabsValue
  245. this.editableTabs.splice(tabIndex, 1)//删除当前tab页
  246. if (this.editableTabs.length === 0) {
  247. this.currentPage = {}
  248. return;
  249. }
  250. if (!isActiveTab) return; //不是当前页面直接结束
  251. if (tabIndex > 0) {
  252. const { title, name, content } = this.editableTabs[tabIndex - 1]
  253. this.currentPage.id = name
  254. this.currentPage.title = title
  255. this.currentPage.url = content
  256. this.editableTabsValue = name
  257. } else {
  258. const { title, name, content } = this.editableTabs[0]
  259. this.currentPage.id = name
  260. this.currentPage.title = title
  261. this.currentPage.url = content
  262. this.editableTabsValue = name
  263. }
  264. },
  265. tabClick(tabElement) {
  266. //console.log("tabClick", tabElement)
  267. const index = tabElement.index
  268. const { title, name, content } = this.editableTabs[index]
  269. this.currentPage.id = name
  270. this.currentPage.title = title
  271. this.currentPage.url = content
  272. this.editableTabsValue = name
  273. },
  274. getNowDate() {
  275. // 获取当前时间并格式化为 2024年12月10日/星期二/15:23 的格式
  276. const formattedDate = dayjs().format('YYYY年MM月DD日/星期dd/HH:mm');
  277. return formattedDate
  278. },
  279. sendChildWindowMessage: function (operation, data) {
  280. const iframe = this.$refs.iframe
  281. if (operation == "update-graph") {
  282. setTimeout(() => {
  283. iframe.contentWindow.postMessage({ operation, data }, "*")
  284. }, 1000)
  285. } else {
  286. iframe.contentWindow.postMessage({ operation, data }, "*")
  287. }
  288. },
  289. receiveIframeMsg() {
  290. const iframe = this.$refs.iframe
  291. window.addEventListener("message", (event) => {
  292. //console.log("receiveIframeMsg", event)
  293. const { opType } = event.data
  294. if (opType) {
  295. this.dialogData.title = event.data.title
  296. this.dialogData.opType = opType
  297. this.dialogData.showFooter = event.data.showFooter
  298. this.dialogData.width = event.data.width
  299. this.dialogVisible = event.data.dialogVisible
  300. if (opType == 'modifyEntityName-dropdown') {
  301. this.selectedName = event.data.data.selectedName
  302. this.searchInp = event.data.data.searchInp
  303. } else if (opType == 'deleteEntity-dropdown') {
  304. this.selectedName = event.data.data.selectedName
  305. this.searchInp = event.data.data.searchInp
  306. } else if (opType == 'deleteRelationship') {
  307. this.deleteRelationship = event.data.data
  308. } else if (opType == "modifyRelationship") {//右键修改关系名称
  309. this.modifyRelationship.oldVal = event.data.data.relationshipType
  310. } else if (opType == "modifyEntityName") { //右键修改实体名称
  311. this.modifyEntityName.oldName = event.data.data.properties.name
  312. this.modifyEntityName.nodeId = event.data.data.nodeId
  313. this.modifyEntityName.label = event.data.data.type
  314. } else if (opType == "deleteEntity") { //右键删除实体
  315. this.deleteEntity.name = event.data.data.properties.name
  316. this.deleteEntity.nodeId = event.data.data.nodeId
  317. } else if (opType == 'addRelationship') { //右键新增关系
  318. this.addRelationship.startId = event.data.data.nodeId
  319. this.addRelationship.startName = event.data.data.properties.name
  320. this.addRelationship.startLabel = event.data.data.type
  321. } else if (opType == 'addProperty') { //右键新增属性
  322. this.addProperty.nodeId = event.data.data.nodeId
  323. this.addProperty.name = event.data.data.properties.name
  324. this.addProperty.label = event.data.data.type
  325. } else if (opType == 'deleteProperty') { //右键删除属性
  326. this.deleteProperty.nodeId = event.data.data.nodeId
  327. this.deleteProperty.label = event.data.data.type
  328. this.deleteProperty.name = event.data.data.properties.parentName
  329. this.deleteProperty.propertyName = event.data.data.properties.name
  330. } else if (opType === 'modifyProperty') { //右键修改属性
  331. this.modifyProperty.label = event.data.data.type
  332. this.modifyProperty.oldPropertyName = event.data.data.properties.name
  333. this.modifyProperty.oldPropertyValue = event.data.data.properties.value
  334. this.modifyProperty.nodeId = event.data.data.nodeId
  335. } else if (opType === 'merge-entity') { //实体合并
  336. this.mergeEntity = { ...event.data.data }
  337. } else if (opType == 'entityLink') { //实体链接
  338. this.entityLink = { ...this.$options.data().entityLink }
  339. this.entityLink.categories = event.data.data.categories
  340. event.data.data.entityNode.forEach((el, index) => {
  341. el.name = index
  342. el.symbolSize = 80
  343. el.symbol = 'circle'
  344. el.itemStyle = {}
  345. this.entityLink.nodes.push(el)
  346. })
  347. this.$nextTick(() => {
  348. this.drawGraph()
  349. })
  350. } else if (opType == "addRelationship-dropdown") {
  351. this.dialogData.width = '900px'
  352. } else if (opType == "addProperty-dropdown") {
  353. this.dialogData.width = '800px'
  354. }
  355. }
  356. })
  357. },
  358. addEntityAddRow() {
  359. this.tableData.push({ "label": "疾病", "name": "" })
  360. },
  361. deleteRow(index, tableData) {
  362. tableData.splice(index, 1)
  363. },
  364. dialogSubmit() {
  365. switch (this.dialogData.opType) {
  366. case "addEntity":
  367. post(api.createEntity, this.tableData).then((res) => {
  368. //console.log("createEntity", res.data)
  369. if (res.data.code == '0') {
  370. //重置this.tableData的数据
  371. this.tableData = [...this.$options.data().tableData]
  372. this.dialogVisible = false
  373. this.sendChildWindowMessage("update-graph", "")
  374. }
  375. }).catch(err => {
  376. console.log("createEntity接口出错", err)
  377. })
  378. break
  379. case "modifyEntityName-dropdown":
  380. this.updateEntityName(this.nodeTable, -1)
  381. break
  382. case "addRelationship-dropdown":
  383. post(api.createRelationship, this.addRelationshipDropdown).then(res => {
  384. const { msg, code, data } = res.data
  385. if (res.data.code == '0') {
  386. this.addRelationshipDropdown = [...this.$options.data().addRelationshipDropdown]
  387. //console.log("addRelationshipDropdown", this.$options.data().addRelationshipDropdown)
  388. this.dialogVisible = false
  389. this.sendChildWindowMessage("update-graph", "")
  390. }
  391. }).catch(err => {
  392. console.log("createRelationship接口错误", err)
  393. })
  394. break
  395. case 'addProperty-dropdown':
  396. const data = [
  397. {
  398. "label": "string",
  399. "nodeId": 0,
  400. "property": {}
  401. }
  402. ]
  403. data[0].label = this.addPropertyDropdown.label
  404. data[0].nodeId = this.addPropertyDropdown.nodeId
  405. this.addPropertyDropdown.property.forEach(el => {
  406. data[0].property[el.key] = el.value
  407. })
  408. post(api.createEntityProperty, data).then(res => {
  409. const { msg, code, data } = res.data
  410. if (res.data.code == '0') {
  411. //this.addPropertyDropdown.property = []
  412. //this.dialogVisible = false
  413. this.addPropertyDropdown = { ...this.$options.data().addPropertyDropdown }
  414. this.sendChildWindowMessage("update-graph", "")
  415. }
  416. }).catch(err => {
  417. console.log("createEntityProperty接口错误", err)
  418. })
  419. break
  420. case 'deleteRelationship': //删除关系
  421. post(api.deleteRelationship, [this.deleteRelationship]).then(res => {
  422. const { msg, code, data } = res.data
  423. if (res.data.code == '0') {
  424. this.dialogVisible = false
  425. this.sendChildWindowMessage("update-graph", "")
  426. }
  427. }).catch(err => {
  428. console.log("createEntityProperty接口错误", err)
  429. })
  430. break
  431. case "modifyRelationship": //右键修改关系
  432. post(api.updateRelationshipType, [{
  433. "newRelationshipType": this.modifyRelationship.newVal,
  434. "oldRelationshipType": this.modifyRelationship.oldVal
  435. }]).then(res => {
  436. const { data, msg, code } = res.data
  437. if (code == '0') {
  438. this.modifyRelationship = { ...this.$options.data().modifyRelationship }
  439. //this.tableData.splice(index, 1)
  440. this.sendChildWindowMessage("update-graph", "")
  441. this.dialogVisible = false
  442. }
  443. }).catch(err => {
  444. console.log("updateRelationshipType接口出错", err)
  445. })
  446. break
  447. case "modifyEntityName":
  448. post(api.updateEntityName, [this.modifyEntityName]).then(res => {
  449. const { data, msg, code } = res.data
  450. if (code == '0') {
  451. this.dialogVisible = false
  452. this.modifyEntityName = { ...this.$options.data().modifyEntityName }
  453. this.sendChildWindowMessage("update-graph", "")
  454. }
  455. }).catch(err => {
  456. console.log("updateEntityName接口出错", err)
  457. })
  458. break
  459. case "deleteEntity":
  460. post(api.deleteEntity, [this.deleteEntity.nodeId]).then(res => {
  461. const { data, msg, code } = res.data
  462. if (code == '0') {
  463. this.deleteEntity = { ...this.$options.data().deleteEntity }
  464. this.dialogVisible = false
  465. this.sendChildWindowMessage("update-graph", "")
  466. }
  467. }).catch(err => {
  468. console.log("deleteEntity接口出错", err)
  469. })
  470. break
  471. case "addRelationship": //右键新增关系
  472. post(api.createRelationship, [this.addRelationship]).then(res => {
  473. const { msg, code, data } = res.data
  474. if (res.data.code == '0') {
  475. this.addRelationship = { ...this.$options.data().addRelationship }
  476. this.dialogVisible = false
  477. this.sendChildWindowMessage("update-graph", "")
  478. }
  479. }).catch(err => {
  480. console.log("createRelationship接口错误", err)
  481. })
  482. break
  483. case "addProperty":
  484. const addPropertyTemp = [
  485. {
  486. "label": "string",
  487. "nodeId": 0,
  488. "property": {}
  489. }
  490. ]
  491. addPropertyTemp[0].label = this.addProperty.label
  492. addPropertyTemp[0].nodeId = this.addProperty.nodeId
  493. this.addProperty.property.forEach(el => {
  494. addPropertyTemp[0].property[el.key] = el.value
  495. })
  496. post(api.createEntityProperty, addPropertyTemp).then(res => {
  497. const { msg, code, data } = res.data
  498. if (res.data.code == '0') {
  499. this.addProperty.property = [{ kye: "", value: "" }]
  500. this.dialogVisible = false
  501. this.sendChildWindowMessage("update-graph", "")
  502. }
  503. }).catch(err => {
  504. console.log("createEntityProperty接口错误", err)
  505. })
  506. break
  507. case "deleteProperty":
  508. post(api.deleteEntityProperty, [this.deleteProperty]).then(res => {
  509. const { msg, code, data } = res.data
  510. if (res.data.code == '0') {
  511. this.deleteProperty = {}
  512. this.dialogVisible = false
  513. this.sendChildWindowMessage("update-graph", "")
  514. }
  515. }).catch(err => {
  516. console.log("deleteEntityProperty接口错误", err)
  517. })
  518. break
  519. case "modifyProperty"://右键修改属性
  520. post(api.updateEntityProperty, this.modifyProperty).then(res => {
  521. const { data, msg, code } = res.data
  522. if (code == '0') {
  523. this.dialogVisible = false
  524. this.sendChildWindowMessage("update-graph", "")
  525. }
  526. }).catch(err => {
  527. console.log("updateEntityProperty接口出错", err)
  528. })
  529. break
  530. case "merge-entity":
  531. post(api.mergeEntity, this.mergeEntity).then(res => {
  532. const { data, msg, code } = res.data
  533. if (code == '0') {
  534. this.dialogVisible = false
  535. this.sendChildWindowMessage("update-graph", "")
  536. }
  537. }).catch(err => {
  538. console.log("mergeEntity接口出错", err)
  539. })
  540. break
  541. case "entityLink":
  542. const relationshipList = []
  543. this.entityLink.links.forEach((el) => {
  544. relationshipList.push({
  545. "endId": this.entityLink.nodes[el.target].nodeId,
  546. "endLabel": this.entityLink.nodes[el.target].type,
  547. "property": {},
  548. "relationshipType": el.value,
  549. "startId": this.entityLink.nodes[el.source].nodeId,
  550. "startLabel": this.entityLink.nodes[el.source].type
  551. })
  552. })
  553. post(api.createRelationship, relationshipList).then(res => {
  554. const { msg, code, data } = res.data
  555. if (res.data.code == '0') {
  556. this.dialogVisible = false
  557. this.sendChildWindowMessage("update-graph", "")
  558. return
  559. }
  560. }).catch(err => {
  561. console.log("createRelationship接口错误", err)
  562. })
  563. break
  564. default:
  565. this.dialogVisible = false
  566. this.sendChildWindowMessage("update-graph", "")
  567. }
  568. },
  569. addPropertyDropdownValueChange(value) {
  570. for (let i = 0; i < this.addPropertyDropdownOptions.length; i++) {
  571. const option = this.addPropertyDropdownOptions[i]
  572. if (option.nodeId === value) {
  573. this.addPropertyDropdown.name = option.name
  574. break
  575. }
  576. }
  577. // this.addPropertyDropdownOptions
  578. },
  579. addPropertyDropdownRemoteMethod(name, label) {
  580. post(api.getNode, {
  581. "inputStr": name,
  582. "labelName": label
  583. }).then(res => {
  584. const { msg, code, data } = res.data
  585. if (code == '0') {
  586. this.addPropertyDropdownOptions = data
  587. // data.forEach((el, index) => {
  588. // this.addPropertyDropdownOptions.push(
  589. // { oldName: el.name, name: "", nodeId: el.nodeId, type: el.label })
  590. // })
  591. }
  592. }).catch(err => {
  593. console.log("addPropertyDropdownRemoteMethod的getNode接口出错了", err)
  594. })
  595. },
  596. getNode() {
  597. post(api.getNode, {
  598. "inputStr": this.searchInp,
  599. "labelName": this.selectedName
  600. }).then(res => {
  601. const { msg, code, data } = res.data
  602. if (code == '0') {
  603. this.nodeTable = []
  604. data.forEach((el, index) => {
  605. this.nodeTable.push(
  606. { oldName: el.name, name: "", nodeId: el.nodeId, type: el.label })
  607. })
  608. }
  609. }).catch(err => {
  610. console.log("getNode接口出错了", err)
  611. })
  612. },
  613. updateEntityName(data, index) {
  614. this.$confirm("确定修改实体名称吗?", "修改实体名称提示", {
  615. confirmButtonText: '确定',
  616. cancelButtonText: '取消',
  617. type: 'warning'
  618. }).then(() => {
  619. post(api.updateEntityName, data).then(res => {
  620. const { data, msg, code } = res.data
  621. if (code == '0') {
  622. if (index >= 0) {
  623. this.nodeTable.splice(index, 1)
  624. } else {
  625. //this.nodeTable = []
  626. this.nodeTable.splice(0, this.nodeTable.length)
  627. }
  628. this.sendChildWindowMessage("update-graph", "")
  629. }
  630. }).catch(err => {
  631. console.log("updateEntityName接口出错", err)
  632. })
  633. }).catch(err => {
  634. })
  635. },
  636. deleteEntityFunc(data, index) {
  637. this.$confirm('确定删除该实体吗?', '删除实体提示', {
  638. confirmButtonText: '确定',
  639. cancelButtonText: '取消',
  640. type: 'warning'
  641. }).then(() => {
  642. post(api.deleteEntity, data).then(res => {
  643. const { data, msg, code } = res.data
  644. if (code == '0') {
  645. if (index >= 0) {
  646. this.nodeTable.splice(index, 1)
  647. } else {
  648. this.nodeTable.splice(0, this.nodeTable.length)
  649. }
  650. this.sendChildWindowMessage("update-graph", "")
  651. }
  652. }).catch(err => {
  653. console.log("deleteEntity接口出错", err)
  654. })
  655. }).catch(err => {
  656. })
  657. },
  658. addRelationshipDropdownAddRow() {
  659. this.addRelationshipDropdown.push(this.$options.data().addRelationshipDropdown[0])
  660. },
  661. querySearchAsync(queryString, cb, label) {
  662. //console.log("label", label)
  663. post(api.getNode, {
  664. "inputStr": queryString,
  665. "labelName": label || "疾病"
  666. }).then(res => {
  667. const { msg, code, data } = res.data
  668. if (code == '0') {
  669. var restaurants = []
  670. data.forEach((el, index) => {
  671. restaurants.push(
  672. { value: el.name, nodeId: el.nodeId, label: el.label })
  673. })
  674. cb(restaurants)
  675. }
  676. }).catch(err => {
  677. console.log("querySearchAsync的getNode接口出错了", err)
  678. })
  679. },
  680. querySearchAsync2(query, cb) {
  681. if (!query) {
  682. cb([])
  683. return
  684. }
  685. post(api.findEntityListByName, {
  686. "label": this.modifyPropertyDropdown.label,
  687. "name": query
  688. }).then(res => {
  689. const { msg, code, data } = res.data
  690. if (code == '0') {
  691. var restaurants = []
  692. data.forEach((el, index) => {
  693. restaurants.push(
  694. { value: el.properties.name, nodeId: el.id, label: el.labels[0], properties: el.properties })
  695. })
  696. cb(restaurants)
  697. }
  698. }).catch(err => {
  699. console.log("findEntityListByName的getNode接口出错了", err)
  700. })
  701. },
  702. handleSelect(item, row, flag) {
  703. if (flag == 'start') {
  704. row.startId = item.nodeId
  705. row.startLabel = item.label
  706. } else if (flag == 'end') {
  707. row.endId = item.nodeId
  708. row.endLabel = item.label
  709. } else if (flag == 'addProperty-dropdown') { //下拉框新增属性
  710. row.label = item.label
  711. row.nodeId = item.nodeId
  712. this.addPropertyDropdown.property = []
  713. this.addPropertyDropdownAddRow()
  714. } else if (flag == 'addRelationship') {
  715. row.endLabel = item.label
  716. row.endId = item.nodeId
  717. } else if (flag == 'modifyProperty-dropdown') { //下拉修改属性
  718. row.splice(0, row.length)
  719. for (let i in item.properties) {
  720. if (i == 'name' || i == 'is_deleted') continue;
  721. const property = {
  722. "label": item.label,
  723. "name": item.value,
  724. "newPropertyName": "",
  725. "newPropertyValue": "",
  726. "nodeId": item.nodeId,
  727. "oldPropertyName": i,
  728. "oldPropertyValue": item.properties[i],
  729. }
  730. row.push(property)
  731. }
  732. }
  733. //console.log("handleSelect-2", item, row, flag);
  734. },
  735. findRelationshipType() {
  736. post(api.findRelationshipType, { "relationshipType": this.searchRelationshipName }).then(res => {
  737. const { data, msg, code } = res.data
  738. if (code === '0') {
  739. this.modifyRelationshipNameDropdown = []
  740. data.forEach((el, index) => {
  741. this.modifyRelationshipNameDropdown.push({
  742. "newRelationshipType": "",
  743. "oldRelationshipType": el
  744. })
  745. })
  746. }
  747. }).catch(err => {
  748. console.log("findRelationshipType接口出错了", err)
  749. })
  750. },
  751. updateRelationshipType(tableData, index) {
  752. this.$confirm('确定修改此关系名称吗?', '提示', {
  753. confirmButtonText: '确定',
  754. cancelButtonText: '取消',
  755. type: 'warning'
  756. }).then(() => {
  757. post(api.updateRelationshipType, [tableData[index]]).then(res => {
  758. const { data, msg, code } = res.data
  759. if (code == '0') {
  760. tableData.splice(index, 1)
  761. this.sendChildWindowMessage("update-graph", "")
  762. }
  763. }).catch(err => {
  764. console.log("updateRelationshipType接口出错", err)
  765. })
  766. }).catch(() => {
  767. });
  768. },
  769. addPropertyDropdownAddRow() {
  770. this.addPropertyDropdown.property.push(this.$options.data().addPropertyDropdown.property[0])
  771. },
  772. addPropertyAddRow() {
  773. this.addProperty.property.push({ key: "", value: "" })
  774. },
  775. modifyPropertyDropdownConfirm(index, tableData) {
  776. this.$confirm('确定修改此属性吗?', '提示', {
  777. confirmButtonText: '确定',
  778. cancelButtonText: '取消',
  779. type: 'warning'
  780. }).then(() => {
  781. post(api.updateEntityProperty, tableData[index]).then(res => {
  782. const { data, msg, code } = res.data
  783. if (code == '0') {
  784. tableData.splice(index, 1)
  785. this.sendChildWindowMessage("update-graph", "")
  786. }
  787. }).catch(err => {
  788. console.log("updateEntityProperty接口出错")
  789. })
  790. }).catch(() => {
  791. });
  792. },
  793. drawGraph() {
  794. if (myChart) {
  795. myChart.dispose();
  796. myChart = null
  797. }
  798. myChart = echarts.init(document.getElementById("entityLink"));
  799. const options = {
  800. color: ['#dd7172', '#E57373', '#0EB1EE', '#9D96F5', '#ACC68E', '#EDAA77', '#14BBB3', '#538FFF', '#1390FB', '#C7B02E',],
  801. grid: {
  802. containLabel: true, // 保证标签和内容在图表区域内
  803. //top: 1000
  804. },
  805. tooltip: {
  806. formatter: function (x) {
  807. return x.data.label;
  808. }
  809. },
  810. series: [{
  811. categories: this.entityLink.categories,
  812. type: 'graph',
  813. layout: 'circular',
  814. roam: 'none',
  815. force: {
  816. repulsion: 1000,
  817. edgeLength: [50, 150],
  818. layoutAnimation: true
  819. },
  820. //center: ['50%', '50%'],
  821. //radius: ['30%', '50%'],
  822. edgeSymbol: ['none', 'arrow'],
  823. edgeSymbolSize: 10,
  824. data: this.entityLink.nodes,
  825. links: this.entityLink.links,
  826. lineStyle: {
  827. normal: {
  828. color: 'target',
  829. cursor: 'default',
  830. width: 2,
  831. curveness: 0.3 // 设置弯曲度,避免重叠
  832. },
  833. },
  834. edgeLabel: {
  835. normal: {
  836. show: true,
  837. formatter: function (x) {
  838. return x.data.value; //横线关系
  839. }
  840. }
  841. },
  842. label: {
  843. normal: {
  844. show: true,
  845. textStyle: {
  846. cursor: 'pointer',
  847. },
  848. color: '#000', //label字体颜色
  849. formatter: function (x) {
  850. var tmp = x.data.label;
  851. if (tmp.length >= 12) {
  852. tmp = tmp.substring(0, 12);
  853. tmp = tmp + "...";
  854. }
  855. return tmp;
  856. }
  857. }
  858. },
  859. }]
  860. }
  861. myChart.setOption(options)
  862. var startNode = null;
  863. myChart.on('mousedown', (params) => {
  864. //console.log('mousedown', params)
  865. if (params && params.dataType === 'node') {
  866. startNode = { ...params }; // 记录开始拖动的节点
  867. }
  868. });
  869. // 监听鼠标移动事件
  870. myChart.getDom().addEventListener('mousemove', (event) => {
  871. //console.log("mousemove-event", event)
  872. if (startNode) {
  873. var rect = myChart.getDom().getBoundingClientRect();
  874. var mouseX = event.clientX - rect.left;
  875. var mouseY = event.clientY - rect.top;
  876. // 动态更新光标位置的线条
  877. myChart.setOption({
  878. graphic: [
  879. {
  880. type: 'line',
  881. shape: {
  882. x1: startNode.event.offsetX, // 节点的 x 坐标
  883. y1: startNode.event.offsetY, // 节点的 y 坐标
  884. x2: mouseX, // 光标的 x 坐标
  885. y2: mouseY // 光标的 y 坐标
  886. },
  887. style: {
  888. stroke: '#FF0000', // 线条颜色
  889. lineWidth: 2 // 线条宽度
  890. }
  891. }
  892. ]
  893. }, false);
  894. }
  895. });
  896. myChart.getDom().addEventListener('mouseup', (event) => {
  897. //console.log("mouseup-event", event)
  898. startNode = null
  899. const option = myChart.getOption()
  900. myChart.setOption({
  901. graphic: [
  902. {
  903. style: {
  904. lineWidth: 0 // 线条宽度
  905. }
  906. }
  907. ]
  908. }, false)
  909. })
  910. myChart.getDom().addEventListener('mouseleave', (event) => {
  911. //console.log("mouseup-event", event)
  912. startNode = null
  913. const option = myChart.getOption()
  914. myChart.setOption({
  915. graphic: [
  916. {
  917. style: {
  918. lineWidth: 0 // 线条宽度
  919. }
  920. }
  921. ]
  922. }, false)
  923. })
  924. myChart.on('dblclick', (event) => {
  925. //console.log("dblclick", event)
  926. if (event && event.dataType === 'edge') {
  927. this.$prompt('输入关系名', '关系修改提示', {
  928. confirmButtonText: '确定',
  929. cancelButtonText: '取消',
  930. inputValue: event.data.value,
  931. type: 'warning'
  932. }).then(({ value }) => {
  933. this.entityLink.links[event.dataIndex].value = value
  934. // 更新图表
  935. myChart.setOption({
  936. series: [{
  937. type: 'graph',
  938. links: this.entityLink.links
  939. }]
  940. }, false);
  941. }).catch((err) => {
  942. console.log("修改关系错误", err)
  943. })
  944. }
  945. });
  946. myChart.on('mouseup', (params) => {
  947. //console.log('mouseup', params)
  948. params.event.event.stopPropagation()
  949. if (startNode && params && params.dataType === 'node' && params.data.nodeId !== startNode.data.nodeId) {
  950. let isReverseLink = false //是否有相反方向的线
  951. let isLink = false //是否存在连线
  952. this.entityLink.links.forEach(el => {
  953. if (el.source === params.data.name && el.target === startNode.data.name) {
  954. isReverseLink = true
  955. }
  956. if (el.source === startNode.data.name && el.target === params.data.name) {
  957. isLink = true
  958. }
  959. })
  960. if (isLink) { //存在连线直接跳过
  961. myChart.setOption({ //销毁连线
  962. graphic: [
  963. {
  964. style: {
  965. lineWidth: 0 // 线条宽度
  966. }
  967. }
  968. ],
  969. }, false);
  970. startNode = null
  971. return
  972. }
  973. this.$prompt('请输入关系', '连接关系', {
  974. confirmButtonText: '确定',
  975. cancelButtonText: '取消',
  976. type: 'info'
  977. }).then(({ value }) => {
  978. // 创建正式的连线
  979. //console.log("输入的关系", value)
  980. this.entityLink.links.push({
  981. source: startNode.data.name,
  982. target: params.data.name,
  983. value: value,
  984. lineStyle: {
  985. curveness: isReverseLink ? 0.3 : -0.3,
  986. }
  987. });
  988. // 更新图表,移除临时连线
  989. myChart.setOption({
  990. graphic: [
  991. {
  992. style: {
  993. lineWidth: 0 // 线条宽度
  994. }
  995. }
  996. ],
  997. series: [{
  998. type: 'graph',
  999. data: this.entityLink.nodes,
  1000. links: this.entityLink.links
  1001. }]
  1002. }, false);
  1003. }).catch((err) => {
  1004. console.log("连线报错", err)
  1005. myChart.setOption({
  1006. graphic: [
  1007. {
  1008. style: {
  1009. lineWidth: 0 // 线条宽度
  1010. }
  1011. }
  1012. ],
  1013. }, false);
  1014. }).finally(() => {
  1015. // 重置
  1016. startNode = null;
  1017. })
  1018. } else {
  1019. myChart.setOption({ //隐藏连接线
  1020. graphic: [
  1021. {
  1022. style: {
  1023. lineWidth: 0 // 线条宽度
  1024. }
  1025. }
  1026. ]
  1027. }, false)
  1028. startNode = null;
  1029. }
  1030. });
  1031. },
  1032. handleLogin(event) {
  1033. const { type, username, userId } = event.data
  1034. if (type === 'login') {
  1035. this.username = username
  1036. window.localStorage.setItem('username', JSON.stringify(username))
  1037. window.localStorage.setItem('userId', JSON.stringify(userId))
  1038. }
  1039. }
  1040. },
  1041. watch: {
  1042. isCollapse: {
  1043. handler(newVal, oldVal) {
  1044. setTimeout(() => {
  1045. this.sendChildWindowMessage("left-collapse", this.isCollapse)
  1046. }, 200)
  1047. }
  1048. },
  1049. "searchInp": {
  1050. handler() {
  1051. this.getNode()
  1052. }
  1053. },
  1054. "selectedName": {
  1055. handler() {
  1056. this.getNode()
  1057. }
  1058. },
  1059. searchRelationshipName(newVal) {
  1060. if (newVal) {
  1061. this.findRelationshipType()
  1062. }
  1063. },
  1064. },
  1065. computed: {
  1066. },
  1067. created() {
  1068. // 使用 day.js 插件 设置为中文
  1069. dayjs.locale('zh-cn');
  1070. timer = setInterval(() => {
  1071. this.nowDate = this.getNowDate()
  1072. }, 1000)
  1073. this.receiveIframeMsg()
  1074. },
  1075. mounted() {
  1076. localStorage.getItem('username') && (this.username = JSON.parse(localStorage.getItem('username')) || '管理员')
  1077. window.addEventListener('message', this.handleLogin)
  1078. if (getUrlArgObject('page') === '2') {
  1079. this.simpleUpdataPage = true
  1080. this.currentPage = {
  1081. id: "knowledgeUpdate",
  1082. url: "./knowledgeUpdate.html",
  1083. title: "知识更新",
  1084. children: null
  1085. }
  1086. }
  1087. },
  1088. destroyed() {
  1089. //销毁定时器
  1090. clearInterval(timer)
  1091. window.removeEventListener('message', this.handleLogin)
  1092. }
  1093. })