123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- <template>
- <nav class="left-sidebar">
- <template v-for="{ type, name } in taskTypeArray">
- <div
- v-if="[TASK_EXPLAIN, taskType].includes(type)"
- :key="type"
- :class="[`${type}-task`, curTaskType === type ? 'active' : '']"
- @click="changeTaskType(type)"
- >
- <span>{{ name }}</span>
- <span v-if="type !== TASK_EXPLAIN">
- {{ taskNumAndSubtaskNum(type) }}
- </span>
- </div>
- <!-- 导航栏任务列表 -->
- <div v-if="[taskType].includes(type)" :key="`${type}-task`" class="task-list">
- <template v-for="({ name: taskName, child_task_list }, index) in taskList">
- <div
- :key="`sidebar-task-${index}`"
- :class="['task-list-item', curSelectMark === `${type}-${index}` ? 'active' : '']"
- >
- <span class="task-index" @click="setSelectMark(type, index)">{{ index + 1 }}.</span>
- <span class="task-name" @click="setSelectMark(type, index)">{{ taskName }}</span>
- </div>
- <div
- v-for="({ name: subtaskName }, subtask_index) in child_task_list"
- :key="`sidebar-subtask-${index}-${subtask_index}`"
- :class="['task-list-subtask', curSelectMark === `${type}-${index}-${subtask_index}` ? 'active' : '']"
- >
- <span class="task-index" @click="setSelectMark(type, index, subtask_index)">
- {{ `${index + 1}.${subtask_index + 1}` }}
- </span>
- <span class="task-name" @click="setSelectMark(type, index, subtask_index)">{{ subtaskName }}</span>
- </div>
- </template>
- </div>
- </template>
- </nav>
- </template>
- <script>
- export default {
- name: 'LeftSidebar'
- };
- </script>
- <script setup>
- import { ref, nextTick, inject } from 'vue';
- import { TASK_EXPLAIN, taskTypeArray } from '../data/TaskType';
- defineProps({
- curTaskType: {
- type: String,
- required: true
- },
- changeTaskType: {
- type: Function,
- required: true
- },
- taskType: {
- type: String,
- required: true
- }
- });
- /**
- * 处理选中任务导航事件
- */
- let curSelectMark = ref(''); // 当前选中任务标记
- function setSelectMark(type, index, subtask_index = -1) {
- curSelectMark.value = `${type}-${index}${subtask_index >= 0 ? `-${subtask_index}` : ''}`;
- nextTick(() => {
- document.querySelector(`.${curSelectMark.value}`)?.scrollIntoView({ behavior: 'smooth' });
- });
- }
- let curTaskTypeObj = inject('curTaskTypeObj');
- let taskList = inject('taskList');
- // 任务数量和子任务数量显示名
- function taskNumAndSubtaskNum(taskType) {
- if (!taskList.value) return;
- return taskList.value.length > 0
- ? `${taskList.value.length}/${taskList.value.reduce((pre, { child_task_list }) => pre + child_task_list.length, 0)}`
- : 0;
- }
- </script>
- <style lang="scss" scoped>
- $basic-background-color: #f7f7f7;
- .left-sidebar {
- width: 155px;
- padding: 16px 0 16px 8px;
- overflow: auto;
- font-size: 14px;
- background-color: $basic-background-color;
- border-right: 1px solid $border-color;
- .explain-task {
- width: 138px;
- height: 28px;
- padding: 2px 16px;
- margin-bottom: 14px;
- font-weight: bold;
- line-height: 22px;
- text-align: center;
- cursor: pointer;
- background-color: #fff;
- border: 1px solid $border-color;
- border-radius: 20px;
- &.active {
- color: #fff;
- background-color: v-bind('curTaskTypeObj.active_color');
- }
- }
- .pre-task,
- .mid-task,
- .after-task {
- display: flex;
- justify-content: space-between;
- width: 146px;
- height: 28px;
- padding: 2px 8px;
- margin-top: 8px;
- font-weight: bold;
- line-height: 22px;
- color: #fff;
- text-transform: uppercase;
- cursor: pointer;
- background-color: #cfcfcf;
- border: 1px solid $border-color;
- border-radius: 4px 0 0 4px;
- &.active {
- background-color: v-bind('curTaskTypeObj.active_color');
- }
- }
- .task-list {
- margin: 6px 0 0 8px;
- border-left: 1px solid #d9d9d9;
- &-item,
- %item {
- display: flex;
- column-gap: 8px;
- padding: 3px 16px;
- .task-index {
- cursor: pointer;
- }
- .task-name {
- word-break: break-all;
- cursor: pointer;
- }
- &.active {
- color: #0052d9;
- box-shadow: -1px 0 #0052d9;
- }
- }
- &-subtask {
- @extend %item;
- .task-index {
- margin-left: 16px;
- cursor: pointer;
- }
- }
- }
- }
- </style>
|