diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 58733c3..02a0864 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -1,6 +1,6 @@ # 船长 · HeiXiu — 前端架构文档 -> 最后更新:2026-06-08 +> 最后更新:2026-06-09 ## 目录结构 @@ -165,18 +165,20 @@ NavBar / 设置页 → AppProvider.logout() - 纯发布-订阅,不依赖任何框架 - 用于跨模块解耦通信(如 axios 拦截器无法直接用 React Context) -- 预定义事件:`AUTH_REQUIRED` / `SHOW_LOGIN` / `LOGIN_SUCCESS` / `LOGOUT` / `TASK_SUBMITTED` / `OPEN_SETTINGS` +- 预定义事件:`AUTH_REQUIRED` / `SHOW_LOGIN` / `LOGIN_SUCCESS` / `LOGOUT` / `TASK_SUBMITTED` / `OPEN_SETTINGS` / `OPEN_PAGE` ### 页面叠加层模式(QT 多窗口模型映射) 本项目是 Python QT 桌面应用的 Web 重构版。QT 应用以"新开窗口"为常态,原窗口不因新窗口打开而销毁。Web 端对应原则: -| QT 原版 | Web 对应 | 实现方式 | -|---------|---------|---------| -| 新开窗口叠加在主窗口之上 | Modal / Drawer | 事件总线驱动,主页面不卸载 | -| Tab 切换 / 视图替换 | React Router | 跨页状态放 Provider 或 localStorage | +| QT 原版 | Web 对应 | 实现方式 | +|---------------|----------------|-------------------------------| +| 新开窗口叠加在主窗口之上 | Modal / Drawer | 事件总线驱动,主页面不卸载 | +| Tab 切换 / 视图替换 | React Router | 跨页状态放 Provider 或 localStorage | **当前叠加层**: + +- `PageDispatcher` — 统一页面调度器,监听 `OPEN_PAGE` 事件,根据 `modalType` 渲染 Modal/Drawer/FloatingPanel,全局互斥(同一时刻最多一个面板) - LoginPage — Modal,事件总线 `SHOW_LOGIN` / `AUTH_REQUIRED` 触发 - SettingsPage — Modal,事件总线 `OPEN_SETTINGS` 触发 - AnnouncementDrawer — Drawer,NavBar 内部 state 控制 diff --git a/CHANGELOG.md b/CHANGELOG.md index 1417d71..d226185 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,21 @@ > 每次发版前修改此文件,`npm run build:win` 打包后会自动读取生成 update-info.json。 --- +## 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) **主题切换性能优化 — 桌面端流畅度提升** diff --git a/TODO.md b/TODO.md index b9b9537..10aad2d 100644 --- a/TODO.md +++ b/TODO.md @@ -1,6 +1,6 @@ # TODO — 船长·HeiXiu 待办与优化清单 -> 最后更新:2026-06-08 +> 最后更新:2026-06-09 --- @@ -14,10 +14,10 @@ ### 路由与页面 +- [x] 账户信息页面(`/account`) — `AccountInfo.tsx`,AuthAPI.getUserInfo() 驱动 - [ ] 合规素材库页面(`/compliance-assets`) - [ ] 项目管理页面(`/projects`,企业版) -- [ ] 账户/会员/充值/消费记录/订单明细页面 -- [ ] 各页面暗色主题适配 +- [ ] 会员/充值/消费记录/订单明细页面 ### 导航栏 diff --git a/src/pages/home/HomeContent.tsx b/src/pages/home/HomeContent.tsx index 1270a12..19e11dc 100644 --- a/src/pages/home/HomeContent.tsx +++ b/src/pages/home/HomeContent.tsx @@ -3,7 +3,7 @@ // 可拖拽调整三栏宽度,所有数据请求在登录后发送 // ============================================================ -import { createContext, useContext, useState, useCallback, useRef, useEffect, useMemo } from 'react'; +import React, { createContext, useContext, useState, useCallback, useRef, useEffect, useMemo } from 'react'; import { theme as antTheme, Empty } from 'antd'; import { useAppContext } from '@/components/AppProvider'; diff --git a/src/pages/home/components/ModelInputForm.tsx b/src/pages/home/components/ModelInputForm.tsx index 4fd46e2..cb4b950 100644 --- a/src/pages/home/components/ModelInputForm.tsx +++ b/src/pages/home/components/ModelInputForm.tsx @@ -75,12 +75,17 @@ function DependentFormItem({ onChange?: (value: unknown) => void; disabled?: boolean; }) { - const depValues = (field.dependsOn || []).map((depName) => - Form.useWatch(depName, form), - ); + // Form.useWatch 必须在组件顶层无条件调用(不能放 .map() 或条件分支中)。 + // dependsOn 长度由 param_schema 约束(当前 API 最多 2 个), + // 预留 3 个固定槽位覆盖未来扩展;无依赖时 watch 空串 → 返回 undefined。 + const deps = field.dependsOn || []; + const d0 = Form.useWatch(deps[0] || '', form); + const d1 = Form.useWatch(deps[1] || '', form); + const d2 = Form.useWatch(deps[2] || '', form); + const depValues = [d0, d1, d2].slice(0, deps.length); const isDepDisabled = - field.dependsOn?.some((_, i) => isValueEmpty(depValues[i])) ?? false; + deps.some((_, i) => isValueEmpty(depValues[i])); const effectiveDisabled = formItemDisabled || isDepDisabled; const effectiveConfig = effectiveDisabled @@ -115,7 +120,7 @@ export function ModelInputForm() { // 提交突变 Hook const { execute: submitTask, loading: submitting, errorMessage } = useSubmitTask({ onSuccess: useCallback((_data: TaskInfoItemResponseBody) => { - message.success('任务已提交'); + void message.success('任务已提交'); emit(EVENTS.TASK_SUBMITTED); }, []), }); @@ -147,7 +152,7 @@ export function ModelInputForm() { form.setFieldsValue(initialValues); setTaskTag(''); } - }, [selectedModel?.id, initialValues]); + }, [selectedModel?.id, initialValues, selectedModel, form]); // 重置参数(回到默认值 + 清空标签) const handleReset = useCallback(() => { @@ -384,7 +389,7 @@ export function ModelInputForm() {