110 lines
6.8 KiB
TypeScript
110 lines
6.8 KiB
TypeScript
import { cookies } from 'next/headers'
|
||
import { redirect } from 'next/navigation'
|
||
import { verifySharedJwt } from '@/lib/jwt'
|
||
import Header from '@/components/Header'
|
||
|
||
function siteUrl(url: string, domain: string): string {
|
||
if (process.env.NODE_ENV === 'production') {
|
||
return `https://${domain}`
|
||
}
|
||
return url
|
||
}
|
||
|
||
const CORE_SITES = [
|
||
{ name: '资产管理', url: 'http://127.0.0.1:6177', desc: 'GPU 服务器、存储服务器等硬件设备信息管理与实时监控', tag: 'CMDB', dot: '#2563eb', domain: 'assets.tlyq.ai' },
|
||
{ name: '工单跟踪', url: 'http://127.0.0.1:6176', desc: '故障工单全流程管理,SLA 自动计算,月度/周度报告导出', tag: 'ITS', dot: '#7c3aed', domain: 'issue.tlyq.ai' },
|
||
]
|
||
|
||
const OTHER_SITES = [
|
||
{ name: '官网', url: 'http://127.0.0.1:6173', desc: 'tlyq.ai 企业官方网站', tag: 'WWW', dot: '#059669', domain: 'www.tlyq.ai' },
|
||
{ name: '云平台', url: 'http://127.0.0.1:6174', desc: '云服务登录入口与资源概览', tag: 'CLOUD', dot: '#d97706', domain: 'cloud.tlyq.ai' },
|
||
{ name: 'Token 工厂', url: 'http://127.0.0.1:6175', desc: 'Token 管理与发放平台', tag: 'TOKEN', dot: '#e11d48', domain: 'token.tlyq.ai' },
|
||
{ name: '代码仓库', url: 'https://git.tlyq.ai', desc: 'Gitea 代码托管与版本管理', tag: 'GIT', dot: '#db2777', domain: 'git.tlyq.ai' },
|
||
]
|
||
|
||
const COLORS: Record<string, { light: string; tag: string }> = {
|
||
'#2563eb': { light: 'rgba(37,99,235,0.08)', tag: '#2563eb' },
|
||
'#7c3aed': { light: 'rgba(124,58,237,0.08)', tag: '#7c3aed' },
|
||
'#059669': { light: 'rgba(5,150,105,0.08)', tag: '#059669' },
|
||
'#d97706': { light: 'rgba(217,119,6,0.08)', tag: '#d97706' },
|
||
'#e11d48': { light: 'rgba(225,29,72,0.08)', tag: '#e11d48' },
|
||
'#db2777': { light: 'rgba(219,39,119,0.08)', tag: '#db2777' },
|
||
}
|
||
|
||
export default async function HomePage() {
|
||
const cookieStore = await cookies()
|
||
const sessionCookie = cookieStore.get('session')?.value
|
||
let username = ''
|
||
if (sessionCookie) {
|
||
try { username = JSON.parse(sessionCookie).username || '' } catch { }
|
||
}
|
||
if (!username) redirect('/login')
|
||
|
||
const tlyqToken = cookieStore.get('tlyq_session')?.value
|
||
let displayName = username
|
||
if (tlyqToken) {
|
||
const shared = verifySharedJwt(tlyqToken)
|
||
if (shared && shared.displayName && shared.displayName !== shared.username) {
|
||
displayName = shared.displayName
|
||
}
|
||
}
|
||
|
||
return (
|
||
<div style={{ minHeight: '100vh', background: 'var(--bg)' }}>
|
||
<Header />
|
||
|
||
<div style={{ maxWidth: 1160, margin: '0 auto', padding: '32px 28px 60px' }}>
|
||
<div style={{ marginBottom: 28 }}>
|
||
<div style={{ fontSize: 11, color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: '0.06em', marginBottom: 4 }}>tlyq.ai / OA PORTAL</div>
|
||
<h2 style={{ fontSize: 24, fontWeight: 700, color: 'var(--text)', margin: 0 }}>欢迎回来,{displayName}</h2>
|
||
</div>
|
||
|
||
<div style={{ fontSize: 12, fontWeight: 600, color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: '0.05em', margin: '0 0 12px', paddingBottom: 8, borderBottom: '1px solid var(--border)' }}>核心系统</div>
|
||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(280px, 1fr))', gap: 16 }}>
|
||
{CORE_SITES.map(site => {
|
||
const c = COLORS[site.dot]
|
||
return (
|
||
<a key={site.name} href={siteUrl(site.url, site.domain)} target="_blank" rel="noopener noreferrer" className="sc" style={{
|
||
display: 'flex', flexDirection: 'column', background: 'var(--bg-card)', border: '1px solid var(--border)',
|
||
borderRadius: 12, padding: 22, textDecoration: 'none', minHeight: 140,
|
||
boxShadow: '0 1px 2px rgba(0,0,0,0.04)', transition: 'all 0.2s',
|
||
}}>
|
||
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 6 }}>
|
||
<div style={{ width: 7, height: 7, borderRadius: '50%', background: site.dot, flexShrink: 0 }}></div>
|
||
<div style={{ fontSize: 15, fontWeight: 600, color: 'var(--text)', flex: 1 }}>{site.name}</div>
|
||
<span style={{ fontSize: 11, padding: '2px 8px', borderRadius: 10, background: c.light, color: c.tag, fontWeight: 500, letterSpacing: '0.03em' }}>{site.tag}</span>
|
||
</div>
|
||
<div style={{ fontSize: 13, color: 'var(--text-secondary)', lineHeight: 1.5, flex: 1 }}>{site.desc}</div>
|
||
<div className="ch" style={{ fontSize: 11, color: 'var(--text-muted)', marginTop: 'auto', paddingTop: 8, opacity: 0, transform: 'translateY(4px)', transition: 'all 0.25s ease' }}>{site.domain} →</div>
|
||
</a>
|
||
)
|
||
})}
|
||
</div>
|
||
|
||
<div style={{ fontSize: 12, fontWeight: 600, color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: '0.05em', margin: '36px 0 12px', paddingBottom: 8, borderBottom: '1px solid var(--border)' }}>其他站点</div>
|
||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(280px, 1fr))', gap: 16 }}>
|
||
{OTHER_SITES.map(site => {
|
||
const c = COLORS[site.dot]
|
||
return (
|
||
<a key={site.name} href={siteUrl(site.url, site.domain)} target="_blank" rel="noopener noreferrer" className="sc" style={{
|
||
display: 'flex', flexDirection: 'column', background: 'var(--bg-card)', border: '1px solid var(--border)',
|
||
borderRadius: 12, padding: 22, textDecoration: 'none', minHeight: 140,
|
||
boxShadow: '0 1px 2px rgba(0,0,0,0.04)', transition: 'all 0.2s',
|
||
}}>
|
||
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 6 }}>
|
||
<div style={{ width: 7, height: 7, borderRadius: '50%', background: site.dot, flexShrink: 0 }}></div>
|
||
<div style={{ fontSize: 15, fontWeight: 600, color: 'var(--text)', flex: 1 }}>{site.name}</div>
|
||
<span style={{ fontSize: 11, padding: '2px 8px', borderRadius: 10, background: c.light, color: c.tag, fontWeight: 500, letterSpacing: '0.03em' }}>{site.tag}</span>
|
||
</div>
|
||
<div style={{ fontSize: 13, color: 'var(--text-secondary)', lineHeight: 1.5, flex: 1 }}>{site.desc}</div>
|
||
<div className="ch" style={{ fontSize: 11, color: 'var(--text-muted)', marginTop: 'auto', paddingTop: 8, opacity: 0, transform: 'translateY(4px)', transition: 'all 0.25s ease' }}>{site.domain} →</div>
|
||
</a>
|
||
)
|
||
})}
|
||
</div>
|
||
<style>{`.sc:hover { border-color: #2563eb !important; box-shadow: 0 1px 3px rgba(0,0,0,0.06), 0 1px 2px rgba(0,0,0,0.04) !important; transform: translateY(-1px); } .sc:hover .ch { opacity: 1 !important; transform: translateY(0) !important; } .lo:hover { background: var(--bg-hover) !important; color: var(--text) !important; border-color: var(--text-muted) !important; }`}</style>
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|