mirror of
https://github.com/hellodigua/ChatLab.git
synced 2026-05-12 17:21:01 +08:00
feat: 优化身份卡片样式
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
<script setup lang="ts">
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'openIncrementalImport'): void
|
||||
(e: 'openSessionIndex'): void
|
||||
(e: 'openMessageExport'): void
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col gap-2">
|
||||
<span class="mb-1 px-1 text-[10px] font-bold uppercase tracking-widest text-gray-400 dark:text-gray-500">
|
||||
{{ t('analysis.overview.tools') }}
|
||||
</span>
|
||||
<button
|
||||
class="group flex w-full items-center justify-between rounded-lg border border-gray-200 bg-white px-3.5 py-2.5 text-sm font-medium text-gray-700 shadow-[0_1px_2px_rgba(0,0,0,0.02)] transition-all hover:border-gray-300 hover:bg-gray-50 hover:text-gray-900 dark:border-white/10 dark:bg-[#161616] dark:text-gray-300 dark:hover:border-white/20 dark:hover:bg-[#1f1f1f] dark:hover:text-white"
|
||||
@click="emit('openIncrementalImport')"
|
||||
>
|
||||
<div class="flex items-center gap-2.5">
|
||||
<UIcon
|
||||
name="i-heroicons-plus-circle"
|
||||
class="h-4 w-4 text-gray-400 transition-colors group-hover:text-pink-500 dark:text-gray-500"
|
||||
/>
|
||||
{{ t('analysis.tooltip.incrementalImport') }}
|
||||
</div>
|
||||
<UIcon
|
||||
name="i-heroicons-arrow-right-circle"
|
||||
class="h-4 w-4 text-gray-300 opacity-0 transition-all group-hover:translate-x-0.5 group-hover:opacity-100 dark:text-gray-600"
|
||||
/>
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="group flex w-full items-center justify-between rounded-lg border border-gray-200 bg-white px-3.5 py-2.5 text-sm font-medium text-gray-700 shadow-[0_1px_2px_rgba(0,0,0,0.02)] transition-all hover:border-gray-300 hover:bg-gray-50 hover:text-gray-900 dark:border-white/10 dark:bg-[#161616] dark:text-gray-300 dark:hover:border-white/20 dark:hover:bg-[#1f1f1f] dark:hover:text-white"
|
||||
@click="emit('openSessionIndex')"
|
||||
>
|
||||
<div class="flex items-center gap-2.5">
|
||||
<UIcon
|
||||
name="i-heroicons-clock"
|
||||
class="h-4 w-4 text-gray-400 transition-colors group-hover:text-blue-500 dark:text-gray-500"
|
||||
/>
|
||||
{{ t('analysis.tooltip.sessionIndex') }}
|
||||
</div>
|
||||
<UIcon
|
||||
name="i-heroicons-arrow-right-circle"
|
||||
class="h-4 w-4 text-gray-300 opacity-0 transition-all group-hover:translate-x-0.5 group-hover:opacity-100 dark:text-gray-600"
|
||||
/>
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="group flex w-full items-center justify-between rounded-lg border border-gray-200 bg-white px-3.5 py-2.5 text-sm font-medium text-gray-700 shadow-[0_1px_2px_rgba(0,0,0,0.02)] transition-all hover:border-gray-300 hover:bg-gray-50 hover:text-gray-900 dark:border-white/10 dark:bg-[#161616] dark:text-gray-300 dark:hover:border-white/20 dark:hover:bg-[#1f1f1f] dark:hover:text-white"
|
||||
@click="emit('openMessageExport')"
|
||||
>
|
||||
<div class="flex items-center gap-2.5">
|
||||
<UIcon
|
||||
name="i-heroicons-document-arrow-down"
|
||||
class="h-4 w-4 text-gray-400 transition-colors group-hover:text-green-500 dark:text-gray-500"
|
||||
/>
|
||||
{{ t('analysis.messageExport.title') }}
|
||||
</div>
|
||||
<UIcon
|
||||
name="i-heroicons-arrow-right-circle"
|
||||
class="h-4 w-4 text-gray-300 opacity-0 transition-all group-hover:translate-x-0.5 group-hover:opacity-100 dark:text-gray-600"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,81 +1,305 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { computed, ref, watch, onMounted, onUnmounted } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useDark } from '@vueuse/core'
|
||||
import * as echarts from 'echarts/core'
|
||||
import { HeatmapChart } from 'echarts/charts'
|
||||
import { CalendarComponent, TooltipComponent, VisualMapComponent } from 'echarts/components'
|
||||
import { CanvasRenderer } from 'echarts/renderers'
|
||||
import type { EChartsOption } from 'echarts'
|
||||
import type { AnalysisSession } from '@/types/base'
|
||||
import type { DailyActivity } from '@/types/analysis'
|
||||
import { formatDateRange } from '@/utils'
|
||||
|
||||
const { t } = useI18n()
|
||||
echarts.use([HeatmapChart, CalendarComponent, TooltipComponent, VisualMapComponent, CanvasRenderer])
|
||||
|
||||
const { t, locale } = useI18n()
|
||||
const isDark = useDark()
|
||||
|
||||
const props = defineProps<{
|
||||
session: AnalysisSession
|
||||
dailyActivity: DailyActivity[]
|
||||
totalDurationDays: number
|
||||
totalDailyAvgMessages: number
|
||||
timeRange: { start: number; end: number } | null
|
||||
}>()
|
||||
|
||||
// 聊天记录起止时间(完整范围)
|
||||
const chartRef = ref<HTMLElement | null>(null)
|
||||
let chartInstance: echarts.ECharts | null = null
|
||||
|
||||
const fullTimeRangeText = computed(() => {
|
||||
if (!props.timeRange) return ''
|
||||
return formatDateRange(props.timeRange.start, props.timeRange.end, 'YYYY/MM/DD')
|
||||
})
|
||||
|
||||
// 滚动 12 个月日期范围(与 GitHub 贡献图一致)
|
||||
const calendarRange = computed(() => {
|
||||
const today = new Date()
|
||||
const yearAgo = new Date(today)
|
||||
yearAgo.setFullYear(yearAgo.getFullYear() - 1)
|
||||
yearAgo.setDate(yearAgo.getDate() + 1)
|
||||
const fmt = (d: Date) => d.toISOString().slice(0, 10)
|
||||
return [fmt(yearAgo), fmt(today)]
|
||||
})
|
||||
|
||||
// 转换 DailyActivity 为 ECharts 日历数据
|
||||
const chartData = computed(() => {
|
||||
const [startStr, endStr] = calendarRange.value
|
||||
const startDate = new Date(startStr + 'T00:00:00Z')
|
||||
const endDate = new Date(endStr + 'T00:00:00Z')
|
||||
|
||||
const dict = new Map<string, number>()
|
||||
props.dailyActivity
|
||||
.filter((d) => d.date >= startStr && d.date <= endStr)
|
||||
.forEach((d) => dict.set(d.date, d.messageCount))
|
||||
|
||||
const res: any[] = []
|
||||
const curr = new Date(startDate)
|
||||
while (curr <= endDate) {
|
||||
const dStr = curr.toISOString().slice(0, 10)
|
||||
const val = dict.get(dStr) || 0
|
||||
res.push({
|
||||
value: [dStr, val],
|
||||
itemStyle: val === 0 ? { color: emptyColor.value } : undefined,
|
||||
})
|
||||
curr.setUTCDate(curr.getUTCDate() + 1)
|
||||
}
|
||||
return res
|
||||
})
|
||||
|
||||
const maxValue = computed(() => {
|
||||
if (props.dailyActivity.length === 0) return 10
|
||||
return Math.max(...props.dailyActivity.map((d) => d.messageCount), 1)
|
||||
})
|
||||
|
||||
const themeColors = {
|
||||
light: ['#fce4ec', '#f8a4b8', '#f06292', '#e91e63'],
|
||||
dark: ['#3d1f24', '#6b2f3a', '#a34557', '#ee4567'],
|
||||
}
|
||||
|
||||
// GitHub 风格:标准的空白格底色
|
||||
const emptyColor = computed(() => (isDark.value ? '#161b22' : '#ebedf0'))
|
||||
|
||||
const chartOption = computed<EChartsOption>(() => ({
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: (params: any) => {
|
||||
const date = params.value[0]
|
||||
const value = params.value[1]
|
||||
return `${date}<br/>${t('views.message.calendarTooltipMessages')}: ${value}`
|
||||
},
|
||||
},
|
||||
visualMap: {
|
||||
min: 1,
|
||||
max: maxValue.value,
|
||||
calculable: false,
|
||||
orient: 'horizontal',
|
||||
left: 'center',
|
||||
bottom: 0,
|
||||
itemWidth: 10,
|
||||
itemHeight: 80,
|
||||
text: [`${maxValue.value}`, '1'],
|
||||
inRange: {
|
||||
color: isDark.value ? themeColors.dark : themeColors.light,
|
||||
},
|
||||
textStyle: {
|
||||
color: isDark.value ? '#8b949e' : '#6b7280',
|
||||
fontSize: 10,
|
||||
},
|
||||
show: true,
|
||||
},
|
||||
calendar: {
|
||||
top: 20,
|
||||
left: 30,
|
||||
cellSize: [13, 13],
|
||||
range: calendarRange.value,
|
||||
itemStyle: {
|
||||
borderWidth: 0,
|
||||
color: 'transparent',
|
||||
},
|
||||
yearLabel: { show: false },
|
||||
monthLabel: {
|
||||
show: true,
|
||||
color: isDark.value ? '#8b949e' : '#6b7280',
|
||||
fontSize: 10,
|
||||
nameMap: [
|
||||
t('common.month.jan'),
|
||||
t('common.month.feb'),
|
||||
t('common.month.mar'),
|
||||
t('common.month.apr'),
|
||||
t('common.month.may'),
|
||||
t('common.month.jun'),
|
||||
t('common.month.jul'),
|
||||
t('common.month.aug'),
|
||||
t('common.month.sep'),
|
||||
t('common.month.oct'),
|
||||
t('common.month.nov'),
|
||||
t('common.month.dec'),
|
||||
],
|
||||
},
|
||||
dayLabel: {
|
||||
show: true,
|
||||
firstDay: 1,
|
||||
color: isDark.value ? '#8b949e' : '#9ca3af',
|
||||
fontSize: 10,
|
||||
nameMap: [
|
||||
t('common.weekday.sun'),
|
||||
t('common.weekday.mon'),
|
||||
t('common.weekday.tue'),
|
||||
t('common.weekday.wed'),
|
||||
t('common.weekday.thu'),
|
||||
t('common.weekday.fri'),
|
||||
t('common.weekday.sat'),
|
||||
],
|
||||
},
|
||||
splitLine: { show: false },
|
||||
},
|
||||
series: [
|
||||
{
|
||||
type: 'heatmap',
|
||||
coordinateSystem: 'calendar',
|
||||
data: chartData.value,
|
||||
itemStyle: {
|
||||
borderRadius: 3,
|
||||
borderWidth: 2,
|
||||
borderColor: isDark.value ? '#0f0f0f' : '#ffffff',
|
||||
},
|
||||
},
|
||||
],
|
||||
}))
|
||||
|
||||
function initChart() {
|
||||
if (!chartRef.value) return
|
||||
chartInstance = echarts.init(chartRef.value, undefined, { renderer: 'canvas' })
|
||||
chartInstance.setOption(chartOption.value)
|
||||
}
|
||||
|
||||
function updateChart() {
|
||||
if (!chartInstance) return
|
||||
chartInstance.setOption(chartOption.value, { notMerge: true })
|
||||
}
|
||||
|
||||
function handleResize() {
|
||||
chartInstance?.resize()
|
||||
}
|
||||
|
||||
watch([() => props.dailyActivity, locale], () => updateChart())
|
||||
|
||||
watch(isDark, () => {
|
||||
chartInstance?.dispose()
|
||||
initChart()
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
initChart()
|
||||
window.addEventListener('resize', handleResize)
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('resize', handleResize)
|
||||
chartInstance?.dispose()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="relative overflow-hidden rounded-3xl bg-gradient-to-br from-pink-500 to-pink-600 p-8 shadow-sm ring-1 ring-pink-600 dark:bg-gray-800/50 dark:from-transparent dark:to-transparent dark:ring-gray-800"
|
||||
class="relative overflow-hidden rounded-[24px] border border-gray-200/60 bg-white p-8 shadow-sm dark:border-white/5 dark:bg-[#0f0f0f]"
|
||||
>
|
||||
<div class="relative flex gap-8">
|
||||
<div class="flex-1">
|
||||
<div>
|
||||
<div class="flex items-center gap-3">
|
||||
<h2 class="text-3xl font-black tracking-tight text-white">{{ session.name }}</h2>
|
||||
<span
|
||||
class="rounded-full bg-white px-3 py-1 text-xs font-medium text-pink-600 dark:bg-pink-500/10 dark:text-pink-400"
|
||||
>
|
||||
{{ session.platform.toUpperCase() }}
|
||||
</span>
|
||||
<!-- 左侧:身份信息 + 日历 -->
|
||||
<div class="min-w-0 flex-1 flex flex-col">
|
||||
<!-- 上方:身份信息 + 统计数据 -->
|
||||
<div class="flex flex-wrap items-center justify-between gap-8 pb-4">
|
||||
<!-- 身份信息 -->
|
||||
<div>
|
||||
<div class="flex flex-wrap items-center gap-3">
|
||||
<h2 class="text-3xl font-bold tracking-tight text-gray-900 dark:text-gray-100">
|
||||
{{ session.name }}
|
||||
</h2>
|
||||
<div
|
||||
class="flex items-center gap-1.5 rounded-full bg-pink-50 px-2.5 py-1 text-xs font-semibold text-pink-600 ring-1 ring-inset ring-pink-500/20 dark:bg-pink-500/10 dark:text-pink-400 dark:ring-pink-500/20"
|
||||
>
|
||||
<span class="h-1.5 w-1.5 rounded-full bg-pink-500"></span>
|
||||
<span>{{ session.platform.toUpperCase() }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 flex flex-col gap-2 text-sm font-medium text-gray-500 dark:text-gray-400">
|
||||
<div class="flex items-center gap-2">
|
||||
<div
|
||||
class="flex h-6 w-6 shrink-0 items-center justify-center rounded bg-gray-100 text-gray-500 dark:bg-gray-800 dark:text-gray-400"
|
||||
>
|
||||
<UIcon v-if="session.type === 'group'" name="i-heroicons-user-group" class="h-3.5 w-3.5" />
|
||||
<UIcon v-else name="i-heroicons-user" class="h-3.5 w-3.5" />
|
||||
</div>
|
||||
<span class="truncate">
|
||||
{{
|
||||
session.type === 'private'
|
||||
? t('analysis.overview.identity.privateChat')
|
||||
: t('analysis.overview.identity.groupChat')
|
||||
}}
|
||||
· {{ t('analysis.overview.identity.analysisReport') }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div v-if="fullTimeRangeText" class="flex items-center gap-2">
|
||||
<div class="flex h-6 w-6 shrink-0 items-center justify-center">
|
||||
<UIcon name="i-heroicons-calendar" class="h-4 w-4 opacity-70" />
|
||||
</div>
|
||||
<span class="truncate font-mono text-xs opacity-90">{{ fullTimeRangeText }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 紧凑统计数据 (贴靠右侧) -->
|
||||
<div class="flex shrink-0 gap-6">
|
||||
<div class="flex flex-col gap-1 text-center">
|
||||
<span class="text-2xl font-black font-mono tracking-tight text-gray-900 dark:text-white">
|
||||
{{ session.messageCount.toLocaleString() }}
|
||||
</span>
|
||||
<span class="text-xs font-medium text-gray-500 dark:text-gray-400">
|
||||
{{ t('analysis.overview.identity.totalMessages') }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col gap-1 text-center">
|
||||
<span class="text-2xl font-black font-mono tracking-tight text-gray-900 dark:text-white">
|
||||
{{ totalDurationDays.toLocaleString() }}
|
||||
</span>
|
||||
<span class="text-xs font-medium text-gray-500 dark:text-gray-400">
|
||||
{{ t('analysis.overview.identity.durationDays') }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col gap-1 text-center">
|
||||
<span class="text-2xl font-black font-mono tracking-tight text-gray-900 dark:text-white">
|
||||
{{ totalDailyAvgMessages.toLocaleString() }}
|
||||
</span>
|
||||
<span class="text-xs font-medium text-gray-500 dark:text-gray-400">
|
||||
{{ t('analysis.overview.identity.dailyAvgMessages') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<p class="mt-2 text-lg font-medium text-pink-100 dark:text-gray-400">
|
||||
{{
|
||||
session.type === 'private'
|
||||
? t('analysis.overview.identity.privateChat')
|
||||
: t('analysis.overview.identity.groupChat')
|
||||
}}
|
||||
·
|
||||
<span class="opacity-80">{{ t('analysis.overview.identity.analysisReport') }}</span>
|
||||
</p>
|
||||
<!-- 聊天记录起止时间 -->
|
||||
<p v-if="fullTimeRangeText" class="mt-2 text-sm font-medium text-pink-100/90 dark:text-gray-400">
|
||||
{{ fullTimeRangeText }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="mt-8 grid grid-cols-3 gap-6">
|
||||
<div class="rounded-2xl bg-white/10 px-6 py-4 dark:bg-gray-800">
|
||||
<p class="text-3xl font-black tracking-tight text-white">
|
||||
{{ session.messageCount.toLocaleString() }}
|
||||
</p>
|
||||
<p class="mt-1 text-sm font-medium text-pink-100 dark:text-gray-400">
|
||||
{{ t('analysis.overview.identity.totalMessages') }}
|
||||
</p>
|
||||
<!-- 热力图区域 -->
|
||||
<div class="mt-8 pt-2">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<span class="text-[10px] font-bold uppercase tracking-widest text-gray-400 dark:text-gray-500">
|
||||
Activity Heatmap
|
||||
</span>
|
||||
</div>
|
||||
<div class="rounded-2xl bg-white/10 px-6 py-4 dark:bg-gray-800">
|
||||
<p class="text-3xl font-black tracking-tight text-white">{{ totalDurationDays }}</p>
|
||||
<p class="mt-1 text-sm font-medium text-pink-100 dark:text-gray-400">
|
||||
{{ t('analysis.overview.identity.durationDays') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="rounded-2xl bg-white/10 px-6 py-4 dark:bg-gray-800">
|
||||
<p class="text-3xl font-black tracking-tight text-white">{{ totalDailyAvgMessages }}</p>
|
||||
<p class="mt-1 text-sm font-medium text-pink-100 dark:text-gray-400">
|
||||
{{ t('analysis.overview.identity.dailyAvgMessages') }}
|
||||
</p>
|
||||
<div class="overflow-x-auto overflow-y-hidden scrollbar-hide py-1">
|
||||
<div ref="chartRef" class="h-[140px] min-w-[700px] lg:w-full" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 右侧工具区插槽 -->
|
||||
<div v-if="$slots.tools" class="flex flex-none flex-col justify-end">
|
||||
<div
|
||||
v-if="$slots.tools"
|
||||
class="flex flex-none flex-col justify-end w-56 border-l border-gray-100 pl-8 dark:border-white/5"
|
||||
>
|
||||
<slot name="tools" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -11,6 +11,7 @@ import { useOverviewStatistics } from '@/composables/analysis/useOverviewStatist
|
||||
import { useDailyTrend } from '@/composables/analysis/useDailyTrend'
|
||||
import OverviewStatCards from '@/components/analysis/Overview/OverviewStatCards.vue'
|
||||
import OverviewIdentityCard from '@/components/analysis/Overview/OverviewIdentityCard.vue'
|
||||
import OverviewActionTools from '@/components/analysis/Overview/OverviewActionTools.vue'
|
||||
import DailyTrendCard from '@/components/analysis/Overview/DailyTrendCard.vue'
|
||||
|
||||
const { t } = useI18n()
|
||||
@@ -108,41 +109,21 @@ watch(
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="main-content space-y-6 p-6">
|
||||
<div class="main-content mx-auto max-w-7xl space-y-6 p-4 sm:p-6">
|
||||
<!-- 群聊身份卡 -->
|
||||
<OverviewIdentityCard
|
||||
:session="session"
|
||||
:daily-activity="dailyActivity"
|
||||
:total-duration-days="totalDurationDays"
|
||||
:total-daily-avg-messages="totalDailyAvgMessages"
|
||||
:time-range="timeRange"
|
||||
>
|
||||
<template #tools>
|
||||
<div class="flex flex-col gap-2">
|
||||
<span class="mb-0.5 text-xs font-semibold tracking-wide text-white/60 dark:text-gray-500">
|
||||
{{ t('analysis.overview.tools') }}
|
||||
</span>
|
||||
<button
|
||||
class="flex items-center gap-2 rounded-xl bg-white/10 px-4 py-2.5 text-sm font-medium text-white transition-colors hover:bg-white/20 dark:bg-gray-700 dark:hover:bg-gray-600"
|
||||
@click="emit('openIncrementalImport')"
|
||||
>
|
||||
<UIcon name="i-heroicons-plus-circle" class="h-4 w-4 shrink-0" />
|
||||
{{ t('analysis.tooltip.incrementalImport') }}
|
||||
</button>
|
||||
<button
|
||||
class="flex items-center gap-2 rounded-xl bg-white/10 px-4 py-2.5 text-sm font-medium text-white transition-colors hover:bg-white/20 dark:bg-gray-700 dark:hover:bg-gray-600"
|
||||
@click="emit('openSessionIndex')"
|
||||
>
|
||||
<UIcon name="i-heroicons-clock" class="h-4 w-4 shrink-0" />
|
||||
{{ t('analysis.tooltip.sessionIndex') }}
|
||||
</button>
|
||||
<button
|
||||
class="flex items-center gap-2 rounded-xl bg-white/10 px-4 py-2.5 text-sm font-medium text-white transition-colors hover:bg-white/20 dark:bg-gray-700 dark:hover:bg-gray-600"
|
||||
@click="emit('openMessageExport')"
|
||||
>
|
||||
<UIcon name="i-heroicons-document-arrow-down" class="h-4 w-4 shrink-0" />
|
||||
{{ t('analysis.messageExport.title') }}
|
||||
</button>
|
||||
</div>
|
||||
<OverviewActionTools
|
||||
@open-incremental-import="emit('openIncrementalImport')"
|
||||
@open-session-index="emit('openSessionIndex')"
|
||||
@open-message-export="emit('openMessageExport')"
|
||||
/>
|
||||
</template>
|
||||
</OverviewIdentityCard>
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import { useOverviewStatistics } from '@/composables/analysis/useOverviewStatist
|
||||
import { useDailyTrend } from '@/composables/analysis/useDailyTrend'
|
||||
import OverviewStatCards from '@/components/analysis/Overview/OverviewStatCards.vue'
|
||||
import OverviewIdentityCard from '@/components/analysis/Overview/OverviewIdentityCard.vue'
|
||||
import OverviewActionTools from '@/components/analysis/Overview/OverviewActionTools.vue'
|
||||
import DailyTrendCard from '@/components/analysis/Overview/DailyTrendCard.vue'
|
||||
|
||||
const { t } = useI18n()
|
||||
@@ -124,41 +125,21 @@ watch(
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="main-content space-y-6 p-6">
|
||||
<div class="main-content mx-auto max-w-7xl space-y-6 p-4 sm:p-6">
|
||||
<!-- 私聊身份卡 -->
|
||||
<OverviewIdentityCard
|
||||
:session="session"
|
||||
:daily-activity="dailyActivity"
|
||||
:total-duration-days="totalDurationDays"
|
||||
:total-daily-avg-messages="totalDailyAvgMessages"
|
||||
:time-range="timeRange"
|
||||
>
|
||||
<template #tools>
|
||||
<div class="flex flex-col gap-2">
|
||||
<span class="mb-0.5 text-xs font-semibold tracking-wide text-white/60 dark:text-gray-500">
|
||||
{{ t('analysis.overview.tools') }}
|
||||
</span>
|
||||
<button
|
||||
class="flex items-center gap-2 rounded-xl bg-white/10 px-4 py-2.5 text-sm font-medium text-white transition-colors hover:bg-white/20 dark:bg-gray-700 dark:hover:bg-gray-600"
|
||||
@click="emit('openIncrementalImport')"
|
||||
>
|
||||
<UIcon name="i-heroicons-plus-circle" class="h-4 w-4 shrink-0" />
|
||||
{{ t('analysis.tooltip.incrementalImport') }}
|
||||
</button>
|
||||
<button
|
||||
class="flex items-center gap-2 rounded-xl bg-white/10 px-4 py-2.5 text-sm font-medium text-white transition-colors hover:bg-white/20 dark:bg-gray-700 dark:hover:bg-gray-600"
|
||||
@click="emit('openSessionIndex')"
|
||||
>
|
||||
<UIcon name="i-heroicons-clock" class="h-4 w-4 shrink-0" />
|
||||
{{ t('analysis.tooltip.sessionIndex') }}
|
||||
</button>
|
||||
<button
|
||||
class="flex items-center gap-2 rounded-xl bg-white/10 px-4 py-2.5 text-sm font-medium text-white transition-colors hover:bg-white/20 dark:bg-gray-700 dark:hover:bg-gray-600"
|
||||
@click="emit('openMessageExport')"
|
||||
>
|
||||
<UIcon name="i-heroicons-document-arrow-down" class="h-4 w-4 shrink-0" />
|
||||
{{ t('analysis.messageExport.title') }}
|
||||
</button>
|
||||
</div>
|
||||
<OverviewActionTools
|
||||
@open-incremental-import="emit('openIncrementalImport')"
|
||||
@open-session-index="emit('openSessionIndex')"
|
||||
@open-message-export="emit('openMessageExport')"
|
||||
/>
|
||||
</template>
|
||||
</OverviewIdentityCard>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user