From 4566d7cd5eeb19bb46e08daa5ce34637e0cfdca6 Mon Sep 17 00:00:00 2001 From: LoveChengke Date: Fri, 11 Sep 2026 22:01:32 +0800 Subject: [PATCH] =?UTF-8?q?feat(server):=20=E5=A2=9E=E5=8A=A0=E6=A0=B9?= =?UTF-8?q?=E8=B7=AF=E5=BE=84=E6=9C=8D=E5=8A=A1=E9=A6=96=E9=A1=B5=EF=BC=8C?= =?UTF-8?q?=E5=AE=8C=E5=96=84=E6=96=87=E6=A1=A3=E4=B8=AD=E7=9A=84=E8=AE=BF?= =?UTF-8?q?=E9=97=AE=E5=9C=B0=E5=9D=80=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 16 ++++++--- packages/server/src/app.ts | 74 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 2350319..028a231 100644 --- a/README.md +++ b/README.md @@ -99,11 +99,17 @@ pnpm dev 启动后访问: -| 服务 | 地址 | -| ------------------ | -------------------------------- | -| Web 管理端(开发) | http://127.0.0.1:5173 | -| 后端 API | http://127.0.0.1:4000/api | -| 健康检查 | http://127.0.0.1:4000/api/health | +| 服务 | 地址 | +| ------------------------------------------ | -------------------------------- | +| Web 管理端(开发) | http://127.0.0.1:5173 | +| 后端服务首页(浏览器可读,列出已挂载模块) | http://127.0.0.1:4000 | +| 后端 API | http://127.0.0.1:4000/api | +| 健康检查 | http://127.0.0.1:4000/api/health | + +> 后端只提供 REST API 与 WebSocket,没有业务网页界面。直接访问 +> `http://127.0.0.1:4000/` 会返回服务首页(带 `Accept: application/json` 时返回结构化信息); +> 其它未匹配路径统一返回 `{ "success": false, "code": "NOT_FOUND" }`。 +> Web 管理端地址是 **5173** 端口,请勿访问 80 端口(会连接被拒绝)。 也可以分开启动:`pnpm dev:server`(仅后端)、`pnpm dev:web`(仅 Web 端)。 diff --git a/packages/server/src/app.ts b/packages/server/src/app.ts index 2df737a..6d2e1b0 100644 --- a/packages/server/src/app.ts +++ b/packages/server/src/app.ts @@ -25,6 +25,55 @@ async function healthHandler(_req: Request, res: Response): Promise { ); } +/** + * 根路径落地页。 + * API 全部挂在 /api 下,根路径本身不是接口;这里给出一个可读的服务首页, + * 避免浏览器直接访问 4000 端口时看到 404 JSON 而误以为服务没起来。 + */ +function renderLandingPage(): string { + const moduleRows = apiModules + .map((module) => `
  • ${API_PREFIX}${module.basePath} ${module.name}
  • `) + .join(''); + return ` + + + + + 班级小助手 · 后端服务 + + + +
    +

    班级小助手 · 后端服务 running

    +

    版本 0.1.0 · 运行环境 ${env.nodeEnv} · 数据库 ${env.databaseProvider}

    +

    + 健康检查:${API_PREFIX}/health · + 管理端开发地址:http://127.0.0.1:5173 +

    + 已挂载模块(${apiModules.length} 个) +
      ${moduleRows}
    +
    + 提示:本服务只提供 REST API 与 WebSocket,没有网页界面。
    + 网页界面请访问 Web 管理端 http://127.0.0.1:5173(pnpm dev:web), + WebSocket 端点为 ws://127.0.0.1:${env.port}/socket.io。 +
    +
    + +`; +} + /** 组装 Express 应用:中间件 -> 健康检查 -> 模块路由 -> 404 -> 统一错误处理 */ export function createApp(): Express { const app = express(); @@ -39,6 +88,31 @@ export function createApp(): Express { next(); }); + // 服务首页(浏览器可读);如果客户端显式要 JSON,则返回结构化信息 + app.get('/', (req, res) => { + if (req.accepts(['html', 'json']) === 'json') { + sendOk( + res, + { + service: 'class-helper-server', + version: '0.1.0', + apiPrefix: API_PREFIX, + webAdmin: 'http://127.0.0.1:5173', + socket: `/socket.io`, + modules: apiModules.map((module) => `${API_PREFIX}${module.basePath}`), + }, + '服务运行正常,API 前缀为 /api', + ); + return; + } + res.type('html').send(renderLandingPage()); + }); + + // 浏览器会自动请求 favicon,直接返回 204,避免污染日志 + app.get('/favicon.ico', (_req, res) => { + res.status(204).end(); + }); + // 健康检查(同时暴露已挂载模块列表,便于确认模块化装配结果) app.get(`${API_PREFIX}/health`, healthHandler); app.get('/health', healthHandler);