# 更新日志 > 每次发版前修改此文件,`npm run build:win` 打包后会自动读取生成 update-info.json。 --- ## 0.0.20(2026-06-12) **任务状态轮询 + Token 刷新容错增强 + 提交防抖 + 文件上传 Hook** ### 任务状态轮询 - 新增 `useTaskPolling` hook:批量轮询非终态任务状态,递归 `setTimeout` + `next_poll_ms` 自适应间隔 - `TaskHistory` 集成批量轮询,`OutputPreview` 改为监听终态转换(Context 桥接)触发 `refetch()`,消除重复请求 - `POLLING_STATUSES` 统一管理非终态状态,所有轮询逻辑引用此常量 - `batchTaskStatus` 使用 GET + 逗号拼接 `task_ids=a,b,c`,修复 axios 默认 bracket 序列化 ### Token 刷新容错增强 - **主动刷新**:JWT `exp` 解码驱动定时器,在 75% 过期点通过 `setTimeout` 提前续期 - **失败分级**:`refreshHandler` 永久失败(refresh_token 过期)→ **throw** → 清 token 弹登录;临时失败(网络超时)→ **return null** → 仅拒绝当前请求不登出 - 新增 `RefreshTokenExpiredError` 类区分失败类型 - `AppProvider` 登录/自动登录/退出 启停主动刷新定时器 ### 提交按钮防抖 - 两级防护:2s 节流防抖("你点击的太快了")+ 二次确认弹窗("您已提交,确认要再次提交吗?") - `doSubmit` 抽取为 `useCallback`,`handleSubmit` 负责门控 - 修复 `useAsyncMutation.execute` 返回值判空(原 `try/catch` 为死代码) ### 文件上传 Hook - 新增 `useFileUpload` hook:封装 `request.upload()` 为 antd Upload 兼容 `customRequest`,复用全局拦截器 - `ImageInput` / `ImageListInput` / `AudioListInput` 集成 `customRequest` - `uploadValidation.beforeUpload` 返回值修正:`false` → `true`(校验通过后放行至 `customRequest`) ### 其他 - `AnnouncementDrawer` 接入公告 API + `EnumResolver` - billing / announcement / banner 服务模块完善 - 文档:ARCHITECTURE.md 新增轮询/Token刷新/上传/防抖章节 --- ## 0.0.19(2026-06-11) **数据获取架构重构 + Mac 指纹采集 + Token 刷新容错 + 账单页面** ### 数据获取架构重构 - `useAsyncData` 集成 AbortController:cleanup 时真正中断 HTTP 请求,不再仅丢弃响应(解决 StrictMode 双重请求) - fetcher 签名变更:`() => Promise` → `(signal: AbortSignal) => Promise` - API 模块统一 `signal?: AbortSignal` 可选参数,透传 axios config(banner/auth/models/task/vip) - `use-api.ts` 成为数据 Hook 集中管理中心: - 新增 `useAccountInfo` — `Promise.all` 并行获取用户信息 + VIP 等级 - 新增 `useBillingBalance` — 账户余额 - 新增 `useBillingLedger` — 账单明细(支持分页参数) - `AccountInfo.tsx` 重构:~40 行手写状态管理(`useRef`+`useEffect`+`cancelled`+`retryTick`)→ 1 行 `useAccountInfo()` - 共享工具 `src/utils/display.ts` — `centToYuan` / `formatDate`,消除 AccountInfo/BillingInfo 重复定义 - 移除 `modelFirstFetchDone` 模块级变量(StrictMode 不安全) ### Mac 硬件指纹采集 - `electron/preload/device.ts` Mac 完整实现: - UUID:`ioreg -d2 -c IOPlatformExpertDevice` → `IOPlatformUUID` - CPU:`sysctl -n hw.model` → 机型标识 - HDD:三级回退 `system_profiler SPNVMeDataType` → `SPSerialATADataType` → `SPHardwareDataType` - `isMacOS()` / `runMacCommand()` / `getMacHddValue()` 辅助函数 - `getComponentId()` / `fingerprintSha256()` Mac 早退分支,与 Windows 共享 SHA256 管线 ### 账单页面 - `BillingInfo.tsx` — 余额卡片(BalanceCard)+ 账单表格(LedgerTable)+ 分页 - `BillingAPI` — `getBalance` / `getLedger`,`signal` 参数透传 - `PageDispatcher` 注册 `/billing` 页面(FloatingPanel 960×680) - 修复 `billing.ts` signal 参数位置 bug:`get(url, {signal})` → `get(url, undefined, {signal})` - BillingInfo 标题精简:移除冗余页面 Title 和 Card title,仅保留 FloatingPanel 标题栏 ### Bug 修复 - **Token 刷新容错**(`auth-token.ts`):网络错误/超时时保留 refresh_token,仅 RefreshError(token 过期)时清除。 解决网络短暂中断后被迫手动重新登录的问题 - **AppProvider 自动登录**:`email`/`admin_permissions` 等 nullable 字段默认值修复(`?? ''` / `?? []`) - **antd Table align**:`align: 'left'` → `align: 'left' as const`,修复 TS2322 类型错误 - **分页器位置**:显式添加 `position: ['bottomRight']` ### 文档 - CLAUDE.md 精简为 AI 行为规则,项目技术内容移入 ARCHITECTURE.md - ARCHITECTURE.md 新增:数据获取架构、页面调度详情、Token 刷新错误分类、设备指纹 --- ## 0.0.18(2026-06-10) **前后端联调 — 任务创建 + 账户信息 + 预估花费** ### 任务创建联调 - `CreatTaskRequestBody.device_id` 改为后端必填参数,API 层 `Omit` 封装,自动注入 `getDeviceId()`(UUID v4 持久化,与登录/注册统一) - `useSubmitTask` 泛型同步改为 `Omit`,调用方无感 - `submitTask` 移除 `body.device_id || getDeviceId()` 兜底逻辑,始终以本地生成的设备 ID 为准 ### 预估花费计算(与 QT/Python 后端对齐) - `src/utils/pricing.ts` — 从 Python 后端 `calculate_cost` 完整移植六种定价模式: - 服务端:`SIMPLE` · `MULTI_DIMENSION` · `BILLING_ADAPTER`(per_k_chars / rate + 条件附加费) - 客户端:`fixed` · `per_k_chars` · `rate_matrix` · `matrix` - `ModelInputForm.tsx` — 三层兜底预估消费展示:完整动态计价 → 配置文件兜底提取 → 模式标签 - **修复 6 个定价 Bug**: - SIMPLE 浮点冗余 `(x/100)*100` 在 IEEE 754 下不恒等 → `Math.round(分子)/100` - `rate_matrix` / `matrix` 内联维度匹配缺少 `.trim().toLowerCase()` + null 跳过 → 统一 `matchDimensions()` - `lookupMappingValue` / `matchDimensions` 缺 null 守卫 → `Cannot use 'in' operator` 崩溃 - `rate_matrix` 错误应用 `unit_scale`(Python spec 无此行为)→ 移除乘法 - `matrix` 模式 `dimensions` 空值提前返 null(与 `MULTI_DIMENSION` 不一致)→ 对齐处理 - 矩阵维度提取 `row.raw` — API 实际在行顶层存储维度(如 `resolution`),`raw` 子对象不存在 → `matrixRowData()` 兼容两种格式 - `pricing_config` 类型修正:`Record` → `Record | null`(对齐 OpenAPI `anyOf`) - 修复 React Hooks 顺序违例 — `estimatedCostDisplay` useMemo 移至提前返回之前 ### 账户信息联调 - `AccountInfo.tsx` "当前套餐"从 VIP 等级列表匹配详细数据: - `vip_level_id` → `VipLevelsItem.id` 映射查找 - 新增套餐说明、套餐周期字段,席位上限优先取 VIP 等级值 - 到期时间提取 `isExpired` 变量复用 - `VipAPI.getVipLevels()` 与 `AuthAPI.getUserInfo()` 并行加载 ### 模型列表缓存 - 加密持久化缓存(safe-storage):启动时 `Promise.all` 初始化,缓存优先渲染消除 loading 闪烁 - `useModelList` Stale-while-revalidate:即时展示缓存 → 后台拉新 → 覆盖缓存 ### 其他 - VIP API 模块(`src/services/modules/vip-api.ts`)— 激活码/等级列表/订单/模拟支付 - ESLint/TS 类型修复(未使用符号清理、分号补充) - CLAUDE.md 更新系统兼容性说明 --- ## 0.0.17(2026-06-09) **修复接口重复调用 — 请求量减半** - AppProvider 自动登录 useEffect 增加 aborted 清理标志,修复 StrictMode 双重挂载导致 refreshToken/getUserInfo 各调两次 - useModelList 提升到 LeftPanel 单例调用,修复 ModelSelector 和 TaskHistory 各自独立请求全量模型列表 - 开发模式 DevTools 中"已停止"的请求即为 StrictMode 第一轮挂载被丢弃的请求 - 模型输入栏三层架构:useUI 组件体系(10 种 widget → antd 映射)+ useModelUI Hook(param_schema → UIFieldConfig[]) - constraints_config.requires 动态联动:enable_switch 开关控制依赖字段启用/禁用 - 修复模型默认值不加载(antd 外部 form 实例忽略 initialValues)+ DependentFormItem prop 透传断裂 - PageDispatcher 统一页面调度:Modal/Drawer/FloatingPanel 三容器,全局互斥,动态视口尺寸 - 账户信息页:AuthAPI.getUserInfo() 驱动,积分/套餐/统计三卡片布局 - 代码去重:runFieldChecks 校验运行器 + createImageBeforeUpload 上传校验工厂 - 主题切换性能优化 — View Transitions API + 0.15s 统一过渡 + 设置页增强(0.0.15 延续) - 目录调整:wechat-work/ → headers/ --- ## 0.0.16(2026-06-09) **模型输入栏重构 + 统一页面调度 + 依赖联动** - 模型输入栏三层架构:useUI 组件体系(10 种 widget → antd 映射)+ useModelUI Hook(param_schema → UIFieldConfig[]) - constraints_config.requires 动态联动:enable_switch 开关控制依赖字段启用/禁用 - 修复模型默认值不加载(antd 外部 form 实例忽略 initialValues)+ DependentFormItem prop 透传断裂 - PageDispatcher 统一页面调度:Modal/Drawer/FloatingPanel 三容器,全局互斥,动态视口尺寸 - 账户信息页:AuthAPI.getUserInfo() 驱动,积分/套餐/统计三卡片布局 - 代码去重:runFieldChecks 校验运行器 + createImageBeforeUpload 上传校验工厂 - 主题切换性能优化 — View Transitions API + 0.15s 统一过渡 + 设置页增强(0.0.15 延续) - 目录调整:wechat-work/ → headers/ --- ## 0.0.15(2026-06-09) **主题切换性能优化 — 桌面端流畅度提升** - View Transitions API 驱动主题切换:GPU 合成器单次 cross-fade 替代 80+ 个独立 CSS 过渡,消除 Electron 卡顿 - 主题更新时序统一:`applyHtmlTheme` 从 updater → `useLayoutEffect`,CSS 变量与 React 提交同帧 - 过渡参数对齐:全部 `0.2s ease` → `0.15s linear`,桌面应用更利落 - CSS 过渡精准覆盖:antd 容器组件(Layout/Card/Modal/Table/Input/Menu 等 ~80 个类)替代 `html *` 全局选择器 - 设置页 Esc 键关闭 + macOS 关闭按钮适配 + 关闭后焦点防跳转 --- ## 0.0.14 -- 🚀更新公告 **模型选择器焕新** - 模型列表改为标签页分组展示,新增「全部模型」Tab - 列表项新增悬停高亮效果,维护中模型自动置灰并提示 - 修复选择模型后参数表单重复 key 报错 - 类型体系重构,支持后端分类 slug 自动映射 --- ## 0.0.13(2026-06-07) - 修复主题切换后首页状态重置问题:设置页去路由化,改为事件总线驱动的 Modal 叠加 - 首页三栏分隔条视觉对齐:移除右侧多余 margin,左右完全对称 - 轮播图新增关闭按钮:session 级别隐藏,每次启动重新展示 - 确立 QT 多窗口模型 → Web 架构映射原则:叠加层走 Modal/Drawer + 事件总线,不走路由 - 修复首页三栏布局溢出:拖拽分隔条增加最大宽度约束 + 视口缩小时自动收窄面板,防止右侧面板被挤出视口 --- ## 0.0.12(2026-06-04) - 重构更新检查流程:无更新不再抛异常,PreCheck → 直接 IPC 通知 - 新增用户决定下载流程:检查到新版本后展示更新内容,用户确认后再下载 - 设置页新增"查看详情"弹窗,Markdown 格式化展示更新日志 - 新增"下载更新"按钮,与"安装更新"分离为两个独立操作 - 修复测试服务器版本排序(字符串序 → 语义版本序,0.0.10 正确排在 0.0.9 之后) - electron-updater Provider 增加 TTL 缓存,避免重复 API 请求 - 修复 Windows cmd `set` 命令空格导致的 Invalid URL 问题 - 修复 electron-updater 'error' 事件拦截,无更新不再爆红 --- ## 格式说明 每个版本以 `## x.y.z(日期)` 开头,内容为无序列表。打包脚本会提取最新版本的日志填入 update-info.json。