- 站点设置新增 card.opacity(40–100)与 card.blur,后台「首页管理 → 卡片外观」可调 - 前台所有卡片(首页 / 分组页 / 详情 / 侧栏)共用一套 CSS 变量 - 顺带带上上一轮:背景缓存、搜索记忆、明暗图标跟随实际状态、卡片描边/阴影、分组页卡片外壳
140 lines
4.1 KiB
TypeScript
140 lines
4.1 KiB
TypeScript
import { Brand, Icon, IconButton, Tag, Ticker } from '@stash/ui'
|
||
import {
|
||
fillHeaderText,
|
||
type HeaderItem,
|
||
type SettingsTone,
|
||
type SiteMetaSettings,
|
||
} from '../../settings'
|
||
|
||
/**
|
||
* 顶部栏:左品牌、中间滚动信息(可在 /admin 配置)、右侧操作图标。
|
||
* 品牌与操作图标是否出现,都来自「页头」Tab 的站点设置。
|
||
* 外壳(品牌、跑马灯)都用组件库,这里只拼内容。
|
||
*/
|
||
type SiteHeaderProps = {
|
||
projectCount: number
|
||
/** 用于展示的第一个项目名,没有项目时留空 */
|
||
sampleProject?: string
|
||
live: boolean
|
||
/** 页头滚动信息;为空时用默认三条 */
|
||
headerItems: HeaderItem[]
|
||
headerEnabled: boolean
|
||
/** 滚动一轮的秒数 */
|
||
headerSpeed: number
|
||
/** 信息条目之间的间距(px) */
|
||
headerGap?: number
|
||
/** 品牌与操作工具配置 */
|
||
site: SiteMetaSettings
|
||
/** 站点设置是否已加载;未加载时不渲染依赖配置的图标,避免先显示再消失 */
|
||
ready?: boolean
|
||
/** 是否已登录:决定右侧是「登录」还是「退出登录」 */
|
||
authenticated: boolean
|
||
username?: string
|
||
/** 刷新中:刷新按钮转圈 */
|
||
refreshing?: boolean
|
||
/** 当前是否为深色,决定明暗按钮的图标与文案 */
|
||
dark?: boolean
|
||
onRefresh: () => void
|
||
onToggleTheme: () => void
|
||
onLogin: () => void
|
||
onLogout: () => void
|
||
onSettings: () => void
|
||
}
|
||
|
||
const tagTone: Record<SettingsTone, 'neutral' | 'primary' | 'success'> = {
|
||
plain: 'neutral',
|
||
neutral: 'neutral',
|
||
primary: 'primary',
|
||
success: 'success',
|
||
}
|
||
|
||
export function SiteHeader({
|
||
projectCount,
|
||
sampleProject,
|
||
live,
|
||
headerItems,
|
||
headerEnabled,
|
||
headerSpeed,
|
||
headerGap,
|
||
site,
|
||
ready = true,
|
||
authenticated,
|
||
username,
|
||
refreshing = false,
|
||
dark = false,
|
||
onRefresh,
|
||
onToggleTheme,
|
||
onLogin,
|
||
onLogout,
|
||
onSettings,
|
||
}: SiteHeaderProps) {
|
||
const context = { count: projectCount, project: sampleProject, live }
|
||
|
||
return (
|
||
<div className="site-header-inner">
|
||
<Brand
|
||
href="/"
|
||
name={site.brand.name}
|
||
mark={site.brand.mark}
|
||
logo={site.brand.logo}
|
||
/>
|
||
|
||
<div className="header-ticker-slot">
|
||
{ready && headerEnabled && (
|
||
<Ticker speed={headerSpeed} gap={headerGap} label="运行状态" className="header-ticker">
|
||
{headerItems.map((item, index) => (
|
||
<span className="header-ticker-item" key={`${index}-${item.text}`}>
|
||
{item.tag !== undefined && item.tag !== null && item.tag !== '' && (
|
||
<Tag tone={tagTone[item.tone]} shape="rounded">
|
||
{item.tag}
|
||
</Tag>
|
||
)}
|
||
{fillHeaderText(item.text, context)}
|
||
</span>
|
||
))}
|
||
</Ticker>
|
||
)}
|
||
</div>
|
||
|
||
<div className="header-actions">
|
||
{ready && (
|
||
<>
|
||
{site.actions.theme && (
|
||
<IconButton
|
||
label={dark ? '切换到浅色' : '切换到深色'}
|
||
icon={<Icon name={dark ? 'moon_line' : 'sun_line'} />}
|
||
onClick={onToggleTheme}
|
||
/>
|
||
)}
|
||
{site.actions.refresh && (
|
||
<IconButton
|
||
label="刷新(重扫项目并重拉内容)"
|
||
icon={<Icon name="lightning_line" />}
|
||
spinning={refreshing}
|
||
onClick={onRefresh}
|
||
/>
|
||
)}
|
||
{site.actions.settings && authenticated && (
|
||
<IconButton
|
||
label="站点设置"
|
||
icon={<Icon name="settings_1_line" />}
|
||
onClick={onSettings}
|
||
/>
|
||
)}
|
||
{site.actions.session &&
|
||
(authenticated ? (
|
||
<IconButton
|
||
label={username === undefined ? '退出登录' : `退出登录(${username})`}
|
||
icon={<Icon name="exit_line" />}
|
||
onClick={onLogout}
|
||
/>
|
||
) : (
|
||
<IconButton label="登录" icon={<Icon name="user_3_line" />} onClick={onLogin} />
|
||
))}
|
||
</>
|
||
)}
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|