Files
live-hub-py/web/frontend
yml2213 f416397cc8 feat(account): 详情页重排 + 列表高价值套装列 + 兑换记录点击预览
## 详情页重排(4 张卡,消除重复)

用户反馈「设计太乱、数据不好看、布局也乱」——根因是**同一份数据在一屏出现两次**:
积分/鱼翅/兑换余额在状态条和资产区各一次,角色绑定在状态条和信息表各一次。

新布局:**账号信息**(身份+状态+归属,一张 Descriptions)→ **资产与统计**
(数字只出现一次,上面"现在有多少"、下面"历史累计")→ **高价值套装与兑换记录**
(从最顶上移到这里,它是补充信息,不该抢主视觉)→ **账号时间线**。
零散的 `flex + gap` 统计行改成 `Row/Col` 栅格,列宽对齐。

## 高价值套装:颜色按**价值**口径,别标反

用户澄清的业务语义与直觉相反:
- **没兑换过** = 还能用来绑定兑换 = **高价值**(绿色「可兑换」)
- 兑换过 1 个 → 价值降低;两个都兑换过 → 价值最低(橙色「已兑换」)

判定依据是**斗鱼官方兑换记录**(账号级)。⚠️ 不能用 `query_limited_goods` 的
`count`/`storeStatus` —— 那是**全局库存**(同一时刻不同账号看到的都一样),
用它判"这个账号有没有"必然给错结论。这个结论是推翻过一版才得到的:
第一版拿相隔两个月的两条快照对比,把**时间差异**当成了**账号差异**。

## 列表

- 新增「高价值套装」列:🟢两个都可兑换 / 🟠某套装已兑换 / ⚪未查询
  (「未查询」必须与「没兑换」分开,否则会把未知当成高价值)
- 「兑换记录」列只显示官方口径,**点击弹窗**看全部(按作用域分组,
  含商品/积分/真实兑换时间/当时用的昵称与平台),不用进详情页

## 三个作用域的记录展示

面板与预览都按 精英宝典 / 电竞手册 / 和平小店 分三块展示,
每条带**真实兑换时间**与"使用昵称"(排查时有用)。

## 顺带修

`exchange_records` 从数组改成按作用域分组的对象后,面板同步适配;
`formatTime` 对 `0` 显示 `-`(斗鱼用 0 表示"没有这个时间",
直接格式化会显示成 1970/1/1)。
2026-10-04 20:03:52 +08:00
..
2026-06-22 13:11:15 +08:00
2026-06-22 13:11:15 +08:00
2026-07-05 12:25:18 +08:00
2026-06-22 13:11:15 +08:00
2026-06-22 13:11:15 +08:00
2026-06-22 13:11:15 +08:00
2026-06-22 13:11:15 +08:00
2026-06-22 13:11:15 +08:00

React + TypeScript + Vite

This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.

Currently, two official plugins are available:

React Compiler

The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see this documentation.

Expanding the ESLint configuration

If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:

export default defineConfig([
  globalIgnores(['dist']),
  {
    files: ['**/*.{ts,tsx}'],
    extends: [
      // Other configs...

      // Remove tseslint.configs.recommended and replace with this
      tseslint.configs.recommendedTypeChecked,
      // Alternatively, use this for stricter rules
      tseslint.configs.strictTypeChecked,
      // Optionally, add this for stylistic rules
      tseslint.configs.stylisticTypeChecked,

      // Other configs...
    ],
    languageOptions: {
      parserOptions: {
        project: ['./tsconfig.node.json', './tsconfig.app.json'],
        tsconfigRootDir: import.meta.dirname,
      },
      // other options...
    },
  },
])

You can also install eslint-plugin-react-x and eslint-plugin-react-dom for React-specific lint rules:

// eslint.config.js
import reactX from 'eslint-plugin-react-x'
import reactDom from 'eslint-plugin-react-dom'

export default defineConfig([
  globalIgnores(['dist']),
  {
    files: ['**/*.{ts,tsx}'],
    extends: [
      // Other configs...
      // Enable lint rules for React
      reactX.configs['recommended-typescript'],
      // Enable lint rules for React DOM
      reactDom.configs.recommended,
    ],
    languageOptions: {
      parserOptions: {
        project: ['./tsconfig.node.json', './tsconfig.app.json'],
        tsconfigRootDir: import.meta.dirname,
      },
      // other options...
    },
  },
])