<script setup lang="ts">
|
import type { StepProgress } from '../domain/types';
|
|
import { ArrowLeftOutlined, CheckCircleFilled, ClockCircleOutlined, ExclamationCircleFilled, SearchOutlined } from '@ant-design/icons-vue';
|
import { computed, ref } from 'vue';
|
|
import { STEP_PROGRESS_LABELS } from '../domain/types';
|
|
const props = defineProps<{
|
currentStepId: null | string;
|
progress: StepProgress[];
|
}>();
|
const emit = defineEmits<{ close: []; select: [stepId: string] }>();
|
|
const search = ref('');
|
const items = computed(() => {
|
const query = search.value.trim().toLocaleLowerCase();
|
return props.progress
|
.filter(({ step }) => !query || step.name.toLocaleLowerCase().includes(query))
|
.sort((left, right) => left.step.order - right.step.order || left.step.id.localeCompare(right.step.id));
|
});
|
|
const counts = computed(() => ({
|
complete: props.progress.filter((item) => item.status === 'complete').length,
|
problem: props.progress.filter((item) => item.status === 'problem').length,
|
total: props.progress.length,
|
}));
|
</script>
|
|
<template>
|
<section class="step-directory" aria-label="填写目录">
|
<div class="directory-summary">
|
<a-tooltip title="返回当前步骤">
|
<a-button type="text" size="small" aria-label="返回当前步骤" @click="emit('close')">
|
<template #icon><ArrowLeftOutlined /></template>
|
</a-button>
|
</a-tooltip>
|
<strong>填写目录</strong>
|
<span>{{ counts.complete }}/{{ counts.total }} 已完整</span>
|
<span v-if="counts.problem" class="directory-problem">{{ counts.problem }} 个问题</span>
|
</div>
|
<a-input v-model:value="search" allow-clear aria-label="搜索步骤" placeholder="搜索步骤">
|
<template #prefix><SearchOutlined /></template>
|
</a-input>
|
|
<a-empty v-if="!items.length" :image="false" description="没有匹配的步骤" />
|
<div v-else class="directory-steps">
|
<button
|
v-for="item in items"
|
:key="item.step.id"
|
type="button"
|
class="directory-step"
|
:class="{ 'directory-step-current': item.step.id === currentStepId }"
|
:data-step-id="item.step.id"
|
@click="emit('select', item.step.id)">
|
<CheckCircleFilled v-if="item.status === 'complete'" class="status-complete" />
|
<ExclamationCircleFilled v-else-if="item.status === 'problem'" class="status-problem" />
|
<ClockCircleOutlined v-else class="status-progress" />
|
<span class="directory-step-name">{{ item.step.name }}</span>
|
<a-tag v-if="item.step.id === currentStepId" color="blue">当前</a-tag>
|
<span class="directory-step-status">{{ STEP_PROGRESS_LABELS[item.status] }}</span>
|
</button>
|
</div>
|
</section>
|
</template>
|