优化小程序登录流程,增加用户协议和隐私政策的勾选机制,确保用户主动同意后方可登录,符合审核要求。同时,增强错误处理逻辑,提升用户体验和系统稳定性。新增用户协议和隐私政策页面,更新相关样式以改善界面交互。
This commit is contained in:
@@ -3,4 +3,5 @@
|
||||
# VITE_API_BASE_URL=http://localhost:3006
|
||||
VITE_API_BASE_URL=http://localhost:8080
|
||||
# VITE_API_BASE_URL=https://soulapi.quwanzhi.com
|
||||
# VITE_API_BASE_URL=https://soul.quwanzhi.com
|
||||
|
||||
|
||||
28
soul-admin/src/api/auth.ts
Normal file
28
soul-admin/src/api/auth.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* 管理端 JWT 本地存储(localStorage),与 soul-api JWT 鉴权配合
|
||||
*/
|
||||
const ADMIN_TOKEN_KEY = 'admin_token'
|
||||
|
||||
export function getAdminToken(): string | null {
|
||||
try {
|
||||
return localStorage.getItem(ADMIN_TOKEN_KEY)
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
export function setAdminToken(token: string): void {
|
||||
try {
|
||||
localStorage.setItem(ADMIN_TOKEN_KEY, token)
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
export function clearAdminToken(): void {
|
||||
try {
|
||||
localStorage.removeItem(ADMIN_TOKEN_KEY)
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
/**
|
||||
* 统一 API 请求封装
|
||||
* 规则:API 路径与现网完全一致,仅通过 baseUrl 区分环境(Next 或未来 Gin)
|
||||
* 无缝切换:仅修改 VITE_API_BASE_URL 即可切换后端
|
||||
* 鉴权:管理端使用 JWT,自动带 Authorization: Bearer <token>(token 存 localStorage)
|
||||
*/
|
||||
|
||||
import { getAdminToken } from './auth'
|
||||
|
||||
/** 未设置环境变量时使用的默认 API 地址(零配置部署) */
|
||||
const DEFAULT_API_BASE = 'https://soulapi.quwanzhi.com'
|
||||
|
||||
@@ -24,7 +26,7 @@ export type RequestInitWithBody = RequestInit & { data?: unknown }
|
||||
|
||||
/**
|
||||
* 发起请求。path 为与现网一致的 API 路径(如 /api/admin、/api/orders)。
|
||||
* 自动带上 credentials: 'include' 以支持 Cookie 鉴权(与现有 Next 一致)。
|
||||
* 若有 admin_token(JWT)则自动带 Authorization: Bearer;credentials: 'include' 保留以兼容需 Cookie 的接口。
|
||||
*/
|
||||
export async function request<T = unknown>(
|
||||
path: string,
|
||||
@@ -33,6 +35,10 @@ export async function request<T = unknown>(
|
||||
const { data, ...init } = options
|
||||
const url = apiUrl(path)
|
||||
const headers = new Headers(init.headers as HeadersInit)
|
||||
const token = getAdminToken()
|
||||
if (token) {
|
||||
headers.set('Authorization', `Bearer ${token}`)
|
||||
}
|
||||
if (data !== undefined && data !== null && !headers.has('Content-Type')) {
|
||||
headers.set('Content-Type', 'application/json')
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
BookOpen,
|
||||
} from 'lucide-react'
|
||||
import { get, post } from '@/api/client'
|
||||
import { clearAdminToken } from '@/api/auth'
|
||||
|
||||
const menuItems = [
|
||||
{ icon: LayoutDashboard, label: '数据概览', href: '/dashboard' },
|
||||
@@ -52,7 +53,12 @@ export function AdminLayout() {
|
||||
}, [mounted, navigate])
|
||||
|
||||
const handleLogout = async () => {
|
||||
await post('/api/admin/logout', {})
|
||||
clearAdminToken()
|
||||
try {
|
||||
await post('/api/admin/logout', {})
|
||||
} catch {
|
||||
// 忽略登出接口失败,本地已清 token
|
||||
}
|
||||
navigate('/login', { replace: true })
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Lock, User, ShieldCheck } from 'lucide-react'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { post } from '@/api/client'
|
||||
import { setAdminToken } from '@/api/auth'
|
||||
|
||||
export function LoginPage() {
|
||||
const navigate = useNavigate()
|
||||
@@ -16,11 +17,16 @@ export function LoginPage() {
|
||||
setError('')
|
||||
setLoading(true)
|
||||
try {
|
||||
const data = await post<{ success?: boolean; error?: string }>('/api/admin', {
|
||||
const data = await post<{
|
||||
success?: boolean
|
||||
error?: string
|
||||
token?: string
|
||||
}>('/api/admin', {
|
||||
username: username.trim(),
|
||||
password,
|
||||
})
|
||||
if (data?.success !== false) {
|
||||
if (data?.success !== false && data?.token) {
|
||||
setAdminToken(data.token)
|
||||
navigate('/dashboard', { replace: true })
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user