DG9 统一全站 UI 布局样板迁移

关联 Issue: DG9-0..DG9-12
这个提交包含在:
2026-05-14 00:52:59 +08:00
父节点 3ac5c785b1
当前提交 4b14c925b6
共修改 30 个文件,包含 743 行新增和 437 行删除
+33 -33
查看文件
@@ -325,15 +325,15 @@ export function MobilePortalPage() {
].filter((item): item is MobileAction => Boolean(item)).slice(0, 4);
return (
<PageScaffold className="space-y-4">
<PageScaffold className="mobile-page-stack">
<PageHeader title="今天" />
{canAccessApprovals && pendingApprovalCount > 0 ? (
<section className="mobile-card" data-testid="mobile-pending-summary">
<div className="mb-3 flex items-start justify-between gap-3">
<div>
<div className="text-base font-semibold text-zinc-900">待处理</div>
<div className="mt-1 text-xs text-zinc-500">待我审批</div>
<section className="mobile-card mobile-page-stack" data-testid="mobile-pending-summary">
<div className="mobile-section-header">
<div className="min-w-0">
<div className="mobile-section-title">待处理</div>
<div className="mobile-list-card__subtitle mt-1">待我审批</div>
</div>
<div className="text-right">
<div className="text-3xl font-semibold leading-none text-zinc-900" data-testid="mobile-pending-summary-count">
@@ -345,7 +345,7 @@ export function MobilePortalPage() {
</div>
</div>
{urgentPendingTask ? (
<div className="space-y-2">
<div className="mobile-page-stack">
{(() => {
const task = urgentPendingTask;
const entityType = task.workflowInstance?.entityType;
@@ -355,16 +355,16 @@ export function MobilePortalPage() {
key={task.id}
to={`/mobile/approvals/${encodeURIComponent(task.id)}`}
state={{ from: currentMobileSource }}
className="block rounded-lg border border-zinc-200 px-3 py-2 text-sm"
className="mobile-list-card block text-sm"
data-testid="mobile-pending-summary-primary"
>
<div className="flex items-center justify-between gap-3">
<div className="min-w-0 truncate font-medium text-zinc-900">
{reference ? `${businessEntityLabel(entityType, { noun: true })} ${reference}` : businessEntityLabel(entityType, { noun: true })}
<div className="mobile-list-card__header">
<div className="mobile-list-card__title">
{reference ? `${businessEntityLabel(entityType, { noun: true })} ${reference}` : businessEntityLabel(entityType, { noun: true })}
</div>
</div>
</div>
<div className="mt-1 truncate text-xs text-zinc-500">
{joinBusinessMeta([task.businessSummary?.applicantName ? `申请人:${task.businessSummary.applicantName}` : null, task.businessSummary?.amount ?? task.businessSummary?.duration, `节点:${task.stepName}`])}
<div className="mobile-list-card__subtitle mt-1">
{joinBusinessMeta([task.businessSummary?.applicantName ? `申请人:${task.businessSummary.applicantName}` : null, task.businessSummary?.amount ?? task.businessSummary?.duration, `节点:${task.stepName}`])}
</div>
</Link>
);
@@ -378,9 +378,9 @@ export function MobilePortalPage() {
) : null}
{canUseFinance ? (
<section className="mobile-card" data-testid="mobile-finance-summary">
<div className="mb-3 flex items-center justify-between gap-3">
<div className="text-base font-semibold text-zinc-900">财务</div>
<section className="mobile-card mobile-page-stack" data-testid="mobile-finance-summary">
<div className="mobile-section-header">
<div className="mobile-section-title">财务</div>
<span className="badge-neutral">复核与付款</span>
</div>
{portalHomeQuery.isLoading ? <p className="text-sm text-zinc-500">读取中...</p> : null}
@@ -408,9 +408,9 @@ export function MobilePortalPage() {
</section>
) : null}
<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>
<section className="mobile-card mobile-page-stack" data-testid="mobile-today-focus">
<div className="mobile-section-header">
<div className="mobile-section-title">常用</div>
</div>
<div className="mobile-icon-grid" data-testid="mobile-action-grid">
{actions.map((action) => (
@@ -420,9 +420,9 @@ export function MobilePortalPage() {
</section>
{!attendanceFeatureDisabled ? (
<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>
<section className="mobile-card mobile-page-stack" data-testid="mobile-attendance-card">
<div className="mobile-section-header">
<div className="mobile-section-title">打卡</div>
<span className="badge-neutral">{attendanceToday?.workDate ?? "今日"}</span>
</div>
@@ -464,9 +464,9 @@ export function MobilePortalPage() {
</section>
) : null}
<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>
<section className="mobile-card mobile-page-stack" data-testid="mobile-notifications">
<div className="mobile-section-header">
<div className="mobile-section-title">通知</div>
<Button asChild size="sm" type="button" variant="secondary">
<Link to="/mobile/notifications">全部</Link>
</Button>
@@ -482,23 +482,23 @@ export function MobilePortalPage() {
<p className="text-sm text-zinc-500">暂无通知。</p>
) : null}
<div className="space-y-2">
<div className="mobile-page-stack">
{homeNotifications.map((item) => (
<button
key={item.id}
type="button"
className="block w-full rounded-lg border border-zinc-200 px-3 py-2 text-left text-sm"
className="mobile-list-card w-full text-left text-sm"
onClick={() => void openHomeNotification(item)}
data-testid="mobile-home-notification-card"
>
<div className="flex items-center justify-between gap-3">
<div className="mobile-list-card__header">
<div className="min-w-0">
<div className="text-xs text-zinc-500">{notificationTypeLabel(item.type)}</div>
<div className="mt-0.5 truncate font-medium text-zinc-900">{item.title}</div>
<div className="text-xs font-medium text-primary">{notificationTypeLabel(item.type)}</div>
<div className="mobile-list-card__title mt-0.5">{item.title}</div>
</div>
{!item.readAt ? <span className="badge-warning shrink-0">新</span> : null}
{!item.readAt ? <span className="badge-warning mobile-status-slot">新</span> : null}
</div>
<div className="mt-1 text-xs text-zinc-500">{formatDateTime(item.createdAt)}</div>
<div className="mobile-list-card__subtitle mt-1">{formatDateTime(item.createdAt)}</div>
</button>
))}
</div>