/**
* Vue 应用入口
* 侧边栏导航 + 内容区布局,数据驱动菜单渲染
* P1: 登录守卫 + 用户信息展示 + 新页面注册
*/
import { createApp } from 'vue'
import { store, MENU_ITEMS } from './store.js'
import { isLoggedIn, clearTokens, getUserInfo, toast, getRefreshToken } from './utils.js'
import { getCurrentUser, refreshToken } from './api.js'
// 导入组件
import ChatPanel from '../components/ChatPanel.js'
import DocStats from '../components/DocStats.js'
import DocSearch from '../components/DocSearch.js'
import CategoryManager from '../components/CategoryManager.js'
import RoleManager from '../components/RoleManager.js'
import DocList from '../components/DocList.js'
import DocUpload from '../components/DocUpload.js'
import DocDetail from '../components/DocDetail.js'
import ConversationManager from '../components/ConversationManager.js'
import ModelConfigManager from '../components/ModelConfigManager.js'
import SensitiveWordManager from '../components/SensitiveWordManager.js'
import FaqManager from '../components/FaqManager.js'
import AuditLogManager from '../components/AuditLogManager.js'
import LoginPage from '../components/LoginPage.js'
import UserManager from '../components/UserManager.js'
import DashboardPanel from '../components/DashboardPanel.js'
import ApiKeyManager from '../components/ApiKeyManager.js'
import WebhookManager from '../components/WebhookManager.js'
import McpServerManager from '../components/McpServerManager.js'
const app = createApp({
setup() {
const menuItems = MENU_ITEMS
/** 判断父菜单是否高亮(任一子页面激活时高亮父菜单) */
function isMenuActive(parentItem) {
if (!parentItem.children) return store.activePage === parentItem.id
return parentItem.children.some(c => c.id === store.activePage)
}
/** 判断菜单项是否对当前用户可见(roles 限制) */
function isMenuVisible(item) {
if (!item.roles || !item.roles.length) return true
return item.roles.some(r => store.hasRole(r))
}
/** 登录成功回调 */
function onLoginSuccess(user) {
store.currentUser = user || getUserInfo()
store.isLoggedIn = true
}
/** 退出登录 */
function handleLogout() {
clearTokens()
store.isLoggedIn = false
store.currentUser = {}
store.activePage = 'chat'
toast('已退出登录', 'info')
}
/** 尝试刷新 Token */
async function tryRefreshToken() {
const rt = getRefreshToken()
if (!rt) return false
try {
const res = await refreshToken(rt)
if (res.success && res.data) {
const { setToken: st, setRefreshToken: srt } = await import('./utils.js')
st(res.data.accessToken)
srt(res.data.refreshToken)
return true
}
} catch (e) { /* 刷新失败 */ }
return false
}
// 监听 401 未授权事件
window.addEventListener('auth:unauthorized', async () => {
const refreshed = await tryRefreshToken()
if (!refreshed) {
store.isLoggedIn = false
store.currentUser = {}
toast('登录已过期,请重新登录', 'error')
}
})
// 启动时验证登录态
if (isLoggedIn()) {
getCurrentUser().then(res => {
if (res.success && res.data) {
store.currentUser = res.data
store.isLoggedIn = true
} else {
// 业务失败(如用户被禁用),尝试刷新
tryRefreshToken().then(ok => {
if (!ok) {
store.isLoggedIn = false
clearTokens()
} else {
// 刷新成功后重新获取用户信息
getCurrentUser().then(r => {
if (r.success && r.data) {
store.currentUser = r.data
store.isLoggedIn = true
} else {
store.isLoggedIn = false
clearTokens()
}
}).catch(() => { store.isLoggedIn = false; clearTokens() })
}
})
}
}).catch(() => {
// 401 等错误,尝试刷新(不要先清除 token!)
tryRefreshToken().then(ok => {
if (!ok) {
store.isLoggedIn = false
clearTokens()
} else {
// 刷新成功后重新获取用户信息
getCurrentUser().then(r => {
if (r.success && r.data) {
store.currentUser = r.data
store.isLoggedIn = true
} else {
store.isLoggedIn = false
clearTokens()
}
}).catch(() => { store.isLoggedIn = false; clearTokens() })
}
})
})
}
return { menuItems, isMenuActive, isMenuVisible, store, onLoginSuccess, handleLogout }
},
template: `