From 82f96a12d8cec23b0a9a6757eadaf58ba87b4d67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BF=9F=E4=BA=8C=E8=BF=9C?= Date: Wed, 8 Apr 2026 09:37:29 +0800 Subject: [PATCH] =?UTF-8?q?feat=20:=20=E8=B0=83=E6=95=B4=E9=80=82=E9=85=8D?= =?UTF-8?q?=E9=83=A8=E7=BD=B2=E9=98=BF=E9=87=8C=E4=BA=91=E6=95=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/skillhub-app/pom.xml | 6 +-- .../src/main/resources/application-dev.yml | 9 +++++ .../policy/RouteSecurityPolicyRegistry.java | 5 +++ web/nginx.conf.template | 39 ++++++++----------- web/src/bootstrap.ts | 3 +- 5 files changed, 36 insertions(+), 26 deletions(-) diff --git a/server/skillhub-app/pom.xml b/server/skillhub-app/pom.xml index aeeee7a3..6ee9bfbe 100644 --- a/server/skillhub-app/pom.xml +++ b/server/skillhub-app/pom.xml @@ -27,9 +27,9 @@ micrometer-registry-prometheus - org.springdoc - springdoc-openapi-starter-webmvc-ui - 2.3.0 + com.github.xiaoymin + knife4j-openapi3-jakarta-spring-boot-starter + 4.5.0 com.iflytek.skillhub diff --git a/server/skillhub-app/src/main/resources/application-dev.yml b/server/skillhub-app/src/main/resources/application-dev.yml index c4bf1e67..2817e39b 100644 --- a/server/skillhub-app/src/main/resources/application-dev.yml +++ b/server/skillhub-app/src/main/resources/application-dev.yml @@ -167,8 +167,17 @@ skillhub: display-name: ${BOOTSTRAP_ADMIN_DISPLAY_NAME:Admin} email: ${BOOTSTRAP_ADMIN_EMAIL:admin@skillhub.local} +knife4j: + enable: true + setting: + language: zh_cn + swagger-model-name: SkillHub API + springdoc: + api-docs: + path: /v3/api-docs swagger-ui: + path: /swagger-ui.html config-url: /skillhub-server/v3/api-docs/swagger-config url: /skillhub-server/v3/api-docs disable-swagger-default-url: true diff --git a/server/skillhub-auth/src/main/java/com/iflytek/skillhub/auth/policy/RouteSecurityPolicyRegistry.java b/server/skillhub-auth/src/main/java/com/iflytek/skillhub/auth/policy/RouteSecurityPolicyRegistry.java index efbe121e..86f5d08e 100644 --- a/server/skillhub-auth/src/main/java/com/iflytek/skillhub/auth/policy/RouteSecurityPolicyRegistry.java +++ b/server/skillhub-auth/src/main/java/com/iflytek/skillhub/auth/policy/RouteSecurityPolicyRegistry.java @@ -32,6 +32,9 @@ public class RouteSecurityPolicyRegistry { RouteAuthorizationPolicy.permitAll(null, "/v3/api-docs/**"), RouteAuthorizationPolicy.permitAll(null, "/swagger-ui/**"), RouteAuthorizationPolicy.permitAll(null, "/swagger-ui.html"), + RouteAuthorizationPolicy.permitAll(null, "/doc.html"), + RouteAuthorizationPolicy.permitAll(null, "/webjars/**"), + RouteAuthorizationPolicy.permitAll(null, "/favicon.ico"), RouteAuthorizationPolicy.permitAll(null, "/.well-known/**"), RouteAuthorizationPolicy.roles(null, "/actuator/prometheus", "SUPER_ADMIN", "AUDITOR"), RouteAuthorizationPolicy.authenticated(HttpMethod.GET, "/api/v1/skills/*/star"), @@ -101,6 +104,8 @@ public class RouteSecurityPolicyRegistry { ApiTokenPolicy.allow(null, "/actuator/health"), ApiTokenPolicy.allow(null, "/v3/api-docs/**"), ApiTokenPolicy.allow(null, "/swagger-ui/**"), + ApiTokenPolicy.allow(null, "/doc.html"), + ApiTokenPolicy.allow(null, "/webjars/**"), ApiTokenPolicy.require(null, "/api/v1/tokens", "token:manage"), ApiTokenPolicy.require(null, "/api/v1/tokens/**", "token:manage"), ApiTokenPolicy.require(HttpMethod.DELETE, "/api/v1/skills/id/*", "skill:delete"), diff --git a/web/nginx.conf.template b/web/nginx.conf.template index 7589ba1f..64124fb7 100644 --- a/web/nginx.conf.template +++ b/web/nginx.conf.template @@ -10,64 +10,59 @@ server { gzip_types text/plain text/css application/json application/javascript text/xml; gzip_min_length 1000; - location /skillhub-web/ { - alias /usr/share/nginx/html/; - try_files $uri $uri/ /skillhub-web/index.html; + # 静态资源和 SPA 路由 + location / { + try_files $uri $uri/ /index.html; } - location /skillhub-web/api/ { - proxy_pass ${SKILLHUB_API_UPSTREAM}; + # API 代理到后端 server 服务 + location /api/ { + proxy_pass ${SKILLHUB_API_UPSTREAM}/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } - location /skillhub-web/oauth2/ { - proxy_pass ${SKILLHUB_API_UPSTREAM}; + location /oauth2/ { + proxy_pass ${SKILLHUB_API_UPSTREAM}/oauth2/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; } - location /skillhub-web/login/oauth2/ { - proxy_pass ${SKILLHUB_API_UPSTREAM}; + location /login/oauth2/ { + proxy_pass ${SKILLHUB_API_UPSTREAM}/login/oauth2/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; } - location /skillhub-web/.well-known/ { - proxy_pass ${SKILLHUB_API_UPSTREAM}; + location /.well-known/ { + proxy_pass ${SKILLHUB_API_UPSTREAM}/.well-known/; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; } - location /skillhub-web/assets/ { - alias /usr/share/nginx/html/assets/; + location /assets/ { expires 1y; add_header Cache-Control "public, immutable"; } - location = /skillhub-web/registry/skill.md { - alias /usr/share/nginx/html/registry/skill.md; + location = /registry/skill.md { default_type text/plain; add_header Content-Disposition "inline"; add_header X-Content-Type-Options "nosniff"; + try_files $uri =404; } - location = /skillhub-web/runtime-config.js { - alias /usr/share/nginx/html/runtime-config.js; + location = /runtime-config.js { add_header Cache-Control "no-store"; + try_files $uri =404; } location /nginx-health { return 200 'ok'; add_header Content-Type text/plain; } - - # 根路径重定向到子路径 - location = / { - return 301 /skillhub-web/; - } } diff --git a/web/src/bootstrap.ts b/web/src/bootstrap.ts index 8c8ddc6c..8f14ae53 100644 --- a/web/src/bootstrap.ts +++ b/web/src/bootstrap.ts @@ -7,7 +7,8 @@ async function loadRuntimeConfig() { await new Promise((resolve, reject) => { const script = document.createElement('script') - script.src = '/runtime-config.js' + const base = import.meta.env.BASE_URL || '/' + script.src = `${base}runtime-config.js` script.async = false script.onload = () => resolve() script.onerror = () => reject(new Error('Failed to load runtime config'))