Mimingguang ee078b61bc feat: 后台管理系统完整重构 + 前后台数据联通
- 后台全面引入 Naive UI 组件库,统一 UI 规范
- 前台 usePublicApi 切换到 API 调用(GET /api/content/[key])
- 前后台数据源统一(site_content 表)
- 产品线统一管理(tour/camp/course 三套编辑器)
- 产品数据归一化(itinerary/faq/pricing 格式统一)
- 表单提交 API 改写入 submissions 表
- 新增 submissions 标记已读 API
- site-content PUT 支持 upsert
- 修复前台 bug(stories 路由冲突、占位符警告、selector breadcrumb)
- 消除 PageHero 类型警告(useSEO reactive 修复)
- 25 个前台页面全部 HTTP 200,展示效果不变

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 17:48:02 +08:00

48 行
1.1 KiB
JavaScript

/**
* 管理后台认证 composable
*/
export function useAdmin() {
const token = useState('admin_token', () => '')
// 客户端刷新时从 localStorage 恢复 token
if (import.meta.client && !token.value) {
token.value = localStorage.getItem('admin_token') || ''
}
const isLoggedIn = computed(() => !!token.value)
async function login(username, password) {
const data = await $fetch('/api/admin/login', {
method: 'POST',
body: { username, password },
})
token.value = data.token
localStorage.setItem('admin_token', data.token)
return data
}
function logout() {
token.value = ''
localStorage.removeItem('admin_token')
navigateTo('/admin/login')
}
// 带认证的请求封装
function adminFetch(url, options = {}) {
return $fetch(url, {
...options,
headers: {
...options.headers,
Authorization: `Bearer ${token.value}`,
},
onResponseError({ response }) {
if (response.status === 401) {
logout()
}
},
})
}
return { token, isLoggedIn, login, logout, adminFetch }
}