refactor(env, api, i18n): 更新环境配置与API代理逻辑

修改 .env.example,优化API配置说明并明确线上环境要求。更新多语言错误提示,确保用户在未启用API代理时获得清晰反馈。重构API代理逻辑,移除开发代理文件,简化代码结构,提升可维护性。
This commit is contained in:
2026-05-29 15:55:18 +08:00
parent 671c737781
commit 36117144dc
10 changed files with 70 additions and 24 deletions

View File

@@ -1,16 +1,17 @@
# ============================================================================= # =============================================================================
# 管理端本地配置示例:复制为 .env.local 后按需修改 # 管理端配置:复制为 .env 后按需修改(本地/线上同一套)
# ============================================================================= # =============================================================================
# 三端联调Laravel 8000、管理端 3801、玩家端 3800 # 三端联调Laravel 8000、管理端 3801、玩家端 3800
# 生产部署时 Laravel CORS 需含 https://lotteryadmin.tanumo.com,https://lotteryfront.tanumo.com
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# Laravel API # Laravel API — 唯一必配项
# - 浏览器始终请求同源 /api/v1 # - 浏览器请求同源 /api/v1
# - 宝塔线上负责把 /api/* 转发到 Laravel # - Next 自动转发到 LOTTERY_API_UPSTREAM无需宝塔单独配 /api 转发
# - 本地 npm run dev 时Next 临时把 /api/* 代理到 LOTTERY_API_UPSTREAM
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# 本地
LOTTERY_API_UPSTREAM=http://127.0.0.1:8000 LOTTERY_API_UPSTREAM=http://127.0.0.1:8000
# 线上Laravel 在本机时用内网地址更快)
# LOTTERY_API_UPSTREAM=http://127.0.0.1:8000
# LOTTERY_API_UPSTREAM=https://lotterylaravel.tanumo.com # LOTTERY_API_UPSTREAM=https://lotterylaravel.tanumo.com
# Next 开发:局域网 IP 访问(逗号分隔 host无协议 # Next 开发:局域网 IP 访问(逗号分隔 host无协议

3
.gitignore vendored
View File

@@ -24,6 +24,9 @@
.DS_Store .DS_Store
*.pem *.pem
# pm2
/logs
# debug # debug
npm-debug.log* npm-debug.log*
yarn-debug.log* yarn-debug.log*

49
ecosystem.config.cjs Normal file
View File

@@ -0,0 +1,49 @@
/**
* 管理端lotteryadmin宝塔 PM2 配置
*
* 部署步骤(在服务器项目目录执行):
* 1. 复制 .env.example 为 .env按线上域名填写
* 2. npm ci && npm run build
* 3. 修改下方 cwd 为服务器上的实际路径(默认即本文件所在目录)
* 4. pm2 start ecosystem.config.cjs
* 5. pm2 save && pm2 startup
*
* 宝塔PM2 管理器 → 添加项目 → 选择本文件。
* Nginx反代到 127.0.0.1:3801 即可;/api 由 Next 转发到 LOTTERY_API_UPSTREAM无需单独配。
*/
const path = require("path");
/** 改成服务器上的绝对路径,例如 /www/wwwroot/lotteryadmin.tanumo.com */
const APP_CWD = path.resolve(__dirname);
module.exports = {
apps: [
{
name: "lotteryadmin",
cwd: APP_CWD,
script: "node_modules/next/dist/bin/next",
args: "start -p 3801 -H 127.0.0.1",
interpreter: "node",
exec_mode: "fork",
instances: 1,
autorestart: true,
watch: false,
max_memory_restart: "1G",
time: true,
merge_logs: true,
out_file: path.join(APP_CWD, "logs/pm2-out.log"),
error_file: path.join(APP_CWD, "logs/pm2-error.log"),
env: {
NODE_ENV: "production",
PORT: "3801",
// Laravel 根地址(无尾部 /);同机部署填 http://127.0.0.1:8000
LOTTERY_API_UPSTREAM: "http://127.0.0.1:8000",
},
// env_file: path.join(APP_CWD, ".env"),
},
],
};

View File

