TreeNode.vue 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. <template>
  2. <div class="tree-node-container" :style="containerStyle" ref="node">
  3. <div class="tree-node" :style="cardStyle" @click="nodeClick(id)">
  4. <ElCard class="tree-node-card" shadow="hover">
  5. <template #header>
  6. <div class="card-header">
  7. <span class="node-title">{{title}}</span>
  8. <ElTag class="node-state" :type="getTagTypeFromState(state)">{{state}}</ElTag>
  9. </div>
  10. </template>
  11. <div class="card-body">
  12. <PriorityTag :size="'mini'" :priority="priority"></PriorityTag>
  13. <ElTag size="mini" >{{processor}}</ElTag>
  14. </div>
  15. </ElCard>
  16. </div>
  17. <div class="node-postfix">
  18. <template v-if="depth!==1">
  19. <div class="icon" target="delete" @click="deleteNode(id)"></div>
  20. </template>
  21. <template v-if="depth!==4">
  22. <div class="icon" target="add" @click="addChild(id)"></div>
  23. </template>
  24. </div>
  25. </div>
  26. </template>
  27. <script>
  28. import PriorityTag from '@/components/PriorityTag.vue';
  29. const getTagTypeFromState = (state) => {
  30. if (state === '已创建') {
  31. return '';
  32. } if (state === '进行中') {
  33. return 'success';
  34. } if (state === '已完成' || state === '已结束') {
  35. return 'info';
  36. }
  37. return 'danger';
  38. };
  39. export default {
  40. name: 'TreeNode',
  41. components: { PriorityTag },
  42. props: {
  43. id: Number,
  44. state: String,
  45. title: String,
  46. positionY: Number,
  47. positionX: Number,
  48. nodeStyle: Object,
  49. depth: Number,
  50. processor: String,
  51. priority: String,
  52. },
  53. computed: {
  54. containerStyle() {
  55. return {
  56. top: `${this.positionY * 180}px`,
  57. left: `${280 * this.positionX - 100}px`,
  58. width: `${this.nodeStyle.width + this.nodeStyle.padding * 2}px`,
  59. height: `${this.nodeStyle.height + this.nodeStyle.padding * 2}px`,
  60. };
  61. },
  62. cardStyle() {
  63. return {
  64. width: `${this.nodeStyle.width}px`,
  65. height: `${this.nodeStyle.height}px`,
  66. };
  67. },
  68. },
  69. methods: {
  70. getTagTypeFromState,
  71. getTreeNodeSizeAndPosition() {
  72. return {
  73. top: this.$refs.node.offsetTop + this.nodeStyle.padding,
  74. left: this.$refs.node.offsetLeft + this.nodeStyle.padding,
  75. height: this.nodeStyle.height,
  76. width: this.nodeStyle.width,
  77. };
  78. },
  79. addChild(id) {
  80. this.$emit('add-child', id);
  81. },
  82. deleteNode(id) {
  83. this.$emit('delete-node', id);
  84. },
  85. nodeClick(id) {
  86. this.$emit('node-click', id);
  87. },
  88. },
  89. };
  90. </script>
  91. <style lang="scss" scoped>
  92. .tree-node-container {
  93. position: absolute;
  94. box-sizing: border-box;
  95. display: flex;
  96. justify-content: center;
  97. align-items: center;
  98. user-select: none;
  99. & .node-postfix {
  100. position: absolute;
  101. bottom: 10px;
  102. right: 25px;
  103. width: 100%;
  104. display: none;
  105. }
  106. &:hover .node-postfix {
  107. display: block;
  108. }
  109. }
  110. .tree-node {
  111. box-sizing: border-box;
  112. }
  113. .card-header {
  114. display: flex;
  115. justify-content: space-between;
  116. }
  117. .card-body{
  118. display: flex;
  119. justify-content: space-between;
  120. }
  121. .icon {
  122. width: 14px;
  123. height: 14px;
  124. float: right;
  125. background-position: center;
  126. background-repeat: no-repeat;
  127. background-size: 100% 100%;
  128. margin-top: 10px;
  129. margin-right: 10px;
  130. transition: all .2s linear;
  131. }
  132. .icon:hover{
  133. cursor: pointer;
  134. transition-duration: 0.2s;
  135. transform: scale(1.1);
  136. transition-timing-function:ease-in-out;
  137. }
  138. .icon[target=add]{
  139. background-image: url("../assets/icon/add.svg");
  140. }
  141. .icon[target=delete]{
  142. background-image: url("../assets/icon/delete.svg");
  143. }
  144. </style>