From 38db4e2e7338bb0549d4c7102a4deaacc9dc3bf2 Mon Sep 17 00:00:00 2001 From: Sam <315859133@qq.com> Date: Sun, 8 Feb 2026 20:44:03 +0800 Subject: [PATCH] =?UTF-8?q?feat(gateway):=20=E6=B7=BB=E5=8A=A0=E6=B4=BB?= =?UTF-8?q?=E5=8A=A8=E6=9C=8D=E5=8A=A1=E7=BD=91=E5=85=B3=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E5=8F=8A=E7=AE=A1=E7=90=86=E9=9D=A2=E6=9D=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 docker-compose 配置,包含活动服务、YARP 网关、PostgreSQL 与 Redis - 添加活动服务与网关集成文档,详细介绍配置步骤、API 和故障排查 - 删除旧的 bash 注册脚本,新增跨平台 PowerShell 和通用 bash 注册脚本 - 实现网关相关接口的 TypeScript 客户端调用封装,支持服务注册、路由管理 - 新增网关管理前端界面,包含服务统计、服务注册、路由刷新等功能 - 调整请求客户端默认开启 token 刷新以支持更稳定的认证体验 - 制定微服务命名与版本规范,标准化 API 路径和集群命名规则 --- apps/web-antd/src/api/request.ts | 2 +- playground/src/api/gateway/index.ts | 111 ++++ playground/src/api/gateway/model.ts | 66 +++ .../src/router/routes/modules/system.ts | 9 + .../system/gateway/GatewayManagement.vue | 518 ++++++++++++++++++ pnpm-lock.yaml | 3 - 6 files changed, 705 insertions(+), 4 deletions(-) create mode 100644 playground/src/api/gateway/index.ts create mode 100644 playground/src/api/gateway/model.ts create mode 100644 playground/src/views/system/gateway/GatewayManagement.vue diff --git a/apps/web-antd/src/api/request.ts b/apps/web-antd/src/api/request.ts index 288dddd..c95ccc6 100644 --- a/apps/web-antd/src/api/request.ts +++ b/apps/web-antd/src/api/request.ts @@ -86,7 +86,7 @@ function createRequestClient(baseURL: string, options?: RequestClientOptions) { client, doReAuthenticate, doRefreshToken, - enableRefreshToken: preferences.app.enableRefreshToken, + enableRefreshToken: true, formatToken, }), ); diff --git a/playground/src/api/gateway/index.ts b/playground/src/api/gateway/index.ts new file mode 100644 index 0000000..1a25626 --- /dev/null +++ b/playground/src/api/gateway/index.ts @@ -0,0 +1,111 @@ +import { defHttp } from '/@/api/core'; +import type { GatewayStatistics, GatewayService, GatewayRoute, GatewayInstance } from './model'; + +enum Api { + STATISTICS = '/statistics', + SERVICES = '/services', + ROUTES = '/routes', + INSTANCES = '/instances', + RELOAD = '/reload', +} + +export const getStatistics = () => { + return defHttp.get({ + url: `${Api.STATISTICS}`, + }); +}; + +export const getServices = (params?: { globalOnly?: boolean; tenantCode?: string }) => { + return defHttp.get({ + url: `${Api.SERVICES}`, + params, + }); +}; + +export const getService = (serviceName: string, params?: { tenantCode?: string }) => { + return defHttp.get({ + url: `${Api.SERVICES}/${serviceName}`, + params, + }); +}; + +export const registerService = (data: { + servicePrefix: string; + serviceName: string; + version: string; + serviceAddress: string; + destinationId?: string; + weight?: number; + isGlobal?: boolean; + tenantCode?: string; +}) => { + return defHttp.post({ + url: `${Api.SERVICES}`, + data, + }); +}; + +export const unregisterService = (serviceName: string, params?: { tenantCode?: string }) => { + return defHttp.delete({ + url: `${Api.SERVICES}/${serviceName}`, + params, + }); +}; + +export const getRoutes = (params?: { globalOnly?: boolean }) => { + return defHttp.get({ + url: `${Api.ROUTES}`, + params, + }); +}; + +export const createRoute = (data: { + serviceName: string; + clusterId: string; + pathPattern: string; + priority?: number; + isGlobal?: boolean; + tenantCode?: string; +}) => { + return defHttp.post({ + url: `${Api.ROUTES}`, + data, + }); +}; + +export const getInstances = (clusterId: string) => { + return defHttp.get({ + url: `${Api.INSTANCES}`.replace('{clusterId}', clusterId), + }); +}; + +export const addInstance = (data: { + clusterId: string; + destinationId: string; + address: string; + weight?: number; +}) => { + return defHttp.post({ + url: `${Api.INSTANCES}`, + data, + }); +}; + +export const removeInstance = (instanceId: number) => { + return defHttp.delete({ + url: `${Api.INSTANCES}/${instanceId}`, + }); +}; + +export const updateInstanceWeight = (instanceId: number, weight: number) => { + return defHttp.put({ + url: `${Api.INSTANCES}/${instanceId}/weight`, + params: { weight }, + }); +}; + +export const reloadGateway = () => { + return defHttp.post({ + url: `${Api.RELOAD}`, + }); +}; diff --git a/playground/src/api/gateway/model.ts b/playground/src/api/gateway/model.ts new file mode 100644 index 0000000..d854518 --- /dev/null +++ b/playground/src/api/gateway/model.ts @@ -0,0 +1,66 @@ +export interface GatewayStatistics { + totalServices: number; + globalRoutes: number; + tenantRoutes: number; + totalInstances: number; + healthyInstances: number; + recentServices: GatewayService[]; +} + +export interface GatewayService { + id: number; + servicePrefix: string; + serviceName: string; + version: string; + clusterId: string; + pathPattern: string; + serviceAddress: string; + destinationId: string; + weight: number; + instanceCount: number; + isGlobal: boolean; + tenantCode?: string; + status: number; + createdAt: string; +} + +export interface GatewayRoute { + id: number; + serviceName: string; + clusterId: string; + pathPattern: string; + priority: number; + isGlobal: boolean; + tenantCode?: string; + status: number; + instanceCount: number; +} + +export interface GatewayInstance { + id: number; + clusterId: string; + destinationId: string; + address: string; + weight: number; + health: number; + status: number; + createdAt: string; +} + +export interface RegisterServiceForm { + servicePrefix: string; + serviceName: string; + version: string; + serviceAddress: string; + destinationId?: string; + weight: number; + isGlobal: boolean; + tenantCode?: string; +} + +export interface AddInstanceForm { + clusterId: string; + destinationId: string; + address: string; + weight: number; +} diff --git a/playground/src/router/routes/modules/system.ts b/playground/src/router/routes/modules/system.ts index e1bf712..d534b33 100644 --- a/playground/src/router/routes/modules/system.ts +++ b/playground/src/router/routes/modules/system.ts @@ -39,6 +39,15 @@ const routes: RouteRecordRaw[] = [ }, component: () => import('#/views/system/dept/list.vue'), }, + { + path: '/system/gateway', + name: 'SystemGateway', + meta: { + icon: 'ant-design:api-outlined', + title: '网关管理', + }, + component: () => import('#/views/system/gateway/GatewayManagement.vue'), + }, ], }, ]; diff --git a/playground/src/views/system/gateway/GatewayManagement.vue b/playground/src/views/system/gateway/GatewayManagement.vue new file mode 100644 index 0000000..16d7fa7 --- /dev/null +++ b/playground/src/views/system/gateway/GatewayManagement.vue @@ -0,0 +1,518 @@ + + + + + diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index dd65c79..4e9116a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -702,9 +702,6 @@ importers: dayjs: specifier: 'catalog:' version: 1.11.19 - oidc-client-ts: - specifier: ^3.4.1 - version: 3.4.1 pinia: specifier: ^3.0.4 version: 3.0.4(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3))