DisposalProgressContentSecond.vue 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. <template>
  2. <div class="container">
  3. <el-scrollbar class="scrollbox">
  4. <div class="graph-box">
  5. <template v-for="(item, index) in nodeData" :key="index">
  6. <div class="graph-container">
  7. <div class="first-container">
  8. <div class="line-top" :style="{ opacity: index == 0 ? 0 : 1 }"></div>
  9. <div class="first-box" @click="handleNodeClick(item)">
  10. <div class="content">{{ item.nodeName }}</div>
  11. <div class="status-box" :class="getStatus(item.state)" v-if="item.state">
  12. {{ item.state }}
  13. </div>
  14. </div>
  15. <div class="line-bottom" :style="{ opacity: index == nodeData.length - 1 ? 0 : 1 }"></div>
  16. </div>
  17. <DisposalChildBox :data="item" @nodeClick="handleNodeClick" />
  18. <div class="node-data" v-if="!item.children || item.children?.length == 0"></div>
  19. </div>
  20. </template>
  21. </div>
  22. </el-scrollbar>
  23. <!-- 地图工具 -->
  24. <!-- <MapTools></MapTools> -->
  25. <!-- 病例管理节点弹窗 -->
  26. <CaseManageNodeDialog v-if="dialogStore.caseManageNodeDialogOpen"></CaseManageNodeDialog>
  27. <!-- 实验室检测节点弹窗 -->
  28. <LaboratoryTestNodeDialog v-if="dialogStore.laboratoryTestNodeDialogOpen"></LaboratoryTestNodeDialog>
  29. <!-- 风险场所管控节点弹窗 -->
  30. <RiskLocationControlDialog v-if="dialogStore.riskLocationControlDialogOpen"></RiskLocationControlDialog>
  31. </div>
  32. </template>
  33. <script setup>
  34. import { ref, onMounted } from 'vue'
  35. import DisposalChildBox from './common/DisposalChildBox.vue'
  36. import CaseManageNodeDialog from './dialog/CaseManageNodeDialog'
  37. import LaboratoryTestNodeDialog from './dialog/LaboratoryTestNodeDialog.vue'
  38. import RiskLocationControlDialog from './dialog/RiskLocationControlDialog.vue'
  39. // import MapTools from './dialog/MapTools.vue'
  40. import { useDialogStore } from '@/store/dialog'
  41. let dialogStore = useDialogStore()
  42. import { useRightPanelStore } from "@/store/rightPanel";
  43. const rightPanelStore = useRightPanelStore();
  44. const getStatus = status => {
  45. if (status == '已完成') {
  46. return 'status-green'
  47. }
  48. if (status == '进行中') {
  49. return 'status-red'
  50. }
  51. return 'status-no'
  52. }
  53. //点击节点
  54. const handleNodeClick = item => {
  55. console.log(item)
  56. if (!['病例管理', '实验室检测','风险场所管控'].includes(item.nodeName)) return
  57. rightPanelStore.handleCloseAllVisible()
  58. dialogStore.closeAllDialog()
  59. if (item.nodeName === '病例管理') {
  60. dialogStore.setCaseManageNodeDialogOpen(true)
  61. } else if (item.nodeName === '实验室检测') {
  62. dialogStore.setLaboratoryTestNodeDialogOpen(true)
  63. }else if (item.nodeName === '风险场所管控') {
  64. dialogStore.setRiskLocationControlDialogOpen(true)
  65. }
  66. }
  67. const nodeData = [
  68. {
  69. nodeId: 1,
  70. level: 1,
  71. nodeName: '发现报告',
  72. state: '已完成',
  73. children: [
  74. { nodeId: '1-1', level: 2, nodeName: '信息接报', state: '已完成' },
  75. { nodeId: '1-2', level: 2, nodeName: '信息核实', state: '已完成' },
  76. { nodeId: '1-3', level: 2, nodeName: '快速评估', state: '已完成' },
  77. { nodeId: '1-4', level: 2, nodeName: '信息上报', state: '已完成' }
  78. ]
  79. },
  80. {
  81. nodeId: 2,
  82. level: 1,
  83. nodeName: '个案调查处置',
  84. state: '进行中',
  85. children: [
  86. {
  87. nodeId: '2-1',
  88. level: 2,
  89. nodeName: '李梦康',
  90. state: '已完成'
  91. },
  92. {
  93. nodeId: '2-2',
  94. level: 2,
  95. nodeName: '毛超',
  96. state: '已完成',
  97. children: [
  98. { nodeId: '2-2-1', level: 3, nodeName: '病例管理', state: '已完成' },
  99. { nodeId: '2-2-2', level: 3, nodeName: '流行病学调查', state: '已完成' },
  100. { nodeId: '2-2-3', level: 3, nodeName: '实验室检测', state: '已完成' },
  101. { nodeId: '2-2-4', level: 3, nodeName: '风险评估', state: '已完成' }
  102. ]
  103. },
  104. { nodeId: '2-3', level: 2, nodeName: '贾子敏', state: '进行中' }
  105. ]
  106. },
  107. {
  108. nodeId: 3,
  109. level: 1,
  110. nodeName: '风险人员和环境排查管控',
  111. state: '进行中',
  112. children: [
  113. { nodeId: '3-1', level: 2, nodeName: '段伟', state: '已完成' },
  114. { nodeId: '3-2', level: 2, nodeName: '陆成奇', state: '已完成' },
  115. {
  116. nodeId: '3-3',
  117. nodeName: '曾强',
  118. state: '进行中',
  119. level: 2,
  120. children: [
  121. { nodeId: '3-3-1', level: 3, nodeName: '病例管理', state: '已完成' },
  122. { nodeId: '3-3-2', level: 3, nodeName: '流行病学调查', state: '已完成' },
  123. { nodeId: '3-3-3', level: 3, nodeName: '实验室检测', state: '进行中' },
  124. { nodeId: '3-3-4', level: 3, nodeName: '风险人员管控', state: '进行中' },
  125. { nodeId: '3-3-5', level: 3, nodeName: '风险场所管控', state: '进行中' }
  126. ]
  127. }
  128. ]
  129. },
  130. { nodeId: 4, level: 1, nodeName: '区域风险排查管控', state: '未开始' },
  131. { nodeId: 5, level: 1, nodeName: '结案' }
  132. ]
  133. // **画布**
  134. const graphRef = ref(null)
  135. function isLeafNode(d) {
  136. return !d.children || d.children.length === 0
  137. }
  138. // **初始化 X6 画布**
  139. onMounted(() => {})
  140. </script>
  141. <style land="scss" scoped>
  142. .container {
  143. width: 100%;
  144. height: 100%;
  145. .scrollbox {
  146. height: calc(100% - 10px);
  147. }
  148. }
  149. #graph_container {
  150. width: 100%;
  151. height: 100%;
  152. }
  153. .graph-container {
  154. position: relative;
  155. display: flex;
  156. align-items: stretch;
  157. margin: 0px 15px;
  158. margin-right: 0;
  159. /* &::before {
  160. position: absolute;
  161. content: "";
  162. width: 1px;
  163. top: -15px;
  164. height: calc(50% - 18px);
  165. left: 60px;
  166. border-left: 2px dashed #3fa7b6;
  167. z-index: 1;
  168. } */
  169. .first-container {
  170. position: relative;
  171. display: flex;
  172. flex-direction: column;
  173. align-items: center;
  174. justify-content: center;
  175. height: auto;
  176. .line-top {
  177. position: relative;
  178. flex: 1;
  179. width: 1px;
  180. border-left: 2px dashed #3fa7b6;
  181. z-index: 1;
  182. &::after {
  183. position: absolute;
  184. content: '';
  185. width: 17px;
  186. height: 23px;
  187. left: -9px;
  188. bottom: 0px;
  189. background-image: url('../../../../assets/img/节点连线箭头.png');
  190. background-size: 100% 100%;
  191. transform: rotate(90deg);
  192. }
  193. }
  194. .line-bottom {
  195. position: relative;
  196. flex: 1;
  197. width: 1px;
  198. border-left: 2px dashed #3fa7b6;
  199. z-index: 1;
  200. }
  201. }
  202. .node-data {
  203. height: 130px;
  204. }
  205. &:first-child {
  206. margin-top: 15px;
  207. &::before {
  208. display: none;
  209. }
  210. }
  211. /* &::after {
  212. position: absolute;
  213. content: "";
  214. width: 1px;
  215. height: calc(50% - 18px);
  216. bottom: -15px;
  217. left: 60px;
  218. border-left: 2px dashed #3fa7b6;
  219. z-index: 1;
  220. } */
  221. &:last-child {
  222. /* margin-top: 15px; */
  223. &::after {
  224. display: none;
  225. }
  226. }
  227. .first-box {
  228. position: relative;
  229. display: flex;
  230. flex-direction: column;
  231. justify-content: center;
  232. align-items: center;
  233. width: 120px;
  234. min-height: 53px;
  235. padding: 10px 0;
  236. flex-shrink: 0;
  237. background: rgba(16, 252, 255, 0.25);
  238. border-radius: 6px 6px 6px 6px;
  239. border: 1px solid #10fcff;
  240. z-index: 9;
  241. cursor: pointer;
  242. .content {
  243. width: 119px;
  244. white-space: wrap;
  245. font-family: Alibaba PuHuiTi;
  246. font-weight: normal;
  247. font-size: 18px;
  248. line-height: 24px;
  249. text-align: center;
  250. font-style: normal;
  251. text-transform: none;
  252. background: linear-gradient(to bottom, #ffffff 0%, #88eaff 100%);
  253. -webkit-background-clip: text;
  254. -webkit-text-fill-color: transparent;
  255. }
  256. .status-box {
  257. margin-top: 10px;
  258. padding: 0px 15px;
  259. font-family: Alibaba PuHuiTi 3, Alibaba PuHuiTi 30;
  260. font-weight: normal;
  261. font-size: 14px;
  262. text-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25);
  263. text-align: center;
  264. font-style: normal;
  265. text-transform: none;
  266. }
  267. .status-green {
  268. background-image: url('../../../../assets/img/Component 247.png');
  269. background-size: 100% 100%;
  270. background-repeat: no-repeat;
  271. color: #9de05a;
  272. }
  273. .status-red {
  274. background-image: url('../../../../assets/img/Component 246.png');
  275. background-size: 150% 100%;
  276. background-position-x: 50%;
  277. background-repeat: no-repeat;
  278. color: #ff4a4a;
  279. }
  280. .status-no {
  281. background-image: url('../../../../assets/img/Component 245.png');
  282. background-size: 100% 100%;
  283. background-repeat: no-repeat;
  284. color: #c9c9c9;
  285. }
  286. }
  287. }
  288. </style>