继续收口工具弹窗与分段切换预设

新增 PlatformToolModalShell 承接白底工具弹窗壳层和固定可访问名称

新增 PlatformSegmentedTabPresets 沉淀频道下划线、创作 pill rail 与二列 option segment

迁移拼图、抓大鹅、历史素材弹窗和首页 / 作品架 / 充值切换的重复组件写法

同步 PlatformUiKit 文档和 Hermes 决策记录
This commit is contained in:
2026-06-11 16:32:56 +08:00
parent 7c47ad3358
commit ffcffef6d2
15 changed files with 848 additions and 621 deletions
@@ -1,14 +1,12 @@
import { useEffect, useState } from 'react';
import { createPortal } from 'react-dom';
import {
puzzleAssetClient,
type PuzzleHistoryAsset,
} from '../../../services/puzzle-works/puzzleAssetClient';
import { formatPuzzleHistoryAssetCreatedAt } from '../../../services/puzzle-works/puzzleHistoryAsset';
import { useAuthUi } from '../../auth/AuthUiContext';
import { PlatformAssetPickerGrid } from '../../common/PlatformAssetPickerCard';
import { PlatformModalCloseButton } from '../../common/PlatformModalCloseButton';
import { PlatformToolModalShell } from '../../common/PlatformToolModalShell';
type PuzzleHistoryAssetPickerDialogProps = {
isBusy: boolean;
@@ -21,7 +19,6 @@ export function PuzzleHistoryAssetPickerDialog({
onClose,
onSelect,
}: PuzzleHistoryAssetPickerDialogProps) {
const platformTheme = useAuthUi()?.platformTheme ?? 'light';
const [assets, setAssets] = useState<PuzzleHistoryAsset[]>([]);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
@@ -57,62 +54,37 @@ export function PuzzleHistoryAssetPickerDialog({
};
}, []);
if (typeof document === 'undefined') {
return null;
}
return createPortal(
<div
className={`platform-theme platform-theme--${platformTheme} platform-overlay fixed inset-0 z-[145] flex items-end justify-center p-3 backdrop-blur-sm sm:items-center sm:p-4`}
onClick={(event) => {
if (event.target === event.currentTarget) {
onClose();
}
}}
return (
<PlatformToolModalShell
open
title="选择历史图片"
onClose={onClose}
closeLabel="关闭历史图片选择器"
zIndexClassName="z-[145]"
size="xl"
panelClassName="!max-h-[min(92vh,46rem)]"
>
<div
role="dialog"
aria-modal="true"
aria-label="选择历史图片"
className="platform-modal-shell platform-remap-surface flex max-h-[min(92vh,46rem)] w-full max-w-5xl flex-col overflow-hidden rounded-t-[1.75rem] shadow-[0_24px_80px_rgba(0,0,0,0.55)] sm:rounded-[1.75rem]"
onClick={(event) => event.stopPropagation()}
>
<div className="flex items-center justify-between gap-3 border-b border-[var(--platform-subpanel-border)] px-5 py-4">
<div className="text-base font-semibold text-[var(--platform-text-strong)]">
选择历史图片
</div>
<PlatformModalCloseButton
variant="platformIcon"
label="关闭历史图片选择器"
onClick={onClose}
/>
</div>
<div className="min-h-0 flex-1 overflow-y-auto px-5 py-4">
<PlatformAssetPickerGrid
items={assets}
isLoading={isLoading}
error={error}
loadingLabel="读取中..."
emptyLabel="暂无历史拼图素材"
disabled={isBusy}
getKey={(asset) => asset.assetObjectId}
getImageSrc={(asset) => asset.imageSrc}
getImageAlt={() => ''}
getSubtitle={(asset) =>
formatPuzzleHistoryAssetCreatedAt(asset.createdAt)
}
getAriaLabel={(asset) =>
`选择${formatPuzzleHistoryAssetCreatedAt(asset.createdAt)}的历史图片`
}
onSelect={onSelect}
cardRadiusClassName="rounded-[1.25rem]"
bodyClassName="px-4 py-3"
/>
</div>
</div>
</div>,
document.body,
<PlatformAssetPickerGrid
items={assets}
isLoading={isLoading}
error={error}
loadingLabel="读取中..."
emptyLabel="暂无历史拼图素材"
disabled={isBusy}
getKey={(asset) => asset.assetObjectId}
getImageSrc={(asset) => asset.imageSrc}
getImageAlt={() => ''}
getSubtitle={(asset) =>
formatPuzzleHistoryAssetCreatedAt(asset.createdAt)
}
getAriaLabel={(asset) =>
`选择${formatPuzzleHistoryAssetCreatedAt(asset.createdAt)}的历史图片`
}
onSelect={onSelect}
cardRadiusClassName="rounded-[1.25rem]"
bodyClassName="px-4 py-3"
/>
</PlatformToolModalShell>
);
}