feat(insight): add top-level insight navigation

This commit is contained in:
digua committed 2026-07-12 15:29:09 +08:00
1 parent 618af4b5b9
commit 38206716b7
15 files changed
+165 -15

No files matched your search

+29 -15
View File
@@ -50,6 +50,9 @@ const showContactsEntry = computed(() =>
})
)
// 是否在洞察页
const isInsightPage = computed(() => route.path === '/insight')
// 重命名相关状态
const showRenameModal = ref(false)
const renameTarget = ref<AnalysisSession | null>(null)
@@ -462,21 +465,32 @@ function getAvatarColorClass(session: AnalysisSession, isActive: boolean) {
</UButton>
</div>
<!-- 新建分析 -->
<SidebarButton
icon="i-heroicons-plus"
:title="t('layout.newAnalysis')"
:active="isHomePage"
@click="handleImport"
/>
<SidebarButton
v-if="showContactsEntry"
icon="i-lucide-users"
icon-class="scale-90"
:title="t('layout.relationships')"
:active="isPeoplePage"
@click="openContacts"
/>
<div class="space-y-1">
<!-- 新建分析 -->
<SidebarButton
icon="i-heroicons-plus"
:title="t('layout.newAnalysis')"
:active="isHomePage"
@click="handleImport"
/>
<SidebarButton
v-if="showContactsEntry"
icon="i-lucide-users"
icon-class="scale-90"
:title="t('layout.relationships')"
:active="isPeoplePage"
@click="openContacts"
/>
<!-- 洞察 -->
<SidebarButton
icon="i-heroicons-presentation-chart-bar"
:title="t('layout.insight')"
:active="isInsightPage"
@click="router.push('/insight')"
/>
</div>
</div>
<!-- Session List -->
+2
View File
@@ -13,6 +13,7 @@ import views from './views.json'
import wordFilter from './wordFilter.json'
import contacts from './contacts.json'
import relationships from './relationships.json'
import insight from './insight.json'
export default {
common,
@@ -30,4 +31,5 @@ export default {
wordFilter,
contacts,
relationships,
insight,
}
+9
View File
@@ -0,0 +1,9 @@
{
"title": "Insights",
"placeholder": "Global insights are coming soon, stay tuned",
"tabs": {
"overview": "Overview",
"trends": "Trends",
"ranking": "Ranking"
}
}
+3
View File
@@ -3,6 +3,9 @@
"newAnalysis": "New Analysis",
"contacts": "Contacts",
"relationships": "Relationships",
"insight": "Insights",
"tools": "Tools",
"chatHistory": "Chat History",
"manage": "Manage",
"noRecords": "No records",
"searchPlaceholder": "Search conversation name",
+2
View File
@@ -13,6 +13,7 @@ import views from './views.json'
import wordFilter from './wordFilter.json'
import contacts from './contacts.json'
import relationships from './relationships.json'
import insight from './insight.json'
export default {
common,
@@ -30,4 +31,5 @@ export default {
wordFilter,
contacts,
relationships,
insight,
}
+9
View File
@@ -0,0 +1,9 @@
{
"title": "インサイト",
"placeholder": "グローバルインサイト機能は近日公開予定です",
"tabs": {
"overview": "概要",
"trends": "トレンド",
"ranking": "ランキング"
}
}
+3
View File
@@ -3,6 +3,9 @@
"newAnalysis": "新しいチャットを分析",
"contacts": "連絡先",
"relationships": "関係",
"insight": "インサイト",
"tools": "ツール",
"chatHistory": "チャット履歴",
"manage": "管理",
"noRecords": "記録がありません",
"searchPlaceholder": "チャット名を検索",
+2
View File
@@ -13,6 +13,7 @@ import views from './views.json'
import wordFilter from './wordFilter.json'
import contacts from './contacts.json'
import relationships from './relationships.json'
import insight from './insight.json'
export default {
common,
@@ -30,4 +31,5 @@ export default {
wordFilter,
contacts,
relationships,
insight,
}
+9
View File
@@ -0,0 +1,9 @@
{
"title": "洞察",
"placeholder": "全局洞察功能正在建设中,敬请期待",
"tabs": {
"overview": "总览",
"trends": "趋势",
"ranking": "排行"
}
}
+3
View File
@@ -3,6 +3,9 @@
"newAnalysis": "分析新对话",
"contacts": "联系人",
"relationships": "关系",
"insight": "洞察",
"tools": "实用工具",
"chatHistory": "聊天对话",
"manage": "管理",
"noRecords": "暂无记录",
"searchPlaceholder": "搜索对话名称",
+2
View File
@@ -13,6 +13,7 @@ import views from './views.json'
import wordFilter from './wordFilter.json'
import contacts from './contacts.json'
import relationships from './relationships.json'
import insight from './insight.json'
export default {
common,
@@ -30,4 +31,5 @@ export default {
wordFilter,
contacts,
relationships,
insight,
}
+9
View File
@@ -0,0 +1,9 @@
{
"title": "洞察",
"placeholder": "全域洞察功能正在建設中,敬請期待",
"tabs": {
"overview": "總覽",
"trends": "趨勢",
"ranking": "排行"
}
}
+3
View File
@@ -3,6 +3,9 @@
"newAnalysis": "分析新對話",
"contacts": "聯絡人",
"relationships": "關係",
"insight": "洞察",
"tools": "實用工具",
"chatHistory": "聊天紀錄",
"manage": "管理",
"noRecords": "暫無紀錄",
"searchPlaceholder": "搜尋聊天名稱",
+75
View File
@@ -0,0 +1,75 @@
<script setup lang="ts">
import { ref } from 'vue'
import { useI18n } from 'vue-i18n'
import PageHeader from '@/components/layout/PageHeader.vue'
import EmptyState from '@/components/UI/EmptyState.vue'
const { t } = useI18n()
const tabs = [
{ id: 'overview', labelKey: 'insight.tabs.overview', icon: 'i-heroicons-chart-pie' },
{ id: 'trends', labelKey: 'insight.tabs.trends', icon: 'i-heroicons-presentation-chart-line' },
{ id: 'ranking', labelKey: 'insight.tabs.ranking', icon: 'i-heroicons-trophy' },
]
const activeTab = ref('overview')
</script>
<template>
<div class="flex h-full flex-col bg-white dark:bg-gray-900" style="padding-top: var(--titlebar-area-height)">
<PageHeader
:title="t('insight.title')"
icon="i-heroicons-presentation-chart-bar"
icon-class="bg-pink-600 text-white dark:bg-pink-500 dark:text-white"
size="compact"
>
<!-- Tab 栏 -->
<div class="mt-3 flex items-center gap-0.5 overflow-x-auto scrollbar-hide">
<button
v-for="tab in tabs"
:key="tab.id"
class="flex items-center gap-1.5 rounded-lg px-2.5 py-1.5 text-sm font-medium transition-all"
:class="[
activeTab === tab.id
? 'bg-pink-500 text-white dark:bg-pink-900/30 dark:text-pink-300'
: 'text-gray-600 hover:bg-gray-100 dark:text-gray-400 dark:hover:bg-gray-800',
]"
@click="activeTab = tab.id"
>
<UIcon :name="tab.icon" class="h-4 w-4" />
<span class="whitespace-nowrap">{{ t(tab.labelKey) }}</span>
</button>
</div>
</PageHeader>
<!-- Tab 内容区 -->
<div class="relative flex-1 overflow-y-auto">
<div class="h-full">
<Transition name="tab-slide" mode="out-in">
<div :key="activeTab" class="flex h-full items-center justify-center">
<EmptyState :text="t('insight.placeholder')" icon="✨" padding="lg" />
</div>
</Transition>
</div>
</div>
</div>
</template>
<style scoped>
.tab-slide-enter-active,
.tab-slide-leave-active {
transition:
opacity 0.2s ease,
transform 0.2s ease;
}
.tab-slide-enter-from {
opacity: 0;
transform: translateY(10px);
}
.tab-slide-leave-to {
opacity: 0;
transform: translateY(-10px);
}
</style>
+5
View File
@@ -27,6 +27,11 @@ export const appRoutes: RouteRecordRaw[] = [
name: 'private-chat',
component: () => import('@/pages/private-chat/index.vue'),
},
{
path: '/insight',
name: 'insight',
component: () => import('@/pages/insight/index.vue'),
},
{
path: '/people',
component: () => import('@/pages/people/index.vue'),