optimize+注释

This commit is contained in:
stardrophere
2026-03-13 23:48:49 +08:00
parent 6aee65af6c
commit da00ebb8f2
41 changed files with 874 additions and 174 deletions
+33 -76
View File
@@ -1,9 +1,11 @@
<!-- 事件追踪分析页关键词搜索时间热度图表关联事件列表 -->
<script setup lang="ts">
import { ref, computed } from 'vue'
import VueApexCharts from 'vue3-apexcharts'
import { searchEventsTimeline } from '@/api/events'
import type { SearchTimelineResponse } from '@/types/event'
import UnifiedEventCard from '@/components/UnifiedEventCard.vue'
import CustomSelect from '@/components/CustomSelect.vue'
const keyword = ref('')
const searchResult = ref<SearchTimelineResponse | null>(null)
@@ -12,6 +14,22 @@ const hours = ref(2)
const searchMode = ref<'exact' | 'semantic' | 'hybrid'>('hybrid')
const selectedTimeLabel = ref<string | null>(null)
const timeOptions = [
{ label: '最近 2 小时', value: 2 },
{ label: '最近 12 小时', value: 12 },
{ label: '最近 24 小时', value: 24 },
{ label: '最近 48 小时', value: 48 },
{ label: '最近 7 天', value: 168 },
{ label: '最近 15 天', value: 360 }
]
const modeOptions = [
{ label: '混合匹配', value: 'hybrid' },
{ label: '关键词匹配', value: 'exact' },
{ label: '语义匹配', value: 'semantic' }
]
// 根据选中的时间点筛选事件:点击图表节点时只显示该时间点关联的事件
const filteredEvents = computed(() => {
if (!searchResult.value) return []
if (!selectedTimeLabel.value) return searchResult.value.events
@@ -51,6 +69,7 @@ const chartOptions = ref({
easing: 'easeinout',
speed: 800,
},
// 点击图表数据点:切换选中时间,再次点击则取消筛选
events: {
markerClick: function(event: any, chartContext: any, { dataPointIndex }: any) {
if (searchResult.value && searchResult.value.timeline[dataPointIndex]) {
@@ -188,27 +207,16 @@ async function handleSearch() {
class="search-input"
/>
</div>
<div class="time-select-wrapper">
<i class="fa-regular fa-clock select-icon"></i>
<select v-model="hours" class="time-select">
<option :value="2">最近 2 小时</option>
<option :value="12">最近 12 小时</option>
<option :value="24">最近 24 小时</option>
<option :value="48">最近 48 小时</option>
<option :value="168">最近 7 </option>
<option :value="360">最近 15 </option>
</select>
<i class="fa-solid fa-chevron-down select-arrow"></i>
</div>
<div class="time-select-wrapper">
<i class="fa-solid fa-filter select-icon"></i>
<select v-model="searchMode" class="time-select">
<option value="hybrid">混合匹配</option>
<option value="exact">关键词匹配</option>
<option value="semantic">语义匹配</option>
</select>
<i class="fa-solid fa-chevron-down select-arrow"></i>
</div>
<CustomSelect
v-model="hours"
:options="timeOptions"
icon="fa-regular fa-clock"
/>
<CustomSelect
v-model="searchMode"
:options="modeOptions"
icon="fa-solid fa-filter"
/>
<button class="btn btn-primary" @click="handleSearch" :disabled="loading || !keyword.trim()">
<i class="fa-solid fa-bolt" v-if="!loading"></i>
<i class="fa-solid fa-spinner fa-spin" v-else></i>
@@ -359,6 +367,8 @@ async function handleSearch() {
display: flex;
gap: 24px;
align-items: stretch;
position: relative;
z-index: 10; /* 确保搜索框及下拉选择框显示在下方图表之上 */
}
.search-box {
@@ -470,61 +480,6 @@ async function handleSearch() {
background-color: var(--bg-surface);
}
.time-select-wrapper {
position: relative;
display: flex;
align-items: center;
min-width: 160px;
}
.select-icon {
position: absolute;
left: 14px;
color: var(--text-placeholder);
font-size: 15px;
pointer-events: none;
z-index: 1;
}
.select-arrow {
position: absolute;
right: 14px;
color: var(--text-placeholder);
font-size: 12px;
pointer-events: none;
}
.time-select {
width: 100%;
padding: 14px 36px 14px 40px;
border: 1px solid var(--border-subtle);
border-radius: var(--radius-lg);
background-color: var(--bg-input);
color: var(--text-primary);
font-size: 14px;
font-weight: 500;
cursor: pointer;
transition: all 0.2s;
appearance: none;
-webkit-appearance: none;
}
.time-select:focus {
outline: none;
border-color: var(--brand-primary);
box-shadow: 0 0 0 3px var(--brand-primary-alpha);
background-color: var(--bg-surface);
}
.time-select-wrapper:hover .time-select {
border-color: var(--brand-primary);
}
.time-select-wrapper:hover .select-icon,
.time-select-wrapper:hover .select-arrow {
color: var(--brand-primary);
}
.btn-primary {
display: inline-flex;
align-items: center;
@@ -562,6 +517,8 @@ async function handleSearch() {
flex-direction: column;
gap: 24px;
animation: fadeIn 0.4s ease-out;
position: relative;
z-index: 1; /* 低于 top-panels,避免图表覆盖搜索框下拉 */
}
.section-header {