Refine auth, API proxy, and server routing
This commit is contained in:
+49
-5
@@ -1,7 +1,49 @@
|
||||
const API_BASE = ''; // 使用相对路径
|
||||
|
||||
function readTokenPayload(token) {
|
||||
try {
|
||||
const payload = token.split('.')[1];
|
||||
if (!payload) return null;
|
||||
|
||||
const normalizedPayload = payload.replace(/-/g, '+').replace(/_/g, '/');
|
||||
const paddedPayload = normalizedPayload.padEnd(
|
||||
normalizedPayload.length + ((4 - (normalizedPayload.length % 4)) % 4),
|
||||
'='
|
||||
);
|
||||
|
||||
return JSON.parse(atob(paddedPayload));
|
||||
} catch (err) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function getValidToken() {
|
||||
if (typeof window === 'undefined') return null;
|
||||
|
||||
const token = localStorage.getItem('token');
|
||||
if (!token) return null;
|
||||
|
||||
const payload = readTokenPayload(token);
|
||||
if (!payload?.exp || payload.exp * 1000 <= Date.now()) {
|
||||
localStorage.removeItem('token');
|
||||
return null;
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
function redirectToLogin() {
|
||||
if (typeof window === 'undefined') return;
|
||||
|
||||
localStorage.removeItem('token');
|
||||
|
||||
if (window.location.pathname !== '/login') {
|
||||
window.location.replace('/login');
|
||||
}
|
||||
}
|
||||
|
||||
function getAuthHeaders() {
|
||||
const token = typeof window !== 'undefined' ? localStorage.getItem('token') : null;
|
||||
const token = getValidToken();
|
||||
return token ? { Authorization: `Bearer ${token}` } : {};
|
||||
}
|
||||
|
||||
@@ -24,6 +66,9 @@ async function apiCall(url, options = {}) {
|
||||
const data = await res.json();
|
||||
|
||||
if (!res.ok) {
|
||||
if (res.status === 401 && !url.startsWith('/api/auth/')) {
|
||||
redirectToLogin();
|
||||
}
|
||||
throw new Error(data.error || '请求失败');
|
||||
}
|
||||
|
||||
@@ -60,8 +105,7 @@ export function logout() {
|
||||
}
|
||||
|
||||
export function isLoggedIn() {
|
||||
if (typeof window === 'undefined') return false;
|
||||
return !!localStorage.getItem('token');
|
||||
return !!getValidToken();
|
||||
}
|
||||
|
||||
// 账目
|
||||
@@ -106,7 +150,7 @@ export async function deleteRecordsByCategory(category) {
|
||||
|
||||
// 搜索
|
||||
export async function searchRecords(keyword) {
|
||||
return apiCall(`/api/records/search?q=${encodeURIComponent(keyword)}`);
|
||||
return apiCall(`/api/search?q=${encodeURIComponent(keyword)}`);
|
||||
}
|
||||
|
||||
// 统计
|
||||
@@ -177,7 +221,7 @@ export async function exportData() {
|
||||
}
|
||||
|
||||
export async function importData(data) {
|
||||
return apiCall('/api/import', {
|
||||
return apiCall('/api/export', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
devIndicators: {
|
||||
buildActivity: false,
|
||||
},
|
||||
async rewrites() {
|
||||
return [
|
||||
{
|
||||
|
||||
@@ -1,7 +1,17 @@
|
||||
export default async function handler(req, res) {
|
||||
const { 0: path } = req.query;
|
||||
const path = Array.isArray(req.query.path)
|
||||
? req.query.path.join('/')
|
||||
: req.query.path;
|
||||
|
||||
const backendUrl = `http://localhost:3501/${path}`;
|
||||
if (!path) {
|
||||
res.status(400).json({ error: 'Missing API path' });
|
||||
return;
|
||||
}
|
||||
|
||||
const query = { ...req.query };
|
||||
delete query.path;
|
||||
const searchParams = new URLSearchParams(query);
|
||||
const backendUrl = `http://localhost:3501/api/${path}${searchParams.size ? `?${searchParams}` : ''}`;
|
||||
|
||||
const response = await fetch(backendUrl, {
|
||||
method: req.method,
|
||||
|
||||
@@ -12,7 +12,7 @@ import { formatMoney, parseDateTime, getDatePart } from '../lib/utils';
|
||||
export default function Search() {
|
||||
const router = useRouter();
|
||||
const { showToast } = useToast();
|
||||
const confirm = useConfirm();
|
||||
const { confirm } = useConfirm();
|
||||
const { categories, error: categoriesError } = useCategories();
|
||||
|
||||
// 显示分类加载错误
|
||||
|
||||
Reference in New Issue
Block a user