59 lines
2.4 KiB
Vue
59 lines
2.4 KiB
Vue
<template>
|
|
<div class="clue-board">
|
|
<div class="board-header">
|
|
<h3>📋 线索本</h3>
|
|
<span class="clue-count">{{ unlockedCount }}/{{ clues.length }}</span>
|
|
</div>
|
|
<div class="board-body">
|
|
<div v-if="clues.length === 0" class="board-empty">暂无线索</div>
|
|
<div
|
|
v-for="clue in clues"
|
|
:key="clue.id"
|
|
class="clue-item"
|
|
:class="{ unlocked: clue.is_unlocked }"
|
|
>
|
|
<div class="clue-header">
|
|
<span class="clue-type">{{ TYPE_ICONS[clue.clue_type] || '📌' }}</span>
|
|
<span class="clue-name">{{ clue.name }}</span>
|
|
<span v-if="!clue.is_unlocked" class="clue-hidden">🔒</span>
|
|
<span v-else class="clue-unlocked">🔓</span>
|
|
</div>
|
|
<div v-if="clue.is_unlocked" class="clue-desc">{{ clue.content }}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { computed } from 'vue'
|
|
import type { Clue } from '../../stores/clueStore'
|
|
|
|
const props = defineProps<{
|
|
clues: Clue[]
|
|
}>()
|
|
|
|
const TYPE_ICONS: Record<string, string> = {
|
|
physical: '🔧',
|
|
testimony: '💬',
|
|
motive: '💰',
|
|
alibi: '⏰',
|
|
forensic: '🔬',
|
|
}
|
|
|
|
const unlockedCount = computed(() => props.clues.filter((c) => c.is_unlocked).length)
|
|
</script>
|
|
|
|
<style scoped>
|
|
.clue-board { display: flex; flex-direction: column; height: 100%; }
|
|
.board-header { display: flex; justify-content: space-between; align-items: center; padding: 0.75rem 1rem; border-bottom: 1px solid var(--border-color); }
|
|
.board-header h3 { font-size: 0.9rem; font-weight: 600; }
|
|
.clue-count { font-size: 0.7rem; color: var(--text-secondary); }
|
|
.board-body { flex: 1; overflow-y: auto; padding: 0.5rem; }
|
|
.board-empty { display: flex; align-items: center; justify-content: center; height: 80px; color: var(--text-muted); font-size: 0.8rem; }
|
|
.clue-item { padding: 0.5rem; margin-bottom: 0.5rem; border-radius: var(--border-radius); background: var(--bg-card); border: 1px solid var(--border-color); transition: all 0.3s ease; }
|
|
.clue-item.unlocked { border-color: var(--accent-success); background: rgba(107, 203, 119, 0.05); }
|
|
.clue-header { display: flex; align-items: center; gap: 0.5rem; }
|
|
.clue-name { flex: 1; font-size: 0.85rem; font-weight: 500; }
|
|
.clue-desc { margin-top: 0.4rem; padding-top: 0.4rem; border-top: 1px solid var(--border-color); font-size: 0.8rem; color: var(--text-secondary); line-height: 1.5; }
|
|
</style>
|