mirror of
https://github.com/stardrophere/InsightRadar.git
synced 2026-06-05 23:56:36 +08:00
optimize+注释
This commit is contained in:
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user