收口个人中心泥点账单弹窗壳层
RpgEntryHomeView 的 WalletLedgerModal 改用 UnifiedModal 并保留渐变面板与关闭语义 账单弹窗测试改为断言具名 dialog 与关闭卸载路径 更新 PlatformUiKit 收口计划与 .hermes 决策记录
This commit is contained in:
@@ -57,6 +57,7 @@
|
|||||||
- 2026-06-10 追加:`UnifiedModal` 新增 `closeVariant`、`closeOnEscape`、`titleClassName` 和 `descriptionClassName`,用于在收口标准平台弹窗壳层时保留个人中心 `profile / profileCompact` 关闭按钮、原有标题层级和“不响应 Escape / backdrop”的交互语义;RPG 首页个人中心里的昵称修改、账户充值、每日任务和兑换码弹窗已迁移到 `UnifiedModal`,支付结果 / 支付确认遮罩 / 泥点账单这类头部结构不同的弹窗继续保留专用实现。验证命令:`npm run test -- src/components/common/UnifiedModal.test.tsx src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx`。
|
- 2026-06-10 追加:`UnifiedModal` 新增 `closeVariant`、`closeOnEscape`、`titleClassName` 和 `descriptionClassName`,用于在收口标准平台弹窗壳层时保留个人中心 `profile / profileCompact` 关闭按钮、原有标题层级和“不响应 Escape / backdrop”的交互语义;RPG 首页个人中心里的昵称修改、账户充值、每日任务和兑换码弹窗已迁移到 `UnifiedModal`,支付结果 / 支付确认遮罩 / 泥点账单这类头部结构不同的弹窗继续保留专用实现。验证命令:`npm run test -- src/components/common/UnifiedModal.test.tsx src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx`。
|
||||||
- 2026-06-10 追加:`UnifiedModal` 新增 `showHeader`,用于收口不需要标准头部但仍要保留 dialog 无障碍语义、遮罩和层级控制的轻量弹窗;RPG 首页个人中心的支付结果提示与支付确认遮罩已迁移到 `showHeader={false}` 模式,业务页只保留 icon badge、文案与按钮,不再手写 backdrop、aria 和白底壳层。个人中心移动端顶栏“扫码”“打开设置”入口统一使用 `PlatformIconButton`,并继续保留 `.platform-profile-header__icon-button` 局部 class 控制位置与主题色。验证命令:`npm run test -- src/components/common/UnifiedModal.test.tsx src/components/common/PlatformIconButton.test.tsx src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx`。
|
- 2026-06-10 追加:`UnifiedModal` 新增 `showHeader`,用于收口不需要标准头部但仍要保留 dialog 无障碍语义、遮罩和层级控制的轻量弹窗;RPG 首页个人中心的支付结果提示与支付确认遮罩已迁移到 `showHeader={false}` 模式,业务页只保留 icon badge、文案与按钮,不再手写 backdrop、aria 和白底壳层。个人中心移动端顶栏“扫码”“打开设置”入口统一使用 `PlatformIconButton`,并继续保留 `.platform-profile-header__icon-button` 局部 class 控制位置与主题色。验证命令:`npm run test -- src/components/common/UnifiedModal.test.tsx src/components/common/PlatformIconButton.test.tsx src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx`。
|
||||||
- 2026-06-10 追加:RPG 首页发现页分类筛选弹窗和个人中心扫码面板改用 `UnifiedModal` 承接 backdrop、dialog 语义和层级;分类筛选保留本地选项 / 动作布局,扫码面板继续使用 `showHeader={false}` 保留深色自定义头部与摄像头 viewport,并显式维持 `closeOnBackdrop={false}`、`closeOnEscape={false}`。验证命令:`npm run test -- src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx src/components/common/UnifiedModal.test.tsx`。
|
- 2026-06-10 追加:RPG 首页发现页分类筛选弹窗和个人中心扫码面板改用 `UnifiedModal` 承接 backdrop、dialog 语义和层级;分类筛选保留本地选项 / 动作布局,扫码面板继续使用 `showHeader={false}` 保留深色自定义头部与摄像头 viewport,并显式维持 `closeOnBackdrop={false}`、`closeOnEscape={false}`。验证命令:`npm run test -- src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx src/components/common/UnifiedModal.test.tsx`。
|
||||||
|
- 2026-06-10 追加:RPG 首页个人中心泥点账单改用 `UnifiedModal showHeader={false}` 承接 `dialog` 语义和遮罩层级,同时保留渐变面板、`PlatformModalCloseButton variant="floating"`、余额 badge 与账单列表布局;账单继续显式维持 `closeOnBackdrop={false}`、`closeOnEscape={false}`,测试改为直接断言具名 dialog 和关闭后卸载。验证命令:`npm run test -- src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx -t "opens wallet ledger modal from narrative coin card|wallet ledger modal shows empty and error states" src/components/common/UnifiedModal.test.tsx`。
|
||||||
- 2026-06-09 追加:RPG 大编辑器暗色面板内的保存和角色槽动作继续走本地 `ActionButton`,不再混用白底平台 `platform-button` class;平台白底动作收口和编辑器暗色动作收口保持两套视觉边界。
|
- 2026-06-09 追加:RPG 大编辑器暗色面板内的保存和角色槽动作继续走本地 `ActionButton`,不再混用白底平台 `platform-button` class;平台白底动作收口和编辑器暗色动作收口保持两套视觉边界。
|
||||||
- 2026-06-10 追加:`PlatformActionButton surface="editorDark"` 承接 RPG 暗色弹窗 / 运行面板里的普通取消、确认、刷新和编组动作,支持 `size="xxs"` 与 `tone="success" | "warning"`;`tone="accent"` 承接暗色壳层内的琥珀实心 CTA,`tone="accentSoft"` 承接依赖局部 accent 变量的柔和强调按钮。角色自定义 footer、自定义世界生成 footer、地图切换确认、营地编组普通动作和角色聊天刷新动作已迁移。暗色可选项卡仍使用 `PlatformDarkOptionCard`,像素风发送 / 强品牌动作继续保留专用布局。验证命令:`npm run test -- src/components/common/platformActionButtonModel.test.ts src/components/common/PlatformActionButton.test.tsx src/components/SelectionCustomizationModals.test.tsx src/components/CompanionCampModal.test.tsx src/components/MapModal.test.tsx src/components/CharacterChatModal.test.tsx`。
|
- 2026-06-10 追加:`PlatformActionButton surface="editorDark"` 承接 RPG 暗色弹窗 / 运行面板里的普通取消、确认、刷新和编组动作,支持 `size="xxs"` 与 `tone="success" | "warning"`;`tone="accent"` 承接暗色壳层内的琥珀实心 CTA,`tone="accentSoft"` 承接依赖局部 accent 变量的柔和强调按钮。角色自定义 footer、自定义世界生成 footer、地图切换确认、营地编组普通动作和角色聊天刷新动作已迁移。暗色可选项卡仍使用 `PlatformDarkOptionCard`,像素风发送 / 强品牌动作继续保留专用布局。验证命令:`npm run test -- src/components/common/platformActionButtonModel.test.ts src/components/common/PlatformActionButton.test.tsx src/components/SelectionCustomizationModals.test.tsx src/components/CompanionCampModal.test.tsx src/components/MapModal.test.tsx src/components/CharacterChatModal.test.tsx`。
|
||||||
- 2026-06-10 追加:RPG 首页创作 / 草稿顶栏的钱包快捷入口通过同文件 `TopbarWalletShortcutButton` 复用 `PlatformActionButton tone="accentSoft" shape="pill" size="xs"` 与 `PlatformIconBadge`;移动端 / 桌面端继续保留 `.platform-mobile-create-wallet-chip`、`.platform-desktop-create-wallet-chip` 和 `.platform-desktop-search` 兼容 class,承接余额截断、桌面顶栏胶囊壳和既有测试锚点,点击语义仍统一走 `openRechargeOrRewardCodeModal`。验证命令:`npm run test -- src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx`。
|
- 2026-06-10 追加:RPG 首页创作 / 草稿顶栏的钱包快捷入口通过同文件 `TopbarWalletShortcutButton` 复用 `PlatformActionButton tone="accentSoft" shape="pill" size="xs"` 与 `PlatformIconBadge`;移动端 / 桌面端继续保留 `.platform-mobile-create-wallet-chip`、`.platform-desktop-create-wallet-chip` 和 `.platform-desktop-search` 兼容 class,承接余额截断、桌面顶栏胶囊壳和既有测试锚点,点击语义仍统一走 `openRechargeOrRewardCodeModal`。验证命令:`npm run test -- src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx`。
|
||||||
|
|||||||
@@ -223,10 +223,11 @@
|
|||||||
19.2. 拼图广场详情 hero 的返回、上一张 / 下一张关卡图入口迁移到 `PlatformIconButton variant="darkMini"`,修改作品和进入第 1 关迁移到 `PlatformActionButton`,分享动作继续使用 `CopyFeedbackButton` 但复用共享动作按钮 chrome;详情页只保留轮播、复制和跳转语义,不再手写 hero 区按钮壳。
|
19.2. 拼图广场详情 hero 的返回、上一张 / 下一张关卡图入口迁移到 `PlatformIconButton variant="darkMini"`,修改作品和进入第 1 关迁移到 `PlatformActionButton`,分享动作继续使用 `CopyFeedbackButton` 但复用共享动作按钮 chrome;详情页只保留轮播、复制和跳转语义,不再手写 hero 区按钮壳。
|
||||||
19.3. 个人中心充值商品卡里的“购买 / 处理中”胶囊暂保留局部 `span`,不直接套用 `PlatformActionButton`,避免在 `PlatformSubpanel as="button"` 内再嵌套交互按钮;待出现第二个同形态的非交互 action chip 后,再决定是否沉淀独立的共享展示基元。
|
19.3. 个人中心充值商品卡里的“购买 / 处理中”胶囊暂保留局部 `span`,不直接套用 `PlatformActionButton`,避免在 `PlatformSubpanel as="button"` 内再嵌套交互按钮;待出现第二个同形态的非交互 action chip 后,再决定是否沉淀独立的共享展示基元。
|
||||||
19.3.1. RPG 首页创作 / 草稿顶栏的钱包快捷入口迁移到同文件适配器 `TopbarWalletShortcutButton`,内部复用 `PlatformActionButton tone="accentSoft" shape="pill" size="xs"` 与 `PlatformIconBadge`;移动端和桌面端继续保留 `.platform-mobile-create-wallet-chip`、`.platform-desktop-create-wallet-chip` 和 `.platform-desktop-search` 兼容 class,承接移动端余额截断、桌面顶栏胶囊底色以及既有测试锚点。入口点击仍统一走 `openRechargeOrRewardCodeModal`,不把充值 / 兑换码平台分流逻辑改散到两个顶栏分支里。
|
19.3.1. RPG 首页创作 / 草稿顶栏的钱包快捷入口迁移到同文件适配器 `TopbarWalletShortcutButton`,内部复用 `PlatformActionButton tone="accentSoft" shape="pill" size="xs"` 与 `PlatformIconBadge`;移动端和桌面端继续保留 `.platform-mobile-create-wallet-chip`、`.platform-desktop-create-wallet-chip` 和 `.platform-desktop-search` 兼容 class,承接移动端余额截断、桌面顶栏胶囊底色以及既有测试锚点。入口点击仍统一走 `openRechargeOrRewardCodeModal`,不把充值 / 兑换码平台分流逻辑改散到两个顶栏分支里。
|
||||||
19.3.2. 个人中心昵称修改、账户充值、每日任务和兑换码四类标准头部弹窗迁移到 `UnifiedModal`;`UnifiedModal` 新增 `closeVariant`、`closeOnEscape`、`titleClassName` 和 `descriptionClassName`,用于在收口弹窗壳层时保留个人中心 `profile / profileCompact` 关闭按钮、居中浮层布局和标题层级。上述弹窗统一通过 `closeOnBackdrop={false}`、`closeOnEscape={false}` 保持原有交互语义,不把 backdrop / Escape 关闭行为悄悄带进个人中心;泥点账单这类头部结构和 footer 语义明显不同的弹窗继续保留专用实现,等出现更多同构 case 再扩充 `UnifiedModal` 能力。
|
19.3.2. 个人中心昵称修改、账户充值、每日任务和兑换码四类标准头部弹窗迁移到 `UnifiedModal`;`UnifiedModal` 新增 `closeVariant`、`closeOnEscape`、`titleClassName` 和 `descriptionClassName`,用于在收口弹窗壳层时保留个人中心 `profile / profileCompact` 关闭按钮、居中浮层布局和标题层级。上述弹窗统一通过 `closeOnBackdrop={false}`、`closeOnEscape={false}` 保持原有交互语义,不把 backdrop / Escape 关闭行为悄悄带进个人中心;邀请、玩过作品等结构更复杂的二级弹层继续按同一壳层策略逐步迁移。
|
||||||
19.3.3. 个人中心支付结果提示和支付确认遮罩迁移到 `UnifiedModal` 的 headerless 模式;`UnifiedModal` 新增 `showHeader`,用于在保留 `role="dialog"`、可访问名称、遮罩和 z-index 语义的同时,允许业务页自己排版 icon badge、轻量标题和正文。支付结果提示与确认遮罩统一使用 `showHeader={false}`、`showCloseButton={false}`、`closeOnBackdrop={false}`、`closeOnEscape={false}`,继续保持阻断式确认语义;业务页只保留图标、文案和按钮,不再手写 backdrop、dialog aria 和面板壳层。
|
19.3.3. 个人中心支付结果提示和支付确认遮罩迁移到 `UnifiedModal` 的 headerless 模式;`UnifiedModal` 新增 `showHeader`,用于在保留 `role="dialog"`、可访问名称、遮罩和 z-index 语义的同时,允许业务页自己排版 icon badge、轻量标题和正文。支付结果提示与确认遮罩统一使用 `showHeader={false}`、`showCloseButton={false}`、`closeOnBackdrop={false}`、`closeOnEscape={false}`,继续保持阻断式确认语义;业务页只保留图标、文案和按钮,不再手写 backdrop、dialog aria 和面板壳层。
|
||||||
19.3.4. 个人中心移动端顶栏的“扫码”“打开设置”入口迁移到 `PlatformIconButton`;页面继续保留 `.platform-profile-header__icon-button` 局部 class 控制位置、尺寸和主题色,交互语义与可访问名称统一由共享按钮承接,不再在 `RpgEntryHomeView` 里手写图标按钮的 `type`、`aria-label` 和基础 chrome。
|
19.3.4. 个人中心移动端顶栏的“扫码”“打开设置”入口迁移到 `PlatformIconButton`;页面继续保留 `.platform-profile-header__icon-button` 局部 class 控制位置、尺寸和主题色,交互语义与可访问名称统一由共享按钮承接,不再在 `RpgEntryHomeView` 里手写图标按钮的 `type`、`aria-label` 和基础 chrome。
|
||||||
19.3.5. 发现页分类筛选弹窗与个人中心扫码面板迁移到 `UnifiedModal`;分类筛选继续复用本地选项栅格和底部动作区样式,但 backdrop、dialog 语义、头部关闭入口和 `closeOnEscape={false}` 统一收口到共享壳层。扫码面板复用 `showHeader={false}` 模式保留深色自定义头部、摄像头 viewport 和状态提示,同时显式保持 `closeOnBackdrop={false}`、`closeOnEscape={false}`,确保不会把扫码中的资源清理语义改散到页面外层。
|
19.3.5. 发现页分类筛选弹窗与个人中心扫码面板迁移到 `UnifiedModal`;分类筛选继续复用本地选项栅格和底部动作区样式,但 backdrop、dialog 语义、头部关闭入口和 `closeOnEscape={false}` 统一收口到共享壳层。扫码面板复用 `showHeader={false}` 模式保留深色自定义头部、摄像头 viewport 和状态提示,同时显式保持 `closeOnBackdrop={false}`、`closeOnEscape={false}`,确保不会把扫码中的资源清理语义改散到页面外层。
|
||||||
|
19.3.6. 个人中心泥点账单弹窗迁移到 `UnifiedModal` 的 headerless 模式;共享壳层承接 `dialog` 语义、层级和关闭策略,账单弹窗继续保留自定义渐变面板、浮动关闭按钮、余额 badge、列表 / 空态 / 错误态布局以及 `closeOnBackdrop={false}`、`closeOnEscape={false}` 的原有交互,不再手写 `fixed inset-0` 遮罩壳层。
|
||||||
19.3. creative-agent 首页的侧边栏菜单、账号入口、开启新对话、我的创作、首页激励 CTA 和 prompt suggestion 按钮迁移到 `PlatformIconButton` / `PlatformActionButton`;首页继续保留 `creative-agent-home__*` 本地 class 承接透明顶栏、抽屉和品牌化胶囊视觉,不把视觉回收和语义收口绑成一次大改。`Beta` 徽标和历史记录纯文本行暂保留本地实现,等出现更多同构轻量列表行后再评估是否抽新的共享 row primitive。
|
19.3. creative-agent 首页的侧边栏菜单、账号入口、开启新对话、我的创作、首页激励 CTA 和 prompt suggestion 按钮迁移到 `PlatformIconButton` / `PlatformActionButton`;首页继续保留 `creative-agent-home__*` 本地 class 承接透明顶栏、抽屉和品牌化胶囊视觉,不把视觉回收和语义收口绑成一次大改。`Beta` 徽标和历史记录纯文本行暂保留本地实现,等出现更多同构轻量列表行后再评估是否抽新的共享 row primitive。
|
||||||
19.4. 大鱼吃小鱼结果页 hero 的返回入口迁移到 `PlatformIconButton variant="darkMini"`,测试 / 发布动作迁移到 `PlatformActionButton surface="editorDark"`;结果页只保留测试运行、发布提交和文案状态语义,不再手写 hero 顶栏按钮壳。
|
19.4. 大鱼吃小鱼结果页 hero 的返回入口迁移到 `PlatformIconButton variant="darkMini"`,测试 / 发布动作迁移到 `PlatformActionButton surface="editorDark"`;结果页只保留测试运行、发布提交和文案状态语义,不再手写 hero 顶栏按钮壳。
|
||||||
20. 平台方形上传入口和紧凑虚线新增入口迁移到 `PlatformUploadTile`,上传后的图片预览迁移到 `PlatformUploadPreviewCard`;反馈页上传凭证入口 / 预览、敲木鱼工作台新增功德词条入口、通用创作图片面板的提示词参考图缩略图、抓大鹅封面编辑参考图缩略图、通用输入 Composer 已选参考图条、creation-agent 已选参考图条和拼图结果页关卡引用图横条已先迁移。方形缩略图使用默认 `layout="square"`,横向“已选择参考图 / 文件名 / 素材名 / 移除”条使用 `layout="inline"`;只读引用图条不传 `onRemove`,避免公共组件额外渲染删除入口。后续继续收口结果页素材上传、工作台参考图上传、紧凑虚线新增入口等上传 / 动作块时,业务页只保留文件选择、预览数组、预览回调、删除回调、校验逻辑或新增回调,上传方块外观、主副文案、缩略图壳、预览按钮、标题行、横向已选条、移除按钮和禁用态统一由 Module 承接;工具栏中的小图标上传仍继续使用 `PlatformIconButton asChild="label"`。
|
20. 平台方形上传入口和紧凑虚线新增入口迁移到 `PlatformUploadTile`,上传后的图片预览迁移到 `PlatformUploadPreviewCard`;反馈页上传凭证入口 / 预览、敲木鱼工作台新增功德词条入口、通用创作图片面板的提示词参考图缩略图、抓大鹅封面编辑参考图缩略图、通用输入 Composer 已选参考图条、creation-agent 已选参考图条和拼图结果页关卡引用图横条已先迁移。方形缩略图使用默认 `layout="square"`,横向“已选择参考图 / 文件名 / 素材名 / 移除”条使用 `layout="inline"`;只读引用图条不传 `onRemove`,避免公共组件额外渲染删除入口。后续继续收口结果页素材上传、工作台参考图上传、紧凑虚线新增入口等上传 / 动作块时,业务页只保留文件选择、预览数组、预览回调、删除回调、校验逻辑或新增回调,上传方块外观、主副文案、缩略图壳、预览按钮、标题行、横向已选条、移除按钮和禁用态统一由 Module 承接;工具栏中的小图标上传仍继续使用 `PlatformIconButton asChild="label"`。
|
||||||
|
|||||||
@@ -1256,10 +1256,12 @@ test('opens wallet ledger modal from narrative coin card', async () => {
|
|||||||
renderProfileView();
|
renderProfileView();
|
||||||
await user.click(screen.getByRole('button', { name: /泥点余额\s*0/u }));
|
await user.click(screen.getByRole('button', { name: /泥点余额\s*0/u }));
|
||||||
|
|
||||||
expect(await screen.findByText('泥点账单')).toBeTruthy();
|
const ledgerModal = await screen.findByRole('dialog', { name: '泥点账单' });
|
||||||
const ledgerModal = screen
|
|
||||||
.getByText('泥点账单')
|
expect(ledgerModal).toBeTruthy();
|
||||||
.closest('.fixed') as HTMLElement;
|
expect(
|
||||||
|
within(ledgerModal).getByRole('button', { name: '关闭泥点账单' }),
|
||||||
|
).toBeTruthy();
|
||||||
const balanceBadge = within(ledgerModal).getByText('29泥点');
|
const balanceBadge = within(ledgerModal).getByText('29泥点');
|
||||||
expect(balanceBadge.className).toContain('rounded-full');
|
expect(balanceBadge.className).toContain('rounded-full');
|
||||||
expect(balanceBadge.className).toContain('border-rose-100');
|
expect(balanceBadge.className).toContain('border-rose-100');
|
||||||
@@ -3197,10 +3199,13 @@ test('wallet ledger modal shows empty and error states', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
await user.click(screen.getByLabelText('关闭泥点账单'));
|
await user.click(screen.getByLabelText('关闭泥点账单'));
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(screen.queryByRole('dialog', { name: '泥点账单' })).toBeNull();
|
||||||
|
});
|
||||||
mockGetRpgProfileWalletLedger.mockRejectedValueOnce(new Error('加载失败'));
|
mockGetRpgProfileWalletLedger.mockRejectedValueOnce(new Error('加载失败'));
|
||||||
await user.click(screen.getByRole('button', { name: /泥点余额\s*0/u }));
|
await user.click(screen.getByRole('button', { name: /泥点余额\s*0/u }));
|
||||||
|
|
||||||
expect(await screen.findByText('泥点账单')).toBeTruthy();
|
expect(await screen.findByRole('dialog', { name: '泥点账单' })).toBeTruthy();
|
||||||
await waitFor(() => {
|
await waitFor(() => {
|
||||||
expect(screen.getByText('加载失败')).toBeTruthy();
|
expect(screen.getByText('加载失败')).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3418,8 +3418,22 @@ function WalletLedgerModal({
|
|||||||
const entries = walletLedgerPresentation.entries;
|
const entries = walletLedgerPresentation.entries;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 z-[80] flex items-center justify-center bg-black/48 px-3 py-5">
|
<UnifiedModal
|
||||||
<div className="relative max-h-[min(92vh,42rem)] w-full max-w-[30rem] overflow-hidden rounded-[1.35rem] bg-[linear-gradient(180deg,#fff7f8_0%,#ffffff_38%,#f8fafc_100%)] text-zinc-950 shadow-2xl">
|
open
|
||||||
|
title="泥点账单"
|
||||||
|
onClose={onClose}
|
||||||
|
showHeader={false}
|
||||||
|
showCloseButton={false}
|
||||||
|
closeOnBackdrop={false}
|
||||||
|
closeOnEscape={false}
|
||||||
|
portal={false}
|
||||||
|
size="sm"
|
||||||
|
zIndexClassName="z-[80]"
|
||||||
|
overlayClassName="!items-center !bg-black/48 !px-3 !py-5 !backdrop-blur-none"
|
||||||
|
panelClassName="relative !max-h-[min(92vh,42rem)] !max-w-[30rem] bg-[linear-gradient(180deg,#fff7f8_0%,#ffffff_38%,#f8fafc_100%)] text-zinc-950 shadow-2xl !rounded-[1.35rem] sm:!rounded-[1.35rem]"
|
||||||
|
bodyClassName="!p-0"
|
||||||
|
>
|
||||||
|
<div className="relative max-h-[min(92vh,42rem)] overflow-y-auto px-4 pb-5 pt-4 sm:px-5">
|
||||||
<PlatformModalCloseButton
|
<PlatformModalCloseButton
|
||||||
label="关闭泥点账单"
|
label="关闭泥点账单"
|
||||||
variant="floating"
|
variant="floating"
|
||||||
@@ -3427,94 +3441,89 @@ function WalletLedgerModal({
|
|||||||
className="bg-white/78"
|
className="bg-white/78"
|
||||||
icon="×"
|
icon="×"
|
||||||
/>
|
/>
|
||||||
<div className="max-h-[min(92vh,42rem)] overflow-y-auto px-4 pb-5 pt-4 sm:px-5">
|
<div className="pr-10">
|
||||||
<div className="pr-10">
|
<div className="text-[10px] font-black tracking-[0.22em] text-[#ff4056]">
|
||||||
<div className="text-[10px] font-black tracking-[0.22em] text-[#ff4056]">
|
LEDGER
|
||||||
LEDGER
|
|
||||||
</div>
|
|
||||||
<div className="mt-1 text-2xl font-black">泥点账单</div>
|
|
||||||
<PlatformPillBadge
|
|
||||||
tone="profile"
|
|
||||||
icon={<Coins className="h-3.5 w-3.5 text-[#ff4056]" />}
|
|
||||||
className="mt-3 bg-white/70"
|
|
||||||
>
|
|
||||||
{walletLedgerPresentation.balanceLabel}
|
|
||||||
</PlatformPillBadge>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div className="mt-1 text-2xl font-black">泥点账单</div>
|
||||||
{error ? (
|
<PlatformPillBadge
|
||||||
<PlatformStatusMessage
|
tone="profile"
|
||||||
tone="error"
|
icon={<Coins className="h-3.5 w-3.5 text-[#ff4056]" />}
|
||||||
className="mt-4 rounded-xl py-3"
|
className="mt-3 bg-white/70"
|
||||||
>
|
>
|
||||||
<div>{error}</div>
|
{walletLedgerPresentation.balanceLabel}
|
||||||
<PlatformActionButton
|
</PlatformPillBadge>
|
||||||
surface="profile"
|
|
||||||
shape="pill"
|
|
||||||
size="xs"
|
|
||||||
className="mt-3"
|
|
||||||
onClick={onRetry}
|
|
||||||
>
|
|
||||||
重新加载
|
|
||||||
</PlatformActionButton>
|
|
||||||
</PlatformStatusMessage>
|
|
||||||
) : isLoading ? (
|
|
||||||
<div className="mt-5 space-y-3">
|
|
||||||
{Array.from({ length: 5 }).map((_, index) => (
|
|
||||||
<div
|
|
||||||
key={index}
|
|
||||||
className="h-16 animate-pulse rounded-xl bg-zinc-100"
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
) : entries.length === 0 ? (
|
|
||||||
<PlatformEmptyState
|
|
||||||
surface="subpanel"
|
|
||||||
size="inline"
|
|
||||||
className="mt-5 py-8"
|
|
||||||
>
|
|
||||||
暂无账单记录
|
|
||||||
</PlatformEmptyState>
|
|
||||||
) : (
|
|
||||||
<div className="mt-5 space-y-2.5">
|
|
||||||
{entries.map((entry) => {
|
|
||||||
return (
|
|
||||||
<PlatformSubpanel
|
|
||||||
as="div"
|
|
||||||
key={entry.id}
|
|
||||||
surface="flat"
|
|
||||||
radius="xs"
|
|
||||||
padding="none"
|
|
||||||
className="flex items-center justify-between gap-3 px-3 py-3 shadow-sm"
|
|
||||||
>
|
|
||||||
<div className="min-w-0">
|
|
||||||
<div className="truncate text-sm font-black text-zinc-900">
|
|
||||||
{entry.sourceLabel}
|
|
||||||
</div>
|
|
||||||
<div className="mt-1 text-xs font-semibold text-zinc-500">
|
|
||||||
{formatPlatformWorldTime(entry.createdAt)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="shrink-0 text-right">
|
|
||||||
<div
|
|
||||||
className={`text-base font-black ${
|
|
||||||
entry.isIncome ? 'text-emerald-600' : 'text-rose-500'
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
{entry.amountLabel}
|
|
||||||
</div>
|
|
||||||
<div className="mt-1 text-[11px] font-semibold text-zinc-400">
|
|
||||||
{entry.balanceLabel}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</PlatformSubpanel>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{error ? (
|
||||||
|
<PlatformStatusMessage tone="error" className="mt-4 rounded-xl py-3">
|
||||||
|
<div>{error}</div>
|
||||||
|
<PlatformActionButton
|
||||||
|
surface="profile"
|
||||||
|
shape="pill"
|
||||||
|
size="xs"
|
||||||
|
className="mt-3"
|
||||||
|
onClick={onRetry}
|
||||||
|
>
|
||||||
|
重新加载
|
||||||
|
</PlatformActionButton>
|
||||||
|
</PlatformStatusMessage>
|
||||||
|
) : isLoading ? (
|
||||||
|
<div className="mt-5 space-y-3">
|
||||||
|
{Array.from({ length: 5 }).map((_, index) => (
|
||||||
|
<div
|
||||||
|
key={index}
|
||||||
|
className="h-16 animate-pulse rounded-xl bg-zinc-100"
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
) : entries.length === 0 ? (
|
||||||
|
<PlatformEmptyState
|
||||||
|
surface="subpanel"
|
||||||
|
size="inline"
|
||||||
|
className="mt-5 py-8"
|
||||||
|
>
|
||||||
|
暂无账单记录
|
||||||
|
</PlatformEmptyState>
|
||||||
|
) : (
|
||||||
|
<div className="mt-5 space-y-2.5">
|
||||||
|
{entries.map((entry) => {
|
||||||
|
return (
|
||||||
|
<PlatformSubpanel
|
||||||
|
as="div"
|
||||||
|
key={entry.id}
|
||||||
|
surface="flat"
|
||||||
|
radius="xs"
|
||||||
|
padding="none"
|
||||||
|
className="flex items-center justify-between gap-3 px-3 py-3 shadow-sm"
|
||||||
|
>
|
||||||
|
<div className="min-w-0">
|
||||||
|
<div className="truncate text-sm font-black text-zinc-900">
|
||||||
|
{entry.sourceLabel}
|
||||||
|
</div>
|
||||||
|
<div className="mt-1 text-xs font-semibold text-zinc-500">
|
||||||
|
{formatPlatformWorldTime(entry.createdAt)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="shrink-0 text-right">
|
||||||
|
<div
|
||||||
|
className={`text-base font-black ${
|
||||||
|
entry.isIncome ? 'text-emerald-600' : 'text-rose-500'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{entry.amountLabel}
|
||||||
|
</div>
|
||||||
|
<div className="mt-1 text-[11px] font-semibold text-zinc-400">
|
||||||
|
{entry.balanceLabel}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</PlatformSubpanel>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</UnifiedModal>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user