diff --git a/src/handlers/setupPages.ts b/src/handlers/setupPages.ts index 87a146b..cc8b11c 100644 --- a/src/handlers/setupPages.ts +++ b/src/handlers/setupPages.ts @@ -21,10 +21,12 @@ function t(lang: Lang, key: string): string { cfgDescDefault: '检测到你正在使用示例/默认 JWT_SECRET。为了安全起见,请先修改为随机强密钥后再注册/使用。', cfgDescTooShort: '检测到 JWT_SECRET 长度不足 32 个字符。为了安全起见,请使用至少 32 位的随机字符串。', cfgStepsTitle: '如何在 Cloudflare 修改 JWT_SECRET', - cfgSteps: '打开 Cloudflare 控制台 → Workers 和 Pages → 选择 nodewarden → 设置 → 变量和机密 → 添加变量。\n类型:密钥\n名称:JWT_SECRET\n值:粘贴你生成的随机密钥\n保存后,等待重新部署生效。', + cfgStepsAdd: '打开 Cloudflare 控制台 → Workers 和 Pages → 选择 nodewarden → 设置 → 变量和机密 → 添加变量。\n类型:密钥\n名称:JWT_SECRET\n值:粘贴你生成的随机密钥\n保存后,等待重新部署生效。', + cfgStepsEdit: '打开 Cloudflare 控制台 → Workers 和 Pages → 选择 nodewarden → 设置 → 变量和机密 → 找到 JWT_SECRET 并编辑。\n类型:密钥\n名称:JWT_SECRET\n值:替换为新的随机强密钥\n保存后,等待重新部署生效。', cfgGenTitle: '随机密钥生成器', cfgGenHint: '建议长度:至少 32 字符(推荐 64+)。点击刷新生成新的随机值。', cfgCopy: '复制', + cfgCopied: '已复制', cfgRefresh: '刷新', // Shared @@ -42,10 +44,12 @@ function t(lang: Lang, key: string): string { cfgDescDefault: 'You are using the sample/default JWT_SECRET. For safety, please change it to a strong random secret before registration/usage.', cfgDescTooShort: 'JWT_SECRET is shorter than 32 characters. For safety, use a random string with at least 32 characters.', cfgStepsTitle: 'How to set JWT_SECRET in Cloudflare', - cfgSteps: 'Open Cloudflare Dashboard → Workers & Pages → select nodewarden → Settings → Variables and Secrets → Add variable.\nType: Secret\nName: JWT_SECRET\nValue: paste a random secret\nSave, and wait for redeploy to take effect.', + cfgStepsAdd: 'Open Cloudflare Dashboard → Workers & Pages → select nodewarden → Settings → Variables and Secrets → Add variable.\nType: Secret\nName: JWT_SECRET\nValue: paste a random secret\nSave, and wait for redeploy to take effect.', + cfgStepsEdit: 'Open Cloudflare Dashboard → Workers & Pages → select nodewarden → Settings → Variables and Secrets → find JWT_SECRET and edit it.\nType: Secret\nName: JWT_SECRET\nValue: replace with a new strong random secret\nSave, and wait for redeploy to take effect.', cfgGenTitle: 'Random secret generator', cfgGenHint: 'Recommended length: 32+ characters (64+ preferred). Click refresh to generate a new one.', cfgCopy: 'Copy', + cfgCopied: 'Copied', cfgRefresh: 'Refresh', // Shared @@ -61,21 +65,16 @@ function baseStyles(): string { return ` :root { color-scheme: light; - --bg0: #0b0b0f; - --bg1: #0f1020; - --card: rgba(255, 255, 255, 0.08); - --card2: rgba(255, 255, 255, 0.06); - --border: rgba(255, 255, 255, 0.14); - --text: rgba(255, 255, 255, 0.92); - --muted: rgba(255, 255, 255, 0.62); - --muted2: rgba(255, 255, 255, 0.52); - --accent: #0a84ff; - --accent2: #64d2ff; - --danger: #ff453a; - --ok: #32d74b; - --shadow: 0 16px 60px rgba(0, 0, 0, 0.50); - --radius: 18px; - --radius2: 14px; + --bg: #f3f4f6; + --card: #ffffff; + --border: #d0d5dd; + --text: #101828; + --muted: #475467; + --muted2: #667085; + --accent: #111418; + --shadow: 0 16px 44px rgba(16, 24, 40, 0.08); + --radius: 20px; + --radius2: 16px; --mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; } * { box-sizing: border-box; } @@ -83,107 +82,112 @@ function baseStyles(): string { body { margin: 0; font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro Text", "Segoe UI", Roboto, Helvetica, Arial, sans-serif; - background: - radial-gradient(900px 600px at 15% 10%, rgba(100, 210, 255, 0.25), transparent 60%), - radial-gradient(900px 600px at 85% 20%, rgba(10, 132, 255, 0.22), transparent 60%), - radial-gradient(900px 600px at 50% 90%, rgba(50, 215, 75, 0.10), transparent 60%), - linear-gradient(180deg, var(--bg0), var(--bg1)); + background: var(--bg); color: var(--text); display: flex; align-items: center; justify-content: center; - padding: 24px; + padding: 40px 24px; } - .shell { width: max(500px); } + .shell { width: min(920px, 100%); } .panel { - padding: 22px; + padding: 40px; border: 1px solid var(--border); - background: rgba(255,255,255,0.06); + background: var(--card); border-radius: var(--radius); box-shadow: var(--shadow); - backdrop-filter: blur(16px); - -webkit-backdrop-filter: blur(16px); } .top { display: flex; gap: 14px; align-items: center; - margin-bottom: 14px; + margin-bottom: 10px; } .mark { - width: 46px; - height: 46px; - border-radius: 14px; - background: linear-gradient(135deg, rgba(10,132,255,0.85), rgba(100,210,255,0.55)); - border: 1px solid rgba(255,255,255,0.20); - box-shadow: 0 10px 40px rgba(10, 132, 255, 0.30); + width: 60px; + height: 60px; + border-radius: 16px; + background: #111418; + border: 1px solid #111418; display: flex; align-items: center; justify-content: center; + font-size: 24px; font-weight: 800; - letter-spacing: 1px; - color: rgba(255,255,255,0.96); + letter-spacing: 0.6px; + line-height: 1; + color: #ffffff; text-transform: uppercase; user-select: none; } .title { display: flex; flex-direction: column; gap: 4px; } - .title h1 { font-size: 22px; margin: 0; letter-spacing: -0.3px; } - .title p { margin: 0; color: var(--muted); font-size: 13px; line-height: 1.5; } + .title h1 { font-size: 30px; margin: 0; letter-spacing: -0.6px; } + .title p { margin: 0; color: var(--muted); font-size: 15px; line-height: 1.6; } - h2 { font-size: 16px; margin: 14px 0 10px 0; letter-spacing: -0.2px; } - .lead { font-size: 13px; line-height: 1.7; color: rgba(255,255,255,0.86); } + h2 { font-size: 22px; margin: 20px 0 14px 0; letter-spacing: -0.3px; } + .lead { font-size: 16px; line-height: 1.75; color: #344054; } .kv { border-radius: var(--radius2); - border: 1px solid rgba(255,255,255,0.14); - background: rgba(255,255,255,0.05); - padding: 14px; - margin-top: 12px; + border: 1px solid var(--border); + background: #fafbfc; + padding: 18px; + margin-top: 0; } - .kv h3 { margin: 0 0 8px 0; font-size: 13px; color: rgba(255,255,255,0.86); } - .kv p { margin: 0; font-size: 12px; line-height: 1.55; color: var(--muted); white-space: pre-line; } + .kv h3 { margin: 0 0 10px 0; font-size: 17px; color: #1d2939; } + .kv p { margin: 0; font-size: 15px; line-height: 1.7; color: var(--muted); white-space: pre-line; } .server { margin-top: 10px; font-family: var(--mono); - font-size: 12px; - padding: 10px 12px; - border-radius: 12px; - background: rgba(0,0,0,0.25); - border: 1px solid rgba(255,255,255,0.12); + font-size: 14px; + padding: 12px 14px; + border-radius: 14px; + background: #ffffff; + border: 1px solid #d5dae1; word-break: break-all; - color: rgba(255,255,255,0.90); + color: #111418; } .row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; } + .grid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 12px; + margin-top: 12px; + } + @media (max-width: 760px) { .grid { grid-template-columns: 1fr; } } .btn { - height: 38px; - padding: 0 12px; - border-radius: 12px; - border: 1px solid rgba(255,255,255,0.18); - background: rgba(0,0,0,0.18); - color: rgba(255,255,255,0.92); + height: 46px; + padding: 0 14px; + border-radius: 14px; + border: 1px solid #d5dae1; + background: #ffffff; + color: #111418; font-weight: 700; + font-size: 15px; cursor: pointer; } .btn.primary { - background: linear-gradient(135deg, rgba(10,132,255,0.95), rgba(100,210,255,0.60)); + border-color: #111418; + background: #111418; + color: #ffffff; } .btn:disabled { opacity: 0.55; cursor: not-allowed; } - a { color: rgba(100, 210, 255, 0.92); text-decoration: none; } + a { color: #175cd3; text-decoration: none; } a:hover { text-decoration: underline; } .footer { - margin-top: 18px; - padding-top: 14px; - border-top: 1px solid rgba(255,255,255,0.10); + margin-top: 24px; + padding-top: 18px; + border-top: 1px solid var(--border); display: flex; justify-content: space-between; gap: 12px; flex-wrap: wrap; - font-size: 12px; - color: rgba(255,255,255,0.55); + font-size: 14px; + color: var(--muted2); } `; } @@ -194,6 +198,7 @@ export function renderJwtSecretWarningPage(request: Request, state: JwtSecretSta const lang: Lang = isChineseFromRequest(request) ? 'zh' : 'en'; const descKey = state === 'missing' ? 'cfgDescMissing' : state === 'default' ? 'cfgDescDefault' : 'cfgDescTooShort'; + const stepsKey = state === 'missing' ? 'cfgStepsAdd' : 'cfgStepsEdit'; return ` @@ -217,24 +222,26 @@ export function renderJwtSecretWarningPage(request: Request, state: JwtSecretSta
${t(lang, 'cfgSteps') - .replace(/^类型:密钥/m, '类型:密钥') - .replace(/^名称:JWT_SECRET/m, '名称:JWT_SECRET') - .replace(/^Type: Secret/m, 'Type: Secret') - .replace(/^Name: JWT_SECRET/m, 'Name: JWT_SECRET') - }
-${t(lang, stepsKey) + .replace(/^类型:密钥/m, '类型:密钥') + .replace(/^名称:JWT_SECRET/m, '名称:JWT_SECRET') + .replace(/^Type: Secret/m, 'Type: Secret') + .replace(/^Name: JWT_SECRET/m, 'Name: JWT_SECRET') + }
+${t(lang, 'cfgGenHint')}
- - -${t(lang, 'cfgGenHint')}
+ + +