RS6 修复移动响应式布局体系
这个提交包含在:
@@ -130,25 +130,26 @@ function ActionTile({ action }: { action: MobileAction }) {
|
||||
to={action.to}
|
||||
className={
|
||||
isPrimary
|
||||
? "relative flex min-h-24 flex-col justify-between rounded-lg border border-primary-100 bg-primary-50 p-3 pr-14 text-primary shadow-sm"
|
||||
? "mobile-icon-action mobile-icon-action--primary"
|
||||
: isWarning
|
||||
? "relative flex min-h-24 flex-col justify-between rounded-lg border border-amber-200 bg-amber-50 p-3 pr-14 text-amber-900"
|
||||
: "relative flex min-h-24 flex-col justify-between rounded-lg border border-zinc-200 bg-white p-3 pr-14 text-zinc-900 shadow-sm"
|
||||
? "mobile-icon-action mobile-icon-action--warning"
|
||||
: "mobile-icon-action"
|
||||
}
|
||||
data-testid={`mobile-action-${action.key}`}
|
||||
title={`${action.label}:${action.meta}`}
|
||||
aria-label={`${action.label},${action.meta}`}
|
||||
>
|
||||
<div className="min-w-0">
|
||||
<span className="block min-w-0 whitespace-nowrap text-base font-semibold leading-6" data-testid={`mobile-action-${action.key}-label`}>
|
||||
{action.label}
|
||||
</span>
|
||||
</div>
|
||||
<span
|
||||
className="material-symbols-outlined absolute right-3 top-3 flex size-8 items-center justify-center rounded-md bg-white/70 text-[21px] leading-none shadow-sm"
|
||||
className="material-symbols-outlined mobile-icon-action__icon"
|
||||
data-testid={`mobile-action-${action.key}-icon`}
|
||||
aria-hidden="true"
|
||||
>
|
||||
{action.icon}
|
||||
</span>
|
||||
<div className={isPrimary ? "truncate text-xs text-primary/70" : "truncate text-xs text-zinc-500"}>{action.meta}</div>
|
||||
<span className="mobile-icon-action__label" data-testid={`mobile-action-${action.key}-label`}>
|
||||
{action.label}
|
||||
</span>
|
||||
<span className="sr-only">{action.meta}</span>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
@@ -217,16 +218,14 @@ export function MobilePortalPage() {
|
||||
const unreadNotificationCount = notifications.filter((item) => !item.readAt).length;
|
||||
|
||||
const actions: MobileAction[] = [
|
||||
canAccessApprovals
|
||||
? {
|
||||
key: "approvals",
|
||||
label: "审批",
|
||||
meta: pendingApprovalCount > 0 ? `${pendingApprovalCount} 条待处理` : "暂无待办",
|
||||
icon: "fact_check",
|
||||
to: "/mobile/approvals",
|
||||
tone: pendingApprovalCount > 0 ? "warning" : "primary",
|
||||
}
|
||||
: null,
|
||||
{
|
||||
key: "approvals",
|
||||
label: "审批",
|
||||
meta: pendingApprovalCount > 0 ? `${pendingApprovalCount} 条待处理` : "暂无待办",
|
||||
icon: "fact_check",
|
||||
to: "/mobile/approvals",
|
||||
tone: pendingApprovalCount > 0 ? "warning" : "primary",
|
||||
},
|
||||
canAccessCapture
|
||||
? {
|
||||
key: "capture",
|
||||
@@ -246,6 +245,13 @@ export function MobilePortalPage() {
|
||||
to: "/mobile/reimbursements",
|
||||
}
|
||||
: null,
|
||||
{
|
||||
key: "me",
|
||||
label: "我的",
|
||||
meta: unreadNotificationCount > 0 ? `${unreadNotificationCount} 条新通知` : "资料和通知",
|
||||
icon: "person",
|
||||
to: "/mobile/me",
|
||||
},
|
||||
canAccessLeave
|
||||
? {
|
||||
key: "leave",
|
||||
@@ -255,25 +261,18 @@ export function MobilePortalPage() {
|
||||
to: "/mobile/leave",
|
||||
}
|
||||
: null,
|
||||
{
|
||||
key: "me",
|
||||
label: "我的",
|
||||
meta: unreadNotificationCount > 0 ? `${unreadNotificationCount} 条新通知` : "资料和通知",
|
||||
icon: "person",
|
||||
to: "/mobile/me",
|
||||
},
|
||||
].filter((item): item is MobileAction => Boolean(item)).slice(0, 4);
|
||||
|
||||
return (
|
||||
<PageScaffold className="space-y-4">
|
||||
<PageHeader title="今天" />
|
||||
|
||||
<section className="rounded-lg border border-zinc-200 bg-white p-4 shadow-sm" data-testid="mobile-today-focus">
|
||||
<section className="mobile-card" data-testid="mobile-today-focus">
|
||||
<div className="mb-3 flex items-center justify-between gap-3">
|
||||
<div className="text-base font-semibold text-zinc-900">待处理</div>
|
||||
{pendingApprovalCount > 0 ? <span className="badge-warning">{pendingApprovalCount} 待批</span> : null}
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
<div className="mobile-icon-grid" data-testid="mobile-action-grid">
|
||||
{actions.map((action) => (
|
||||
<ActionTile key={action.key} action={action} />
|
||||
))}
|
||||
@@ -281,7 +280,7 @@ export function MobilePortalPage() {
|
||||
</section>
|
||||
|
||||
{!attendanceFeatureDisabled ? (
|
||||
<section className="rounded-lg border border-zinc-200 bg-white p-4 shadow-sm" data-testid="mobile-attendance-card">
|
||||
<section className="mobile-card" data-testid="mobile-attendance-card">
|
||||
<div className="mb-3 flex items-center justify-between gap-3">
|
||||
<div className="text-base font-semibold text-zinc-900">打卡</div>
|
||||
<span className="badge-neutral">{attendanceToday?.workDate ?? "今日"}</span>
|
||||
@@ -326,7 +325,7 @@ export function MobilePortalPage() {
|
||||
) : null}
|
||||
|
||||
{canAccessApprovals ? (
|
||||
<section className="rounded-lg border border-zinc-200 bg-white p-4 shadow-sm" data-testid="mobile-pending-tasks">
|
||||
<section className="mobile-card" data-testid="mobile-pending-tasks">
|
||||
<div className="mb-3 flex items-center justify-between gap-3">
|
||||
<div className="text-base font-semibold text-zinc-900">待审批</div>
|
||||
<Button asChild size="sm" type="button" variant="secondary">
|
||||
@@ -359,7 +358,7 @@ export function MobilePortalPage() {
|
||||
</section>
|
||||
) : null}
|
||||
|
||||
<section className="rounded-lg border border-zinc-200 bg-white p-4 shadow-sm" data-testid="mobile-notifications">
|
||||
<section className="mobile-card" data-testid="mobile-notifications">
|
||||
<div className="mb-3 flex items-center justify-between gap-3">
|
||||
<div className="text-base font-semibold text-zinc-900">通知</div>
|
||||
<Button asChild size="sm" type="button" variant="secondary">
|
||||
|
||||
在新工单中引用
屏蔽一个用户