Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | <script setup lang="ts">
import { computed, onMounted, ref } from 'vue'
import { useI18n } from 'vue-i18n'
import ApiLoader from '@/components/common/ApiLoader.vue'
import PipelineCard from '@/components/feature/PipelineCard.vue'
import { fetchPipeline } from '@/api/modules/pipeline'
import type { PipelineItem } from '@/api/types'
import { filterPipeline, payoutMonths } from '@/utils/pipelineFilter'
const { t } = useI18n()
const loading = ref(true)
const error = ref<string | null>(null)
const items = ref<PipelineItem[]>([])
const policyQuery = ref('')
const selectedMonth = ref('')
const months = computed(() => payoutMonths(items.value))
const filtered = computed(() =>
filterPipeline(items.value, { query: policyQuery.value, month: selectedMonth.value })
)
async function load() {
loading.value = true
error.value = null
try {
items.value = await fetchPipeline()
// 重新拉取后原选中的月份可能已不存在,否则会停在一个永远为空的筛选条件上
if (selectedMonth.value && !months.value.includes(selectedMonth.value)) {
selectedMonth.value = ''
}
} catch (e) {
error.value = e instanceof Error ? e.message : 'error'
} finally {
loading.value = false
}
}
onMounted(load)
</script>
<template>
<div class="space-y-4">
<div class="rounded-2xl border border-amber-100 bg-amber-50 px-4 py-3 text-xs font-medium text-amber-700">{{ t('pipeline.adjustNote') }}</div>
<div class="grid grid-cols-2 gap-3">
<label class="block">
<span class="mb-1 block text-xs text-slate-500">{{ t('pipeline.filterPolicy') }}</span>
<input
v-model="policyQuery"
type="search"
:placeholder="t('pipeline.filterPolicyPlaceholder')"
class="w-full rounded-xl border border-silver-200 bg-white px-3 py-2 text-sm text-slate-900 outline-none transition-colors placeholder:text-silver-400 focus:border-brand-200"
>
</label>
<label class="block">
<span class="mb-1 block text-xs text-slate-500">{{ t('pipeline.filterMonth') }}</span>
<select
v-model="selectedMonth"
class="w-full rounded-xl border border-silver-200 bg-white px-3 py-2 text-sm text-slate-900 outline-none transition-colors focus:border-brand-200"
>
<option value="">{{ t('pipeline.allMonths') }}</option>
<option v-for="month in months" :key="month" :value="month">{{ month }}</option>
</select>
</label>
</div>
<ApiLoader :loading="loading" :error="error" :empty="!loading && !error && items.length === 0" @retry="load">
<div v-if="filtered.length" class="space-y-3">
<PipelineCard v-for="item in filtered" :key="item.id" :item="item" />
</div>
<div v-else class="py-10 text-center text-sm text-slate-400">{{ t('pipeline.noResult') }}</div>
</ApiLoader>
</div>
</template>
|