diff --git a/admin-server/auth.go b/admin-server/auth.go index f0d22dc..47f3e62 100644 --- a/admin-server/auth.go +++ b/admin-server/auth.go @@ -160,7 +160,15 @@ input{width:100%;padding:11px 13px;border:1px solid var(--inbd);border-radius:10 input:focus{border-color:var(--ac);box-shadow:0 0 0 3px rgba(37,99,235,.12)} button[type=submit]{width:100%;margin-top:18px;padding:11px;border:0;border-radius:10px;background:var(--ac);color:#fff;font:inherit;font-weight:750;cursor:pointer} .err{padding:9px 11px;border-radius:9px;background:var(--errbg);color:var(--errtx);font-size:13px;margin-bottom:14px} -.foot{text-align:center;margin-top:22px;font-size:11px;color:var(--tx2)}.foot a{color:inherit;text-decoration:none} +.foot{margin-top:22px;font-size:11px;color:var(--tx2)} +.foot a{color:inherit;text-decoration:none} +/* 页脚:左列两行备案号 / 右列两行座右铭(与主站一致)。 + 登录卡片只有 400px,窄到放不下两列时退化为居中单列,避免挤压换行。 */ +.foot .navi-footer{display:grid;grid-template-columns:auto auto;grid-template-rows:auto auto;grid-auto-flow:column;gap:2px 12px;justify-content:space-between;align-items:center;text-align:left} +.foot .navi-footer-sep{display:none} +.foot .navi-quote{grid-column:2;justify-self:end;opacity:.85} +@media(max-width:430px){.foot .navi-footer{grid-template-columns:auto;grid-auto-flow:row;justify-content:center;text-align:center;gap:2px} +.foot .navi-quote{grid-column:1;justify-self:center}} @media(prefers-reduced-motion:reduce){*{transition:none!important}}
@@ -172,11 +180,14 @@ button[type=submit]{width:100%;margin-top:18px;padding:11px;border:0;border-radi func renderPortalLogin(w http.ResponseWriter, redirect, errText string) { w.Header().Set("Content-Type", "text/html; charset=utf-8") w.Header().Set("Cache-Control", "no-store") - title, subtitle, logo, icp, gongan := authPageInfo() - _ = portalLoginTemplate.Execute(w, map[string]string{ + title, subtitle, logo, _, _ := authPageInfo() + // 关键:页脚是一段 HTML,必须用 template.HTML 交给模板。 + // 此前用 map[string]string,html/template 会把整段标记转义成文本, + // 页面直接显示 +
认证页与门户页文案(留空=用内置默认)
@@ -503,6 +504,7 @@ async function loadPageInfo() { document.getElementById('p-gongan').value = gongan; // 能从备案号字段还原时,高级 HTML 留空,保存时按模板重新生成 document.getElementById('p-footer').value = (icp || gongan) ? '' : (PAGE.footer || ''); + document.getElementById('p-motto').value = PAGE.motto || ''; if (!PAGE.navLinks && PAGE.navLinks !== null) PAGE.navLinks = []; renderNavLinks(); } @@ -521,6 +523,7 @@ document.getElementById('save-info').addEventListener('click', async () => { gongan: document.getElementById('p-gongan').value, // 留空 = 交给服务端按备案号生成模板;填写则整段覆盖 footer: document.getElementById('p-footer').value, + motto: document.getElementById('p-motto').value, authTitle: document.getElementById('p-auth-title').value.trim(), authSubtitle: document.getElementById('p-auth-sub').value.trim(), diff --git a/portal/css/portal.css b/portal/css/portal.css index bb0ed5d..630c630 100644 --- a/portal/css/portal.css +++ b/portal/css/portal.css @@ -1,241 +1,255 @@ -:root, -[data-theme="light"] { - --bg-primary: #f8fafc; - --bg-secondary: #ffffff; - --bg-card: #ffffff; - --bg-input: #f1f5f9; - --bg-hover: rgba(241,245,249,0.8); - --text-primary: #1e293b; - --text-secondary: #64748b; - --text-muted: #94a3b8; - --border-color: #e2e8f0; - --accent: #2563eb; - --accent-bg: #dbeafe; - --accent-hover: #1d4ed8; - --danger: #dc2626; - --danger-bg: #fef2f2; - --success: #16a34a; - --success-bg: #f0fdf4; - --warning: #d97706; - --warning-bg: #fffbeb; - --shadow-sm: 0 1px 2px rgba(0,0,0,0.04); - --shadow-md: 0 4px 6px -1px rgba(0,0,0,0.06), 0 2px 4px -2px rgba(0,0,0,0.05); - --shadow-lg: 0 10px 15px -3px rgba(0,0,0,0.08), 0 4px 6px -4px rgba(0,0,0,0.04); - --radius: 10px; - --radius-sm: 6px; - --font: -apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif; - --mono: 'SFMono-Regular',Consolas,'Liberation Mono',Menlo,monospace; -} - -[data-theme="dark"] { - --bg-primary: #0f172a; - --bg-secondary: #1e293b; - --bg-card: #1e293b; - --bg-input: #334155; - --bg-hover: rgba(51,65,85,0.8); - --text-primary: #f1f5f9; - --text-secondary: #94a3b8; - --text-muted: #64748b; - --border-color: #334155; - --accent: #60a5fa; - --accent-bg: #1e3a5f; - --accent-hover: #93bbfd; - --danger: #f87171; - --danger-bg: #3b1a1a; - --success: #4ade80; - --success-bg: #1a3b1a; - --warning: #fbbf24; - --warning-bg: #3b2f1a; - --shadow-sm: 0 1px 2px rgba(0,0,0,0.2); - --shadow-md: 0 4px 6px -1px rgba(0,0,0,0.3), 0 2px 4px -2px rgba(0,0,0,0.25); - --shadow-lg: 0 10px 15px -3px rgba(0,0,0,0.35), 0 4px 6px -4px rgba(0,0,0,0.2); -} - -* { margin:0; padding:0; box-sizing:border-box } -html { height:100% } -body { - font-family:var(--font); - background:var(--bg-primary); - color:var(--text-primary); - min-height:100%; - line-height:1.5; - -webkit-font-smoothing:antialiased; - display:flex; - flex-direction:column; -} - -nav { - background:var(--bg-secondary); - border-bottom:1px solid var(--border-color); - height:52px; - display:flex; - align-items:center; - padding:0 24px; - position:sticky; - top:0; - z-index:100; - gap:4px; -} -nav .brand { - font-size:16px; - font-weight:700; - color:var(--accent); - margin-right:24px; - text-decoration:none; - white-space:nowrap; - display:flex; - align-items:center; - gap:8px; -} -nav .brand svg { width:20px; height:20px } -nav a { - padding:14px 16px; - color:var(--text-secondary); - text-decoration:none; - font-size:13px; - font-weight:500; - border-bottom:2px solid transparent; - transition:all .12s; -} -nav a:hover { color:var(--text-primary) } -nav a.active { color:var(--accent); border-bottom-color:var(--accent) } -nav .spacer { margin-left:auto } -nav .nav-btn { - background:none; - border:1px solid var(--border-color); - color:var(--text-secondary); - cursor:pointer; - padding:6px 12px; - border-radius:var(--radius-sm); - font-size:13px; - transition:all .15s; - text-decoration:none; - display:flex; - align-items:center; - gap:6px; -} -nav .nav-btn:hover { color:var(--accent); border-color:var(--accent) } - -.container { padding:32px 24px; max-width:1200px; margin:0 auto; flex:1; width:100% } - -.card { - background:var(--bg-card); - border:1px solid var(--border-color); - border-radius:var(--radius); - padding:20px; - transition:box-shadow .2s,border-color .2s; - box-shadow:var(--shadow-sm); -} - -.btn { - display:inline-flex; - align-items:center; - gap:6px; - padding:8px 16px; - border-radius:var(--radius-sm); - border:none; - font-size:13px; - font-weight:500; - cursor:pointer; - text-decoration:none; - transition:all .15s; - font-family:var(--font); - line-height:1.4; -} -.btn:active { transform:scale(.97) } -.btn-primary { background:var(--accent); color:#fff } -.btn-primary:hover { background:var(--accent-hover) } -.btn-ghost { - background:transparent; - border:1px solid var(--border-color); - color:var(--text-secondary); -} -.btn-ghost:hover { background:var(--bg-hover); color:var(--text-primary) } -.btn-sm { padding:5px 10px; font-size:12px } -.btn-lg { padding:10px 24px; font-size:15px } - -input,textarea,select { - background:var(--bg-input); - border:1px solid var(--border-color); - border-radius:var(--radius-sm); - padding:10px 14px; - color:var(--text-primary); - font-size:14px; - width:100%; - outline:none; - transition:border-color .15s,box-shadow .15s; - font-family:var(--font); -} -input:focus,textarea:focus,select:focus { - border-color:var(--accent); - box-shadow:0 0 0 3px var(--accent-bg); -} - -label { - display:block; - font-size:13px; - font-weight:500; - color:var(--text-secondary); - margin-bottom:4px; -} - -.grid-2 { display:grid; grid-template-columns:1fr 1fr; gap:16px } -.grid-3 { display:grid; grid-template-columns:1fr 1fr 1fr; gap:16px } -.grid-4 { display:grid; grid-template-columns:repeat(4,1fr); gap:16px } - -.badge { - display:inline-flex; - align-items:center; - gap:4px; - padding:2px 8px; - border-radius:4px; - font-size:11px; - font-weight:500; -} -.badge-blue { background:var(--accent-bg); color:var(--accent) } -.badge-green { background:var(--success-bg); color:var(--success) } -.badge-red { background:var(--danger-bg); color:var(--danger) } -.badge-warning { background:var(--warning-bg); color:var(--warning) } - -.error { color:var(--danger); font-size:13px; text-align:center; margin-bottom:12px } -.success { color:var(--success); font-size:13px; text-align:center; margin-bottom:12px } - -.footer { - text-align:center; - padding:20px; - color:var(--text-muted); - font-size:12px; - border-top:1px solid var(--border-color); - background:var(--bg-secondary); - margin-top:auto; -} - -.theme-btn { - background:none; - border:1px solid var(--border-color); - color:var(--text-secondary); - cursor:pointer; - padding:6px 10px; - border-radius:var(--radius-sm); - font-size:13px; - display:flex; - align-items:center; - gap:6px; - transition:all .15s; -} -.theme-btn:hover { color:var(--accent); border-color:var(--accent) } -.theme-btn svg { width:16px; height:16px } -.footer a { color:var(--text-muted); text-decoration:none } -.footer a:hover { color:var(--accent) } - -@media(max-width:768px) { - nav { padding:0 12px; gap:2px } - nav .brand { font-size:14px; margin-right:12px } - nav a { padding:16px 8px; font-size:12px } - .container { padding:16px } - .card { padding:14px } - .grid-2,.grid-3,.grid-4 { grid-template-columns:1fr } -} +:root, +[data-theme="light"] { + --bg-primary: #f8fafc; + --bg-secondary: #ffffff; + --bg-card: #ffffff; + --bg-input: #f1f5f9; + --bg-hover: rgba(241,245,249,0.8); + --text-primary: #1e293b; + --text-secondary: #64748b; + --text-muted: #94a3b8; + --border-color: #e2e8f0; + --accent: #2563eb; + --accent-bg: #dbeafe; + --accent-hover: #1d4ed8; + --danger: #dc2626; + --danger-bg: #fef2f2; + --success: #16a34a; + --success-bg: #f0fdf4; + --warning: #d97706; + --warning-bg: #fffbeb; + --shadow-sm: 0 1px 2px rgba(0,0,0,0.04); + --shadow-md: 0 4px 6px -1px rgba(0,0,0,0.06), 0 2px 4px -2px rgba(0,0,0,0.05); + --shadow-lg: 0 10px 15px -3px rgba(0,0,0,0.08), 0 4px 6px -4px rgba(0,0,0,0.04); + --radius: 10px; + --radius-sm: 6px; + --font: -apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif; + --mono: 'SFMono-Regular',Consolas,'Liberation Mono',Menlo,monospace; +} + +[data-theme="dark"] { + --bg-primary: #0f172a; + --bg-secondary: #1e293b; + --bg-card: #1e293b; + --bg-input: #334155; + --bg-hover: rgba(51,65,85,0.8); + --text-primary: #f1f5f9; + --text-secondary: #94a3b8; + --text-muted: #64748b; + --border-color: #334155; + --accent: #60a5fa; + --accent-bg: #1e3a5f; + --accent-hover: #93bbfd; + --danger: #f87171; + --danger-bg: #3b1a1a; + --success: #4ade80; + --success-bg: #1a3b1a; + --warning: #fbbf24; + --warning-bg: #3b2f1a; + --shadow-sm: 0 1px 2px rgba(0,0,0,0.2); + --shadow-md: 0 4px 6px -1px rgba(0,0,0,0.3), 0 2px 4px -2px rgba(0,0,0,0.25); + --shadow-lg: 0 10px 15px -3px rgba(0,0,0,0.35), 0 4px 6px -4px rgba(0,0,0,0.2); +} + +* { margin:0; padding:0; box-sizing:border-box } +html { height:100% } +body { + font-family:var(--font); + background:var(--bg-primary); + color:var(--text-primary); + min-height:100%; + line-height:1.5; + -webkit-font-smoothing:antialiased; + display:flex; + flex-direction:column; +} + +nav { + background:var(--bg-secondary); + border-bottom:1px solid var(--border-color); + height:52px; + display:flex; + align-items:center; + padding:0 24px; + position:sticky; + top:0; + z-index:100; + gap:4px; +} +nav .brand { + font-size:16px; + font-weight:700; + color:var(--accent); + margin-right:24px; + text-decoration:none; + white-space:nowrap; + display:flex; + align-items:center; + gap:8px; +} +nav .brand svg { width:20px; height:20px } +nav a { + padding:14px 16px; + color:var(--text-secondary); + text-decoration:none; + font-size:13px; + font-weight:500; + border-bottom:2px solid transparent; + transition:all .12s; +} +nav a:hover { color:var(--text-primary) } +nav a.active { color:var(--accent); border-bottom-color:var(--accent) } +nav .spacer { margin-left:auto } +nav .nav-btn { + background:none; + border:1px solid var(--border-color); + color:var(--text-secondary); + cursor:pointer; + padding:6px 12px; + border-radius:var(--radius-sm); + font-size:13px; + transition:all .15s; + text-decoration:none; + display:flex; + align-items:center; + gap:6px; +} +nav .nav-btn:hover { color:var(--accent); border-color:var(--accent) } + +.container { padding:32px 24px; max-width:1200px; margin:0 auto; flex:1; width:100% } + +.card { + background:var(--bg-card); + border:1px solid var(--border-color); + border-radius:var(--radius); + padding:20px; + transition:box-shadow .2s,border-color .2s; + box-shadow:var(--shadow-sm); +} + +.btn { + display:inline-flex; + align-items:center; + gap:6px; + padding:8px 16px; + border-radius:var(--radius-sm); + border:none; + font-size:13px; + font-weight:500; + cursor:pointer; + text-decoration:none; + transition:all .15s; + font-family:var(--font); + line-height:1.4; +} +.btn:active { transform:scale(.97) } +.btn-primary { background:var(--accent); color:#fff } +.btn-primary:hover { background:var(--accent-hover) } +.btn-ghost { + background:transparent; + border:1px solid var(--border-color); + color:var(--text-secondary); +} +.btn-ghost:hover { background:var(--bg-hover); color:var(--text-primary) } +.btn-sm { padding:5px 10px; font-size:12px } +.btn-lg { padding:10px 24px; font-size:15px } + +input,textarea,select { + background:var(--bg-input); + border:1px solid var(--border-color); + border-radius:var(--radius-sm); + padding:10px 14px; + color:var(--text-primary); + font-size:14px; + width:100%; + outline:none; + transition:border-color .15s,box-shadow .15s; + font-family:var(--font); +} +input:focus,textarea:focus,select:focus { + border-color:var(--accent); + box-shadow:0 0 0 3px var(--accent-bg); +} + +label { + display:block; + font-size:13px; + font-weight:500; + color:var(--text-secondary); + margin-bottom:4px; +} + +.grid-2 { display:grid; grid-template-columns:1fr 1fr; gap:16px } +.grid-3 { display:grid; grid-template-columns:1fr 1fr 1fr; gap:16px } +.grid-4 { display:grid; grid-template-columns:repeat(4,1fr); gap:16px } + +.badge { + display:inline-flex; + align-items:center; + gap:4px; + padding:2px 8px; + border-radius:4px; + font-size:11px; + font-weight:500; +} +.badge-blue { background:var(--accent-bg); color:var(--accent) } +.badge-green { background:var(--success-bg); color:var(--success) } +.badge-red { background:var(--danger-bg); color:var(--danger) } +.badge-warning { background:var(--warning-bg); color:var(--warning) } + +.error { color:var(--danger); font-size:13px; text-align:center; margin-bottom:12px } +.success { color:var(--success); font-size:13px; text-align:center; margin-bottom:12px } + +.footer { + text-align:center; + padding:20px; + color:var(--text-muted); + font-size:12px; + border-top:1px solid var(--border-color); + background:var(--bg-secondary); + margin-top:auto; +} + +.theme-btn { + background:none; + border:1px solid var(--border-color); + color:var(--text-secondary); + cursor:pointer; + padding:6px 10px; + border-radius:var(--radius-sm); + font-size:13px; + display:flex; + align-items:center; + gap:6px; + transition:all .15s; +} +.theme-btn:hover { color:var(--accent); border-color:var(--accent) } +.theme-btn svg { width:16px; height:16px } +.footer a { color:var(--text-muted); text-decoration:none } +.footer a:hover { color:var(--accent) } + +/* 页脚内容:左列两行备案号 / 右列两行座右铭(与主站、登录页一致)。 + 分隔符保留在标记里但隐藏 —— 两列本身已经分开了。 */ +.footer .navi-footer { + display:grid; grid-template-columns:auto auto; grid-template-rows:auto auto; + grid-auto-flow:column; gap:2px 14px; justify-content:space-between; + align-items:center; text-align:left; max-width:1100px; margin:0 auto; +} +.footer .navi-footer-sep { display:none } +.footer .navi-quote { grid-column:2; justify-self:end; opacity:.85 } +@media(max-width:520px) { + .footer .navi-footer { grid-template-columns:auto; grid-auto-flow:row; justify-content:center; text-align:center; gap:2px } + .footer .navi-quote { grid-column:1; justify-self:center } +} + +@media(max-width:768px) { + nav { padding:0 12px; gap:2px } + nav .brand { font-size:14px; margin-right:12px } + nav a { padding:16px 8px; font-size:12px } + .container { padding:16px } + .card { padding:14px } + .grid-2,.grid-3,.grid-4 { grid-template-columns:1fr } +} /* ===== enhanced decorative & hero styles (added 2026-08-13) ===== */ body { position:relative }