R67 A1-A6:官网风格前端 UI 刷新
这个提交包含在:
@@ -75,10 +75,10 @@ function renderNavItem(item: ResolvedNavItem, onNavigate?: () => void) {
|
||||
onClick={() => onNavigate?.()}
|
||||
className={({ isActive }) =>
|
||||
cn(
|
||||
"group flex items-center gap-3 rounded-2xl px-3 py-2.5 text-sm transition-colors",
|
||||
"group flex items-center gap-3 rounded-2xl px-3 py-2.5 text-sm transition duration-200",
|
||||
isActive
|
||||
? "bg-zinc-900 text-white shadow-sm"
|
||||
: "text-zinc-600 hover:bg-zinc-50 hover:text-zinc-900",
|
||||
? "bg-primary text-white shadow-sm"
|
||||
: "text-[var(--color-text-secondary)] hover:-translate-y-0.5 hover:bg-white/70 hover:text-[var(--color-text-primary)] hover:shadow-sm",
|
||||
)
|
||||
}
|
||||
>
|
||||
@@ -88,8 +88,8 @@ function renderNavItem(item: ResolvedNavItem, onNavigate?: () => void) {
|
||||
className={cn(
|
||||
"flex size-9 items-center justify-center rounded-xl border text-[20px] transition-colors",
|
||||
isActive
|
||||
? "border-white/15 bg-white/10 text-white"
|
||||
: "border-zinc-200 bg-white text-zinc-500 group-hover:border-zinc-300 group-hover:text-zinc-900",
|
||||
? "border-white/15 bg-white/15 text-white"
|
||||
: "border-slate-200 bg-white text-[var(--color-text-tertiary)] group-hover:border-slate-300 group-hover:text-primary",
|
||||
)}
|
||||
>
|
||||
<span className="material-symbols-outlined text-[20px]">{item.icon}</span>
|
||||
@@ -109,8 +109,8 @@ function renderSection(title: string, description: string, items: ResolvedNavIte
|
||||
return (
|
||||
<section className="space-y-2">
|
||||
<div className="px-3">
|
||||
<div className="text-[11px] font-semibold uppercase tracking-[0.18em] text-zinc-400">{title}</div>
|
||||
<div className="mt-1 text-xs text-zinc-500">{description}</div>
|
||||
<div className="text-[11px] font-bold uppercase tracking-[0.2em] text-primary/70">{title}</div>
|
||||
<div className="mt-1 text-xs leading-5 text-[var(--color-text-tertiary)]">{description}</div>
|
||||
</div>
|
||||
<div className="space-y-1.5">{items.map((item) => renderNavItem(item, onNavigate))}</div>
|
||||
</section>
|
||||
@@ -123,13 +123,13 @@ function renderBackupSection(items: ResolvedNavItem[], onNavigate?: () => void)
|
||||
}
|
||||
|
||||
return (
|
||||
<details className="rounded-2xl border border-zinc-200 bg-zinc-50/80 px-3 py-3">
|
||||
<summary className="flex cursor-pointer list-none items-center justify-between gap-3 rounded-xl px-2 py-1.5 text-sm font-semibold text-zinc-700">
|
||||
<details className="rounded-2xl border border-slate-200 bg-slate-50/80 px-3 py-3">
|
||||
<summary className="flex cursor-pointer list-none items-center justify-between gap-3 rounded-xl px-2 py-1.5 text-sm font-semibold text-[var(--color-text-primary)]">
|
||||
<div>
|
||||
<div>备用模块</div>
|
||||
<div className="mt-0.5 text-xs font-normal text-zinc-500">默认收起,不干扰主路径</div>
|
||||
<div className="mt-0.5 text-xs font-normal text-[var(--color-text-secondary)]">默认收起,不干扰主路径</div>
|
||||
</div>
|
||||
<span className="text-xs font-medium text-zinc-400">按需展开</span>
|
||||
<span className="text-xs font-medium text-[var(--color-text-tertiary)]">按需展开</span>
|
||||
</summary>
|
||||
<div className="mt-3 space-y-1.5 pb-1">{items.map((item) => renderNavItem(item, onNavigate))}</div>
|
||||
</details>
|
||||
|
||||
@@ -3,16 +3,19 @@ import { NavLinks } from "./NavLinks";
|
||||
|
||||
export function Sidebar() {
|
||||
return (
|
||||
<aside className="fixed inset-y-0 z-20 hidden w-72 overflow-hidden border-r border-zinc-200 bg-white/95 backdrop-blur lg:flex lg:flex-col">
|
||||
<div className="border-b border-zinc-200 px-6 py-6">
|
||||
<aside className="fixed inset-y-0 z-20 hidden w-72 overflow-hidden border-r border-slate-200 bg-white/92 shadow-[18px_0_50px_rgba(15,23,42,0.08)] backdrop-blur-xl lg:flex lg:flex-col">
|
||||
<div className="border-b border-slate-200 px-6 py-6">
|
||||
<AppBrand />
|
||||
<div className="mt-4 rounded-2xl border border-zinc-200 bg-zinc-50 px-4 py-3 text-sm text-zinc-600">
|
||||
<div className="font-medium text-zinc-900">统一工作台</div>
|
||||
<div className="mt-1">先看今天要做什么,再进入具体模块处理。</div>
|
||||
<div className="mt-5 overflow-hidden rounded-3xl border border-slate-200 bg-[linear-gradient(135deg,rgba(0,57,138,0.08),rgba(19,168,184,0.10))] px-4 py-4 text-sm text-[var(--color-text-secondary)]">
|
||||
<div className="flex items-center gap-2 font-semibold text-[var(--color-text-primary)]">
|
||||
<span className="size-2 rounded-full bg-primary" />
|
||||
今日工作台
|
||||
</div>
|
||||
<div className="mt-2 leading-6">先处理待办和团队状态,再进入具体模块。</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="min-h-0 flex-1 overflow-y-auto px-4 py-5">
|
||||
<div className="min-h-0 flex-1 overflow-y-auto px-4 py-5 [scrollbar-width:thin]">
|
||||
<NavLinks />
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
@@ -135,7 +135,7 @@ export function Topbar() {
|
||||
|
||||
return (
|
||||
<>
|
||||
<header className="sticky top-0 z-10 border-b border-zinc-200/80 bg-white/90 px-4 py-4 backdrop-blur sm:px-8">
|
||||
<header className="sticky top-0 z-10 border-b border-slate-200/80 bg-white/88 px-4 py-3 shadow-[0_10px_30px_rgba(15,23,42,0.06)] backdrop-blur-xl sm:px-8">
|
||||
<div className="flex items-center justify-between gap-4">
|
||||
<div className="flex min-w-0 items-center gap-3">
|
||||
<Dialog open={mobileNavOpen} onOpenChange={setMobileNavOpen}>
|
||||
@@ -145,9 +145,9 @@ export function Topbar() {
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
|
||||
<DialogContent className="left-0 top-0 h-full w-80 max-w-[84vw] rounded-none rounded-r-3xl border-r border-zinc-200 p-0">
|
||||
<DialogContent className="left-0 top-0 h-full w-80 max-w-[84vw] rounded-none rounded-r-3xl border-r border-slate-200 p-0">
|
||||
<div className="flex h-full flex-col bg-white">
|
||||
<div className="flex items-start justify-between border-b border-zinc-200 px-5 py-5">
|
||||
<div className="flex items-start justify-between border-b border-slate-200 px-5 py-5">
|
||||
<AppBrand />
|
||||
<DialogClose asChild>
|
||||
<Button size="icon" variant="ghost" aria-label="关闭菜单" type="button">
|
||||
@@ -164,9 +164,9 @@ export function Topbar() {
|
||||
</Dialog>
|
||||
|
||||
<div className="min-w-0">
|
||||
<div className="text-xs font-semibold uppercase tracking-[0.18em] text-zinc-400">{pageMeta.group}</div>
|
||||
<div className="text-xs font-bold uppercase tracking-[0.2em] text-primary/70">{pageMeta.group}</div>
|
||||
<div className="mt-1 flex flex-wrap items-center gap-2">
|
||||
<p className="truncate text-lg font-semibold tracking-tight text-zinc-900">{pageMeta.title}</p>
|
||||
<p className="truncate text-lg font-semibold tracking-tight text-[var(--color-text-primary)]">{pageMeta.title}</p>
|
||||
{wecomEntry ? (
|
||||
<span
|
||||
className="badge-neutral border-primary-200 bg-primary-50 text-primary"
|
||||
@@ -176,7 +176,7 @@ export function Topbar() {
|
||||
</span>
|
||||
) : null}
|
||||
</div>
|
||||
<div className="mt-1 text-sm text-zinc-500">{me ? `你好,${me.name}` : "欢迎进入海音达工作台"}</div>
|
||||
<div className="mt-1 text-sm text-[var(--color-text-secondary)]">{me ? `你好,${me.name}` : "欢迎进入海音达工作台"}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -224,11 +224,11 @@ export function Topbar() {
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
|
||||
<DropdownMenuContent align="end" className="w-80 max-w-[calc(100vw-2rem)] p-0">
|
||||
<div className="flex items-center justify-between border-b border-zinc-200 px-4 py-3">
|
||||
<DropdownMenuContent align="end" className="w-80 max-w-[calc(100vw-2rem)] overflow-hidden rounded-2xl border-slate-200 bg-white p-0">
|
||||
<div className="flex items-center justify-between border-b border-slate-200 bg-slate-50/80 px-4 py-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-sm font-semibold text-zinc-900">通知</span>
|
||||
<span className="rounded-full bg-zinc-100 px-2 py-0.5 text-xs font-medium text-zinc-600">
|
||||
<span className="text-sm font-semibold text-[var(--color-text-primary)]">通知</span>
|
||||
<span className="rounded-full bg-white px-2 py-0.5 text-xs font-medium text-[var(--color-text-secondary)]">
|
||||
{unreadCount}
|
||||
</span>
|
||||
</div>
|
||||
@@ -244,7 +244,7 @@ export function Topbar() {
|
||||
|
||||
<div className="max-h-[400px] overflow-y-auto">
|
||||
{dropdownQuery.isLoading ? (
|
||||
<div className="px-4 py-6 text-sm text-zinc-500">通知加载中...</div>
|
||||
<div className="px-4 py-6 text-sm text-[var(--color-text-secondary)]">通知加载中...</div>
|
||||
) : null}
|
||||
|
||||
{dropdownQuery.isError ? (
|
||||
@@ -257,7 +257,7 @@ export function Topbar() {
|
||||
<button
|
||||
key={item.id}
|
||||
type="button"
|
||||
className="flex w-full items-start gap-3 border-b border-zinc-100 px-4 py-3 text-left transition hover:bg-zinc-50 disabled:opacity-60"
|
||||
className="flex w-full items-start gap-3 border-b border-slate-100 px-4 py-3 text-left transition hover:bg-slate-50 disabled:opacity-60"
|
||||
disabled={markReadMutation.isPending}
|
||||
onClick={() => void handleNotificationClick(item)}
|
||||
>
|
||||
@@ -265,20 +265,20 @@ export function Topbar() {
|
||||
{!item.readAt ? <span className="h-2 w-2 rounded-full bg-sky-500" /> : null}
|
||||
</span>
|
||||
<span className="min-w-0 flex-1">
|
||||
<span className="block truncate text-sm font-medium text-zinc-900">{item.title}</span>
|
||||
<span className="mt-1 block text-xs text-zinc-500">
|
||||
<span className="block truncate text-sm font-medium text-[var(--color-text-primary)]">{item.title}</span>
|
||||
<span className="mt-1 block text-xs text-[var(--color-text-secondary)]">
|
||||
{formatNotificationRelativeTime(item.createdAt)}
|
||||
</span>
|
||||
</span>
|
||||
</button>
|
||||
))
|
||||
) : (
|
||||
<div className="px-4 py-6 text-sm text-zinc-500">暂无通知</div>
|
||||
<div className="px-4 py-6 text-sm text-[var(--color-text-secondary)]">暂无通知</div>
|
||||
)
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
<div className="border-t border-zinc-200 px-2 py-2">
|
||||
<div className="border-t border-slate-200 px-2 py-2">
|
||||
<Button asChild variant="ghost" className="w-full justify-between" type="button">
|
||||
<Link to="/notifications" onClick={() => setNotificationsOpen(false)}>
|
||||
查看全部通知
|
||||
@@ -295,7 +295,7 @@ export function Topbar() {
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
|
||||
<DropdownMenuContent align="end" className="w-48">
|
||||
<DropdownMenuContent align="end" className="w-48 rounded-2xl border-slate-200 bg-white">
|
||||
<DropdownMenuItem asChild className="cursor-pointer">
|
||||
<Link to="/settings/profile">个人设置</Link>
|
||||
</DropdownMenuItem>
|
||||
|
||||
在新工单中引用
屏蔽一个用户