@@ -5,7 +5,7 @@
"scripts": { "scripts": {
"dev": "next dev --port 3801", "dev": "next dev --port 3801",
"build": "next build", "build": "next build",
"start": "next start", "start": "next start --port 3801",
"lint": "eslint" "lint": "eslint"
}, },
"dependencies": { "dependencies": {

View File

@@ -1,12 +1,12 @@
import { type NextRequest } from "next/server"; import { type NextRequest } from "next/server";
import { proxyLotteryApiInDev } from "@/lib/lottery-api-dev-proxy"; import { proxyLotteryApi } from "@/lib/lottery-api-proxy";
type RouteContext = { params: Promise<{ path: string[] }> }; type RouteContext = { params: Promise<{ path: string[] }> };
async function handle(request: NextRequest, context: RouteContext) { async function handle(request: NextRequest, context: RouteContext) {
const { path } = await context.params; const { path } = await context.params;
return proxyLotteryApiInDev(request, path); return proxyLotteryApi(request, path);
} }
export const GET = handle; export const GET = handle;

View File

@@ -16,7 +16,7 @@
"submit": "Log in", "submit": "Log in",
"submitting": "Signing in…", "submitting": "Signing in…",
"captchaLoadFailed": "Failed to load captcha. Check the API or network.", "captchaLoadFailed": "Failed to load captcha. Check the API or network.",
"apiBaseMissingToast": "API proxy is not enabled: make sure /api is forwarded to Laravel", "apiBaseMissingToast": "API proxy is not enabled: check LOTTERY_API_UPSTREAM points to Laravel",
"captchaRequired": "Refresh the captcha first", "captchaRequired": "Refresh the captcha first",
"welcome": "Welcome, {{name}}", "welcome": "Welcome, {{name}}",
"networkFailed": "Network request failed", "networkFailed": "Network request failed",

View File

@@ -16,7 +16,7 @@
"submit": "लगइन", "submit": "लगइन",
"submitting": "लगइन हुँदैछ…", "submitting": "लगइन हुँदैछ…",
"captchaLoadFailed": "क्याप्चा लोड गर्न सकिएन। API वा नेटवर्क जाँच गर्नुहोस्।", "captchaLoadFailed": "क्याप्चा लोड गर्न सकिएन। API वा नेटवर्क जाँच गर्नुहोस्।",
"apiBaseMissingToast": "API proxy सक्षम छैन: /api Laravel मा forward भएको छ कि छैन जाँच गर्नुहोस्", "apiBaseMissingToast": "API proxy सक्षम छैन: LOTTERY_API_UPSTREAM Laravel तर्फ छ कि छैन जाँच गर्नुहोस्",
"captchaRequired": "पहिले क्याप्चा रिफ्रेस गर्नुहोस्", "captchaRequired": "पहिले क्याप्चा रिफ्रेस गर्नुहोस्",
"welcome": "स्वागत छ, {{name}}", "welcome": "स्वागत छ, {{name}}",
"networkFailed": "नेटवर्क अनुरोध असफल भयो", "networkFailed": "नेटवर्क अनुरोध असफल भयो",

View File

@@ -16,7 +16,7 @@
"submit": "登录", "submit": "登录",
"submitting": "登录中…", "submitting": "登录中…",
"captchaLoadFailed": "无法获取验证码,请检查接口或网络", "captchaLoadFailed": "无法获取验证码,请检查接口或网络",
"apiBaseMissingToast": "API 代理未启用:请确认宝塔或本地 Next 已转发 /api 到 Laravel", "apiBaseMissingToast": "API 代理未启用:请检查 LOTTERY_API_UPSTREAM 是否指向 Laravel",
"captchaRequired": "请先刷新验证码", "captchaRequired": "请先刷新验证码",
"welcome": "欢迎,{{name}}", "welcome": "欢迎,{{name}}",
"networkFailed": "网络请求失败", "networkFailed": "网络请求失败",

View File

@@ -1,18 +1,15 @@
const DEFAULT_LOTTERY_API_ORIGIN = "http://127.0.0.1:8000"; const DEFAULT_LOTTERY_API_ORIGIN = "http://127.0.0.1:8000";
/** Laravel 根地址(无尾部 `/`供 Next 本地开发代理使用。 */ /** Laravel 根地址(无尾部 `/`),供 Next 代理与 middleware 服务端请求。 */
export function lotteryApiOrigin(): string { export function lotteryApiOrigin(): string {
const configured = const configured = process.env.LOTTERY_API_UPSTREAM?.trim();
process.env.LOTTERY_API_UPSTREAM?.trim() ||
process.env.NEXT_PUBLIC_LOTTERY_API_BASE_URL?.trim();
return (configured || DEFAULT_LOTTERY_API_ORIGIN).replace(/\/$/, ""); return (configured || DEFAULT_LOTTERY_API_ORIGIN).replace(/\/$/, "");
} }
/** /**
* axios `baseURL` * axios `baseURL`
* - 浏览器始终请求同源 `/api/v1` * - 浏览器始终请求同源 `/api/v1`
* - 线上由宝塔转发 `/api/*` 到 Laravel * - Next `app/api/[...path]/route.ts` 转发到 `LOTTERY_API_UPSTREAM`(本地/线上同一套)
* - 本地开发由 `app/api/[...path]/route.ts` 临时代理到 `LOTTERY_API_UPSTREAM`
*/ */
export function resolveLotteryApiV1Base(): string { export function resolveLotteryApiV1Base(): string {
return "/api/v1"; return "/api/v1";

View File

@@ -20,15 +20,11 @@ const STRIP_RESPONSE_HEADERS = [
"content-length", "content-length",
]; ];
/** 本地开发:/api/* → LaravelTurbopack 下 next.config rewrites 常不生效)。 */ /** 浏览器请求同源 `/api/*`Next 转发到 `LOTTERY_API_UPSTREAM`(本地/线上同一套)。 */
export async function proxyLotteryApiInDev( export async function proxyLotteryApi(
request: NextRequest, request: NextRequest,
pathSegments: string[], pathSegments: string[],
): Promise<NextResponse> { ): Promise<NextResponse> {
if (process.env.NODE_ENV !== "development") {
return NextResponse.json({ msg: "Not Found" }, { status: 404 });
}
const path = pathSegments.join("/"); const path = pathSegments.join("/");
const target = `${lotteryApiOrigin()}/api/${path}${request.nextUrl.search}`; const target = `${lotteryApiOrigin()}/api/${path}${request.nextUrl.search}`;