| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307 |
- import { defineStore } from 'pinia';
- import { ref, computed, markRaw, type Component } from 'vue';
- // 标签页类型
- export type TabType = 'page' | 'browser';
- // 标签页接口
- export interface Tab {
- id: string;
- title: string;
- type: TabType;
- // 页面类型标签页的路由路径
- path?: string;
- // 页面组件(用于缓存)
- component?: Component;
- // 浏览器类型标签页的数据
- browserData?: {
- platform: string;
- sessionId?: string;
- url?: string;
- cookieData?: string; // 预设的 Cookie 数据(JSON 格式)
- status?: 'loading' | 'ready' | 'login_pending' | 'login_success' | 'login_failed';
- groupId?: number;
- isAdminMode?: boolean; // 是否是管理后台模式(从后台按钮打开,不需要登录检测和保存账号)
- };
- // 是否可关闭
- closable?: boolean;
- // 图标
- icon?: string;
- }
- // 页面路由配置
- export const PAGE_CONFIG: Record<string, { title: string; icon: string }> = {
- '/': { title: '数据看板', icon: 'DataAnalysis' },
- '/accounts': { title: '账号管理', icon: 'User' },
- '/works': { title: '作品管理', icon: 'Film' },
- '/publish': { title: '发布管理', icon: 'Upload' },
- '/comments': { title: '评论管理', icon: 'ChatDotRound' },
- '/schedule': { title: '定时任务', icon: 'Clock' },
- '/analytics/overview': { title: '数据总览', icon: 'TrendCharts' },
- '/analytics/platform': { title: '平台数据', icon: 'TrendCharts' },
- '/analytics/account': { title: '账号数据', icon: 'TrendCharts' },
- '/analytics/work': { title: '作品数据', icon: 'TrendCharts' },
- '/settings': { title: '系统设置', icon: 'Setting' },
- '/profile': { title: '个人中心', icon: 'User' },
- };
- export const useTabsStore = defineStore('tabs', () => {
- // 所有标签页
- const tabs = ref<Tab[]>([]);
-
- // 当前激活的标签页ID
- const activeTabId = ref<string>('');
-
- // 账号列表刷新计数器(当计数器变化时,Accounts 页面会刷新)
- const accountRefreshTrigger = ref(0);
-
- // 当前激活的标签页
- const activeTab = computed(() =>
- tabs.value.find(tab => tab.id === activeTabId.value)
- );
-
- // 浏览器类型的标签页
- const browserTabs = computed(() =>
- tabs.value.filter(tab => tab.type === 'browser')
- );
-
- // 页面类型的标签页
- const pageTabs = computed(() =>
- tabs.value.filter(tab => tab.type === 'page')
- );
-
- // 生成唯一ID
- function generateId(): string {
- return `tab_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
- }
-
- // 添加标签页
- function addTab(tab: Omit<Tab, 'id'> & { id?: string }): Tab {
- const newTab: Tab = {
- ...tab,
- id: tab.id || generateId(),
- closable: tab.closable ?? true,
- };
-
- // 检查是否已存在相同路径的页面标签
- if (tab.type === 'page' && tab.path) {
- const existingTab = tabs.value.find(t => t.type === 'page' && t.path === tab.path);
- if (existingTab) {
- activeTabId.value = existingTab.id;
- return existingTab;
- }
- }
-
- tabs.value.push(newTab);
- activeTabId.value = newTab.id;
-
- return newTab;
- }
-
- // 打开页面标签页
- function openPageTab(path: string, component?: Component): Tab {
- // 检查是否已存在(支持动态路由匹配)
- const existingTab = tabs.value.find(t => {
- if (t.type === 'page' && t.path) {
- // 精确匹配
- if (t.path === path) return true;
- // 动态路由匹配:/analytics/platform-detail/:platform
- if (path.startsWith('/analytics/platform-detail/') &&
- t.path?.startsWith('/analytics/platform-detail/')) {
- return true;
- }
- }
- return false;
- });
-
- if (existingTab) {
- // 如果路径不同,更新路径(用于动态路由)
- if (existingTab.path !== path) {
- existingTab.path = path;
- }
- activeTabId.value = existingTab.id;
- return existingTab;
- }
-
- // 获取页面配置(支持动态路由)
- let config = PAGE_CONFIG[path];
- if (!config && path.startsWith('/analytics/platform-detail/')) {
- // 从路径中提取平台名称
- const platform = path.split('/').pop() || '';
- const platformNames: Record<string, string> = {
- 'douyin': '抖音',
- 'xiaohongshu': '小红书',
- 'baijiahao': '百家号',
- 'weixin_video': '视频号',
- };
- config = {
- title: `${platformNames[platform] || platform}平台数据详情`,
- icon: 'TrendCharts'
- };
- }
-
- const finalConfig = config || { title: '未知页面', icon: 'Document' };
-
- const tab = addTab({
- title: finalConfig.title,
- type: 'page',
- path,
- component: component ? markRaw(component) : undefined,
- icon: finalConfig.icon,
- // 首页不可关闭
- closable: path !== '/',
- });
-
- return tab;
- }
-
- // 打开浏览器标签页
- function openBrowserTab(platform: string, title?: string, groupId?: number, url?: string, cookieData?: string, isAdminMode?: boolean): Tab {
- const tab = addTab({
- title: title || `${platform} 浏览器`,
- type: 'browser',
- browserData: {
- platform,
- status: 'loading',
- groupId,
- url, // 可选的初始 URL
- cookieData, // 可选的预设 Cookie
- isAdminMode, // 是否是管理后台模式
- },
- icon: 'Monitor',
- });
-
- return tab;
- }
-
- // 更新标签页
- function updateTab(id: string, updates: Partial<Tab>) {
- const index = tabs.value.findIndex(tab => tab.id === id);
- if (index !== -1) {
- tabs.value[index] = { ...tabs.value[index], ...updates };
- }
- }
-
- // 更新浏览器标签页数据
- function updateBrowserTab(id: string, browserData: Partial<Tab['browserData']>) {
- const tab = tabs.value.find(t => t.id === id);
- if (tab && tab.browserData) {
- tab.browserData = { ...tab.browserData, ...browserData };
- }
- }
-
- // 关闭标签页
- function closeTab(id: string) {
- const index = tabs.value.findIndex(tab => tab.id === id);
- if (index === -1) return;
-
- const tab = tabs.value[index];
- if (!tab.closable) return;
-
- tabs.value.splice(index, 1);
-
- // 如果关闭的是当前激活的标签页,激活相邻的标签页
- if (activeTabId.value === id) {
- if (tabs.value.length > 0) {
- // 激活前一个或后一个标签页
- const newIndex = Math.min(index, tabs.value.length - 1);
- activeTabId.value = tabs.value[newIndex].id;
- } else {
- activeTabId.value = '';
- }
- }
- }
-
- // 关闭所有标签页
- function closeAllTabs() {
- tabs.value = tabs.value.filter(tab => !tab.closable);
- if (tabs.value.length > 0) {
- activeTabId.value = tabs.value[0].id;
- } else {
- activeTabId.value = '';
- }
- }
-
- // 关闭其他标签页
- function closeOtherTabs(id: string) {
- tabs.value = tabs.value.filter(tab => tab.id === id || !tab.closable);
- activeTabId.value = id;
- }
-
- // 关闭右侧标签页
- function closeRightTabs(id: string) {
- const index = tabs.value.findIndex(tab => tab.id === id);
- if (index === -1) return;
-
- tabs.value = tabs.value.filter((tab, i) => i <= index || !tab.closable);
-
- // 如果当前激活的标签页被关闭了,激活指定的标签页
- if (!tabs.value.find(t => t.id === activeTabId.value)) {
- activeTabId.value = id;
- }
- }
-
- // 激活标签页
- function activateTab(id: string) {
- if (tabs.value.find(tab => tab.id === id)) {
- activeTabId.value = id;
- }
- }
-
- // 通过路径激活标签页
- function activateTabByPath(path: string): boolean {
- const tab = tabs.value.find(t => t.type === 'page' && t.path === path);
- if (tab) {
- activeTabId.value = tab.id;
- return true;
- }
- return false;
- }
-
- // 通过浏览器会话ID查找标签页
- function findTabBySessionId(sessionId: string): Tab | undefined {
- return tabs.value.find(
- tab => tab.type === 'browser' && tab.browserData?.sessionId === sessionId
- );
- }
-
- // 获取当前激活的页面路径
- function getActivePagePath(): string | undefined {
- const tab = activeTab.value;
- if (tab?.type === 'page') {
- return tab.path;
- }
- return undefined;
- }
-
- // 触发账号列表刷新
- function triggerAccountRefresh() {
- accountRefreshTrigger.value++;
- }
-
- return {
- // 状态
- tabs,
- activeTabId,
- accountRefreshTrigger,
- // 计算属性
- activeTab,
- browserTabs,
- pageTabs,
- // 方法
- addTab,
- openPageTab,
- openBrowserTab,
- updateTab,
- updateBrowserTab,
- closeTab,
- closeAllTabs,
- closeOtherTabs,
- closeRightTabs,
- activateTab,
- activateTabByPath,
- findTabBySessionId,
- getActivePagePath,
- triggerAccountRefresh,
- };
- });
|