TreeNode.vue 3.4 KB

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