|  | @@ -1,11 +1,23 @@
 | 
	
		
			
				|  |  |  <template>
 | 
	
		
			
				|  |  |    <div class="mind">
 | 
	
		
			
				|  |  |      <div class="mind-left">
 | 
	
		
			
				|  |  | -      <div v-for="(li, i) in UpperHalf" :key="`mind-${i}`" :class="['task-item', mindHalfListClass(i, true)]">
 | 
	
		
			
				|  |  | -        <span :class="['task-item-name']" :data-index="i + 1">
 | 
	
		
			
				|  |  | -          <span class="nowrap-ellipsis" :title="li.name">{{ li.name }}</span>
 | 
	
		
			
				|  |  | -        </span>
 | 
	
		
			
				|  |  | -        <span class="task-item-date">{{ previewDateTransform(li.begin_time, li.duration_second) }}</span>
 | 
	
		
			
				|  |  | +      <div v-for="(li, i) in UpperHalf" :key="`mind-${i}`" class="task-wrap">
 | 
	
		
			
				|  |  | +        <div class="subtask-list">
 | 
	
		
			
				|  |  | +          <div
 | 
	
		
			
				|  |  | +            v-for="({ name }, j) in li.child_task_list"
 | 
	
		
			
				|  |  | +            :key="`mind-subtask-${j}`"
 | 
	
		
			
				|  |  | +            :class="['subtask-item', mindHalfListClass(i, true, j, true)]"
 | 
	
		
			
				|  |  | +          >
 | 
	
		
			
				|  |  | +            <span class="subtask-name">{{ name }}</span>
 | 
	
		
			
				|  |  | +            <span class="subtask-index">子任务 {{ j + 1 }}</span>
 | 
	
		
			
				|  |  | +          </div>
 | 
	
		
			
				|  |  | +        </div>
 | 
	
		
			
				|  |  | +        <div :class="['task-item', { 'has-subtask': li.child_task_list.length > 0 }, mindHalfListClass(i, true)]">
 | 
	
		
			
				|  |  | +          <span :class="['task-item-name']" :data-index="i + 1">
 | 
	
		
			
				|  |  | +            <span class="nowrap-ellipsis" :title="li.name">{{ li.name }}</span>
 | 
	
		
			
				|  |  | +          </span>
 | 
	
		
			
				|  |  | +          <span class="task-item-date">{{ previewDateTransform(li.begin_time, li.duration_second) }}</span>
 | 
	
		
			
				|  |  | +        </div>
 | 
	
		
			
				|  |  |        </div>
 | 
	
		
			
				|  |  |      </div>
 | 
	
		
			
				|  |  |      <div class="main-wrap">
 | 
	
	
		
			
				|  | @@ -14,14 +26,24 @@
 | 
	
		
			
				|  |  |        <span v-if="LowerHalf.length > 0" class="connect-line" :style="{ right: '-35px' }"></span>
 | 
	
		
			
				|  |  |      </div>
 | 
	
		
			
				|  |  |      <div class="mind-right">
 | 
	
		
			
				|  |  | -      <template v-for="(li, i) in LowerHalf">
 | 
	
		
			
				|  |  | -        <div :key="`mind-${i}`" :class="['task-item', mindHalfListClass(i, false)]">
 | 
	
		
			
				|  |  | +      <div v-for="(li, i) in LowerHalf" :key="`mind-${i}`" class="task-wrap">
 | 
	
		
			
				|  |  | +        <div :class="['task-item', { 'has-subtask': li.child_task_list.length > 0 }, mindHalfListClass(i, false)]">
 | 
	
		
			
				|  |  |            <span class="task-item-name" :data-index="i + median + 2">
 | 
	
		
			
				|  |  |              <span>{{ li.name }}</span>
 | 
	
		
			
				|  |  |            </span>
 | 
	
		
			
				|  |  |            <span class="task-item-date">{{ previewDateTransform(li.begin_time, li.duration_second) }}</span>
 | 
	
		
			
				|  |  |          </div>
 | 
	
		
			
				|  |  | -      </template>
 | 
	
		
			
				|  |  | +        <div class="subtask-list">
 | 
	
		
			
				|  |  | +          <div
 | 
	
		
			
				|  |  | +            v-for="({ name }, j) in li.child_task_list"
 | 
	
		
			
				|  |  | +            :key="`mind-subtask-${j}`"
 | 
	
		
			
				|  |  | +            :class="['subtask-item', mindHalfListClass(i, false, j, true)]"
 | 
	
		
			
				|  |  | +          >
 | 
	
		
			
				|  |  | +            <span class="subtask-name">{{ name }}</span>
 | 
	
		
			
				|  |  | +            <span class="subtask-index">子任务 {{ j + 1 }}</span>
 | 
	
		
			
				|  |  | +          </div>
 | 
	
		
			
				|  |  | +        </div>
 | 
	
		
			
				|  |  | +      </div>
 | 
	
		
			
				|  |  |      </div>
 | 
	
		
			
				|  |  |    </div>
 | 
	
		
			
				|  |  |  </template>
 | 
	
	
		
			
				|  | @@ -54,16 +76,20 @@ let LowerHalf = computed(() => {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /**
 | 
	
		
			
				|  |  |   * 计算上/下半部分每个子项所需的 class
 | 
	
		
			
				|  |  | - * @param {Number} i 索引
 | 
	
		
			
				|  |  | + * @param {Number} i 任务索引
 | 
	
		
			
				|  |  |   * @param {Boolean} isUpper 是否上半部分
 | 
	
		
			
				|  |  | + * @param {Number} j 子任务索引
 | 
	
		
			
				|  |  | + * @param {Boolean} isSubtask 是否子任务
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  | -function mindHalfListClass(i, isUpper) {
 | 
	
		
			
				|  |  | -  let length = isUpper ? UpperHalf.value.length : LowerHalf.value.length;
 | 
	
		
			
				|  |  | +function mindHalfListClass(i, isUpper, j, isSubtask = false) {
 | 
	
		
			
				|  |  | +  let list = isUpper ? UpperHalf.value : LowerHalf.value;
 | 
	
		
			
				|  |  | +  let length = isSubtask ? list[i].child_task_list.length : list.length;
 | 
	
		
			
				|  |  |    if (length === 1) return;
 | 
	
		
			
				|  |  |    let half = Math.ceil(length / 2) - 1;
 | 
	
		
			
				|  |  |    const isEven = length % 2 === 0;
 | 
	
		
			
				|  |  | -  if (isEven) return i <= half ? 'mind-down' : 'mind-up';
 | 
	
		
			
				|  |  | -  return i < half ? 'mind-down' : i === half ? 'mind-center' : 'mind-up';
 | 
	
		
			
				|  |  | +  let index = isSubtask ? j : i;
 | 
	
		
			
				|  |  | +  if (isEven) return index <= half ? 'mind-down' : 'mind-up';
 | 
	
		
			
				|  |  | +  return index < half ? 'mind-down' : index === half ? 'mind-center' : 'mind-up';
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  </script>
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -95,6 +121,7 @@ $bc-color: #2a76e8;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      .csitem-name {
 | 
	
		
			
				|  |  |        display: inline-block;
 | 
	
		
			
				|  |  | +      max-width: 300px;
 | 
	
		
			
				|  |  |        padding: 8px 12px;
 | 
	
		
			
				|  |  |        color: #fff;
 | 
	
		
			
				|  |  |        vertical-align: middle;
 | 
	
	
		
			
				|  | @@ -117,6 +144,17 @@ $bc-color: #2a76e8;
 | 
	
		
			
				|  |  |        &::after {
 | 
	
		
			
				|  |  |          right: -31px;
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      &.has-subtask::after {
 | 
	
		
			
				|  |  | +        left: -19px;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    .subtask-item {
 | 
	
		
			
				|  |  | +      &::before,
 | 
	
		
			
				|  |  | +      &::after {
 | 
	
		
			
				|  |  | +        right: -28px;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -126,29 +164,125 @@ $bc-color: #2a76e8;
 | 
	
		
			
				|  |  |        &::after {
 | 
	
		
			
				|  |  |          left: -31px;
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      &.has-subtask::after {
 | 
	
		
			
				|  |  | +        right: -19px;
 | 
	
		
			
				|  |  | +        left: auto;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    .subtask-item {
 | 
	
		
			
				|  |  | +      &::before,
 | 
	
		
			
				|  |  | +      &::after {
 | 
	
		
			
				|  |  | +        left: -28px;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  .task-item {
 | 
	
		
			
				|  |  | -    position: relative;
 | 
	
		
			
				|  |  | +  .task-wrap {
 | 
	
		
			
				|  |  |      display: flex;
 | 
	
		
			
				|  |  | -    flex-direction: column;
 | 
	
		
			
				|  |  | -    row-gap: 8px;
 | 
	
		
			
				|  |  | -    padding: 8px 12px;
 | 
	
		
			
				|  |  | -    background-color: #fff;
 | 
	
		
			
				|  |  | -    border-radius: 20px;
 | 
	
		
			
				|  |  | +    column-gap: 47px;
 | 
	
		
			
				|  |  | +    align-items: center;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    &::before {
 | 
	
		
			
				|  |  | -      position: absolute;
 | 
	
		
			
				|  |  | -      top: 50%;
 | 
	
		
			
				|  |  | -      width: 31px;
 | 
	
		
			
				|  |  | -      height: 3px;
 | 
	
		
			
				|  |  | -      content: '';
 | 
	
		
			
				|  |  | -      background-color: $bc-color;
 | 
	
		
			
				|  |  | +    // 子任务列表
 | 
	
		
			
				|  |  | +    .subtask-list {
 | 
	
		
			
				|  |  | +      display: flex;
 | 
	
		
			
				|  |  | +      flex-direction: column;
 | 
	
		
			
				|  |  | +      row-gap: 8px;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      .subtask-item {
 | 
	
		
			
				|  |  | +        position: relative;
 | 
	
		
			
				|  |  | +        display: flex;
 | 
	
		
			
				|  |  | +        flex-direction: column;
 | 
	
		
			
				|  |  | +        row-gap: 8px;
 | 
	
		
			
				|  |  | +        padding: 8px 12px;
 | 
	
		
			
				|  |  | +        background-color: #fff;
 | 
	
		
			
				|  |  | +        border-radius: 20px;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        &::before {
 | 
	
		
			
				|  |  | +          position: absolute;
 | 
	
		
			
				|  |  | +          top: 50%;
 | 
	
		
			
				|  |  | +          width: 28px;
 | 
	
		
			
				|  |  | +          height: 3px;
 | 
	
		
			
				|  |  | +          content: '';
 | 
	
		
			
				|  |  | +          background-color: $bc-color;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        &.mind-down::after {
 | 
	
		
			
				|  |  | +          position: absolute;
 | 
	
		
			
				|  |  | +          top: 50%;
 | 
	
		
			
				|  |  | +          width: 3px;
 | 
	
		
			
				|  |  | +          height: calc(50% + 6px);
 | 
	
		
			
				|  |  | +          content: '';
 | 
	
		
			
				|  |  | +          background-color: $bc-color;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        &.mind-center::after {
 | 
	
		
			
				|  |  | +          position: absolute;
 | 
	
		
			
				|  |  | +          top: -33px;
 | 
	
		
			
				|  |  | +          width: 3px;
 | 
	
		
			
				|  |  | +          height: calc(100% + 66px);
 | 
	
		
			
				|  |  | +          content: '';
 | 
	
		
			
				|  |  | +          background-color: $bc-color;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        &.mind-up::after {
 | 
	
		
			
				|  |  | +          position: absolute;
 | 
	
		
			
				|  |  | +          bottom: 50%;
 | 
	
		
			
				|  |  | +          width: 3px;
 | 
	
		
			
				|  |  | +          height: calc(50% + 6px);
 | 
	
		
			
				|  |  | +          content: '';
 | 
	
		
			
				|  |  | +          background-color: $bc-color;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        .subtask-name {
 | 
	
		
			
				|  |  | +          display: flex;
 | 
	
		
			
				|  |  | +          align-items: center;
 | 
	
		
			
				|  |  | +          font-size: 16px;
 | 
	
		
			
				|  |  | +          font-weight: bold;
 | 
	
		
			
				|  |  | +          color: #000;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        .subtask-index {
 | 
	
		
			
				|  |  | +          min-width: 82px;
 | 
	
		
			
				|  |  | +          height: 22px;
 | 
	
		
			
				|  |  | +          padding: 2px 12px;
 | 
	
		
			
				|  |  | +          background-color: #ebebeb;
 | 
	
		
			
				|  |  | +          border-radius: 20px;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    &.mind-down {
 | 
	
		
			
				|  |  | -      &::after {
 | 
	
		
			
				|  |  | +    .task-item {
 | 
	
		
			
				|  |  | +      position: relative;
 | 
	
		
			
				|  |  | +      display: flex;
 | 
	
		
			
				|  |  | +      flex-direction: column;
 | 
	
		
			
				|  |  | +      row-gap: 8px;
 | 
	
		
			
				|  |  | +      width: 310px;
 | 
	
		
			
				|  |  | +      height: 72px;
 | 
	
		
			
				|  |  | +      padding: 8px 12px;
 | 
	
		
			
				|  |  | +      background-color: #fff;
 | 
	
		
			
				|  |  | +      border-radius: 20px;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      &.has-subtask::after {
 | 
	
		
			
				|  |  | +        position: absolute;
 | 
	
		
			
				|  |  | +        top: 50%;
 | 
	
		
			
				|  |  | +        width: 19px;
 | 
	
		
			
				|  |  | +        height: 3px;
 | 
	
		
			
				|  |  | +        content: '';
 | 
	
		
			
				|  |  | +        background-color: $bc-color;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      &::before {
 | 
	
		
			
				|  |  | +        position: absolute;
 | 
	
		
			
				|  |  | +        top: 50%;
 | 
	
		
			
				|  |  | +        width: 31px;
 | 
	
		
			
				|  |  | +        height: 3px;
 | 
	
		
			
				|  |  | +        content: '';
 | 
	
		
			
				|  |  | +        background-color: $bc-color;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      &.mind-down::after {
 | 
	
		
			
				|  |  |          position: absolute;
 | 
	
		
			
				|  |  |          top: 50%;
 | 
	
		
			
				|  |  |          width: 3px;
 | 
	
	
		
			
				|  | @@ -156,10 +290,8 @@ $bc-color: #2a76e8;
 | 
	
		
			
				|  |  |          content: '';
 | 
	
		
			
				|  |  |          background-color: $bc-color;
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    &.mind-center {
 | 
	
		
			
				|  |  | -      &::after {
 | 
	
		
			
				|  |  | +      &.mind-center::after {
 | 
	
		
			
				|  |  |          position: absolute;
 | 
	
		
			
				|  |  |          top: -33px;
 | 
	
		
			
				|  |  |          width: 3px;
 | 
	
	
		
			
				|  | @@ -167,48 +299,46 @@ $bc-color: #2a76e8;
 | 
	
		
			
				|  |  |          content: '';
 | 
	
		
			
				|  |  |          background-color: $bc-color;
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    &.mind-up {
 | 
	
		
			
				|  |  | -      &::after {
 | 
	
		
			
				|  |  | +      &.mind-up::after {
 | 
	
		
			
				|  |  |          position: absolute;
 | 
	
		
			
				|  |  | -        top: calc(-50% + 3px);
 | 
	
		
			
				|  |  | +        bottom: 50%;
 | 
	
		
			
				|  |  |          width: 3px;
 | 
	
		
			
				|  |  |          height: calc(50% + 33px);
 | 
	
		
			
				|  |  |          content: '';
 | 
	
		
			
				|  |  |          background-color: $bc-color;
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    &-name {
 | 
	
		
			
				|  |  | -      display: flex;
 | 
	
		
			
				|  |  | -      align-items: center;
 | 
	
		
			
				|  |  | -      font-size: 16px;
 | 
	
		
			
				|  |  | -      font-weight: bold;
 | 
	
		
			
				|  |  | -      color: #000;
 | 
	
		
			
				|  |  | +      &-name {
 | 
	
		
			
				|  |  | +        display: flex;
 | 
	
		
			
				|  |  | +        align-items: center;
 | 
	
		
			
				|  |  | +        font-size: 16px;
 | 
	
		
			
				|  |  | +        font-weight: bold;
 | 
	
		
			
				|  |  | +        color: #000;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -      &::before {
 | 
	
		
			
				|  |  | -        display: inline-block;
 | 
	
		
			
				|  |  | -        width: 26px;
 | 
	
		
			
				|  |  | -        height: 26px;
 | 
	
		
			
				|  |  | -        margin-right: 8px;
 | 
	
		
			
				|  |  | -        font-weight: normal;
 | 
	
		
			
				|  |  | -        line-height: 26px;
 | 
	
		
			
				|  |  | -        color: #fff;
 | 
	
		
			
				|  |  | -        text-align: center;
 | 
	
		
			
				|  |  | -        content: attr(data-index);
 | 
	
		
			
				|  |  | -        background-color: #5498ff;
 | 
	
		
			
				|  |  | -        border-radius: 50%;
 | 
	
		
			
				|  |  | +        &::before {
 | 
	
		
			
				|  |  | +          display: inline-block;
 | 
	
		
			
				|  |  | +          width: 26px;
 | 
	
		
			
				|  |  | +          height: 26px;
 | 
	
		
			
				|  |  | +          margin-right: 8px;
 | 
	
		
			
				|  |  | +          font-weight: normal;
 | 
	
		
			
				|  |  | +          line-height: 26px;
 | 
	
		
			
				|  |  | +          color: #fff;
 | 
	
		
			
				|  |  | +          text-align: center;
 | 
	
		
			
				|  |  | +          content: attr(data-index);
 | 
	
		
			
				|  |  | +          background-color: #5498ff;
 | 
	
		
			
				|  |  | +          border-radius: 50%;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    &-date {
 | 
	
		
			
				|  |  | -      min-width: 242px;
 | 
	
		
			
				|  |  | -      height: 22px;
 | 
	
		
			
				|  |  | -      padding: 2px 12px;
 | 
	
		
			
				|  |  | -      margin-left: 34px;
 | 
	
		
			
				|  |  | -      background-color: #ebebeb;
 | 
	
		
			
				|  |  | -      border-radius: 20px;
 | 
	
		
			
				|  |  | +      &-date {
 | 
	
		
			
				|  |  | +        min-width: 242px;
 | 
	
		
			
				|  |  | +        height: 22px;
 | 
	
		
			
				|  |  | +        padding: 2px 12px;
 | 
	
		
			
				|  |  | +        margin-left: 34px;
 | 
	
		
			
				|  |  | +        background-color: #ebebeb;
 | 
	
		
			
				|  |  | +        border-radius: 20px;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 |