7.0 KiB
7.0 KiB
前端锁定修复总结(2026-03-05)
修复概述
按照系统设计理念(管理员操作时全局锁定),修复了两个前端锁定问题:
- ✅ 数据分发任务锁定(P0 高优先级)
- ✅ 扫描任务锁定(P1 中优先级)
修复 1:数据分发任务锁定
问题
DataCopierPanel 是独立的任务管理系统,不与全局锁定机制集成。
修改文件
frontend/src/App.jsxfrontend/src/DataCopierPanel.jsx
修改内容
App.jsx (1334 行):
// 修改前
<DataCopierPanel
apiEndpoint={apiClient.defaults.baseURL}
readOnly={isReadOnlyUser}
/>
// 修改后
<DataCopierPanel
apiEndpoint={apiClient.defaults.baseURL}
readOnly={isReadOnlyUser}
onJobQueued={(taskId) => handleTaskStart(taskId, '数据分发任务已入队,正在处理...')}
/>
DataCopierPanel.jsx (14 行):
// 修改前
const DataCopierPanel = ({ apiEndpoint, readOnly = false }) => {
// 修改后
const DataCopierPanel = ({ apiEndpoint, readOnly = false, onJobQueued }) => {
DataCopierPanel.jsx (119-131 行):
// 修改前
try {
const response = await axios.post(endpoint, {
batch_id: selectedBatchId,
dest_dir: destDir,
copy_statuses: copyStatuses,
}, { withCredentials: true });
setTaskId(response.data.task_id);
} catch (error) {
// 修改后
try {
const response = await axios.post(endpoint, {
batch_id: selectedBatchId,
dest_dir: destDir,
copy_statuses: copyStatuses,
}, { withCredentials: true });
const taskId = response.data.task_id;
setTaskId(taskId);
// 触发全局锁定
if (onJobQueued) {
onJobQueued(taskId);
}
} catch (error) {
效果
- 数据分发任务启动时,前端立即锁定
- 任务完成后,前端自动解锁
- 与其他任务(IDL 自动化、数据监控)行为一致
修复 2:扫描任务锁定
问题
扫描任务执行太快(< 3 秒),前端轮询间隔(3 秒)来不及捕获 RUNNING 状态。
修改文件
frontend/src/DataMonitorPanel.jsx
修改内容
DataMonitorPanel.jsx (168-198 行):
// 修改前
const handleRunNow = async (target) => {
// ... 验证逻辑 ...
setLoading(true);
setMessage(`正在触发${targetMap[target] || '全部'}手动扫描...`);
try {
const url = target ? `${apiEndpoint}/monitor/run-now?target=${target}` : `${apiEndpoint}/monitor/run-now`;
const res = await fetch(url, {
method: 'POST',
credentials: 'include'
});
const data = await res.json();
if (res.ok) {
setMessage(data.message);
if (onTaskStart) onTaskStart(data.task_id, `已触发${targetMap[target] || '全部'}手动扫描...`);
}
// ...
}
};
// 修改后
const handleRunNow = async (target) => {
// ... 验证逻辑 ...
setLoading(true);
setMessage(`正在触发${targetMap[target] || '全部'}手动扫描...`);
// 立即触发全局锁定(在 API 调用之前)
if (onTaskStart) {
onTaskStart(null, `正在触发${targetMap[target] || '全部'}手动扫描...`);
}
try {
const url = target ? `${apiEndpoint}/monitor/run-now?target=${target}` : `${apiEndpoint}/monitor/run-now`;
const res = await fetch(url, {
method: 'POST',
credentials: 'include'
});
const data = await res.json();
if (res.ok) {
setMessage(data.message);
// 更新任务 ID
if (onTaskStart) onTaskStart(data.task_id, `已触发${targetMap[target] || '全部'}手动扫描...`);
}
// ...
}
};
关键改进
- 在 API 调用之前立即锁定:
onTaskStart(null, message) - API 成功后更新任务 ID:
onTaskStart(taskId, message) - 失败时自动解锁:全局轮询检测到没有活跃任务时自动解锁
效果
- 用户点击"扫描"按钮后,前端立即锁定
- 即使任务执行很快(< 3 秒),用户也能看到锁定状态
- 任务完成后,前端自动解锁
测试验证
测试 1:数据分发任务锁定
- 登录管理员账号
- 进入"数据分发" Tab
- 选择批次和目标目录
- 点击"开始复制"
- 预期:前端立即锁定,显示"数据分发任务已入队,正在处理..."
- 等待任务完成
- 预期:前端自动解锁
测试 2:扫描任务锁定
- 登录管理员账号
- 进入"数据管理" Tab
- 点击"扫描雷达数据"或"扫描 D-InSAR 结果"
- 预期:前端立即锁定,显示"正在触发...手动扫描..."
- 等待任务完成(可能很快)
- 预期:前端自动解锁
测试 3:多任务冲突
- 启动数据分发任务
- 预期:前端锁定,无法启动其他任务
- 尝试点击其他操作按钮
- 预期:按钮被禁用或操作被阻止
技术细节
handleTaskStart 函数行为
// hooks/useDinsarOperations.js:123-129
const handleTaskStart = (taskId, message) => {
if (taskId) {
setPendingTaskIds(prev => [...prev, taskId]);
}
setIsGlobalLocked(true); // 总是锁定
if (message) addLog('info', message);
};
关键点:
taskId可以为null(立即锁定,稍后更新 ID)setIsGlobalLocked(true)总是执行(无论 taskId 是否为 null)- 这允许我们在 API 调用之前就锁定前端
解锁机制
前端通过 useGlobalTaskControl hook 自动解锁:
// hooks/useGlobalTaskControl.js:56-64
if (hasRunningTasks !== isGlobalLockedRef.current) {
setIsGlobalLocked(hasRunningTasks);
if (!hasRunningTasks) {
addLog('success', '后台任务已完成,正在同步最新数据...');
setTimeout(() => {
initializeAppDataRef.current?.({ refreshRadarSearch: true });
}, 500);
}
}
工作原理:
- 每 3 秒轮询
/tasks/active - 检测到没有活跃任务时,自动解锁
- 不需要手动调用解锁
修改总结
修改文件
frontend/src/App.jsx- 1 处修改(添加 onJobQueued 回调)frontend/src/DataCopierPanel.jsx- 2 处修改(接收回调 + 调用回调)frontend/src/DataMonitorPanel.jsx- 1 处修改(提前锁定)
代码行数
- 新增:约 10 行
- 修改:约 5 行
- 删除:0 行
风险评估
- 🟢 低风险:改动小,逻辑清晰
- 🟢 向后兼容:不影响现有功能
- 🟢 易于回滚:修改集中,容易撤销
相关文档
ANALYSIS_FRONTEND_LOCKING_2026-03-05.md- 问题分析SECURITY_FIX_PROGRESS.md- 修复进度跟踪HOTFIX_PROJ_CONFLICT_2026-03-05.md- PROJ 冲突修复
下一步
- ✅ 代码修改完成
- ⏳ 前端构建测试
- ⏳ 功能测试验证
- ⏳ 用户验收测试
修复完成时间:2026-03-05 修复人:Claude Opus 4.6 状态:✅ 代码修改完成,等待测试验证