feat(portal-shell): v2.0 P0 shadcn standardization + security + streaming + error handling
- shadcn/ui 标准化:废弃纸感令牌,统一 bg-background/text-foreground 等 - Tailwind v4 + @theme inline,移除 tailwind.config.js - React 19 use() + Suspense 流式渲染,首屏骨架秒出 - 三级错误边界:Route → Section → Widget 层层兜底 - 错误上报:useErrorReport → sendBeacon → /api/log mock 端点 - 三层安全边界:L1 角色门禁 / L2 权限点门禁 / L3 数据范围 - 权限位图 base36 压缩:67 权限点 → ~14 字符,JWT 体积减少 ≥ 99% - notify 统一 Toast 封装,禁止业务直接 import sonner - PluginBoundary 替代 PluginLoader(错误边界 + Suspense + Skeleton 三件套) 验证:typecheck 0 错误 / lint 0 错误 / build 6 路由生成成功
This commit is contained in:
54
scripts/dev-service.ps1
Normal file
54
scripts/dev-service.ps1
Normal file
@@ -0,0 +1,54 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
加载 .env 并启动单个服务(内部辅助脚本)
|
||||
.DESCRIPTION
|
||||
从项目根 .env 加载环境变量到当前进程,然后启动指定服务。
|
||||
用法:powershell -File scripts\dev-service.ps1 <package-name>
|
||||
例: powershell -File scripts\dev-service.ps1 @edu/iam-service
|
||||
#>
|
||||
param(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]$Filter
|
||||
)
|
||||
|
||||
$ProjectRoot = Split-Path -Parent $PSScriptRoot
|
||||
$envFile = Join-Path $ProjectRoot ".env"
|
||||
|
||||
if (Test-Path $envFile) {
|
||||
$envLines = Get-Content $envFile
|
||||
foreach ($line in $envLines) {
|
||||
$line = $line.Trim()
|
||||
if (-not $line -or $line.StartsWith("#") -or -not $line.Contains("=")) { continue }
|
||||
$idx = $line.IndexOf("=")
|
||||
$key = $line.Substring(0, $idx).Trim()
|
||||
$val = $line.Substring($idx + 1).Trim()
|
||||
if ($val.StartsWith('"') -and $val.EndsWith('"')) { $val = $val.Substring(1, $val.Length - 2) }
|
||||
if ($val.StartsWith("'") -and $val.EndsWith("'")) { $val = $val.Substring(1, $val.Length - 2) }
|
||||
[Environment]::SetEnvironmentVariable($key, $val, "Process")
|
||||
}
|
||||
Write-Host "[dev-service] Loaded .env" -ForegroundColor Green
|
||||
}
|
||||
|
||||
# 补充 dev 模式默认值
|
||||
if (-not $env:DEV_MODE) { $env:DEV_MODE = "true" }
|
||||
if (-not $env:OTEL_EXPORTER_OTLP_ENDPOINT) { $env:OTEL_EXPORTER_OTLP_ENDPOINT = "http://localhost:4318" }
|
||||
if (-not $env:NEO4J_URI) { $env:NEO4J_URI = "bolt://localhost:7687" }
|
||||
if (-not $env:NEO4J_USER) { $env:NEO4J_USER = "neo4j" }
|
||||
if (-not $env:CLICKHOUSE_URL) { $env:CLICKHOUSE_URL = "http://localhost:8123" }
|
||||
if (-not $env:ES_URL) { $env:ES_URL = "http://localhost:9200" }
|
||||
if (-not $env:ROUTER_AUTH_SECRET) { $env:ROUTER_AUTH_SECRET = "dev-router-secret" }
|
||||
if (-not $env:CLASSES_SERVICE_URL) { $env:CLASSES_SERVICE_URL = "http://localhost:3001" }
|
||||
if (-not $env:IAM_SERVICE_URL) { $env:IAM_SERVICE_URL = "http://localhost:3002" }
|
||||
if (-not $env:APOLLO_ROUTER_URL) { $env:APOLLO_ROUTER_URL = "http://localhost:3000" }
|
||||
if (-not $env:CORE_EDU_SERVICE_URL) { $env:CORE_EDU_SERVICE_URL = "http://localhost:3004" }
|
||||
if (-not $env:CONTENT_SERVICE_URL) { $env:CONTENT_SERVICE_URL = "http://localhost:3005" }
|
||||
if (-not $env:DATA_ANA_SERVICE_URL) { $env:DATA_ANA_SERVICE_URL = "http://localhost:3006" }
|
||||
if (-not $env:MSG_SERVICE_URL) { $env:MSG_SERVICE_URL = "http://localhost:3007" }
|
||||
if (-not $env:AI_SERVICE_URL) { $env:AI_SERVICE_URL = "http://localhost:3008" }
|
||||
if (-not $env:CORS_ORIGINS) { $env:CORS_ORIGINS = "http://localhost:4000,http://localhost:4010" }
|
||||
if (-not $env:JWKS_URL) { $env:JWKS_URL = "http://localhost:3002/v1/iam/.well-known/jwks.json" }
|
||||
if (-not $env:PUSH_INTERNAL_TOKEN) { $env:PUSH_INTERNAL_TOKEN = "edu-internal-token" }
|
||||
|
||||
Write-Host "[dev-service] Starting $Filter with DEV_MODE=$($env:DEV_MODE)" -ForegroundColor Cyan
|
||||
Set-Location $ProjectRoot
|
||||
pnpm --filter $Filter dev
|
||||
Reference in New Issue
Block a user