chore: initialize insar management system v2
This commit is contained in:
@@ -0,0 +1,265 @@
|
||||
# 前端锁定修复总结(2026-03-05)
|
||||
|
||||
## 修复概述
|
||||
|
||||
按照系统设计理念(管理员操作时全局锁定),修复了两个前端锁定问题:
|
||||
|
||||
1. ✅ **数据分发任务锁定**(P0 高优先级)
|
||||
2. ✅ **扫描任务锁定**(P1 中优先级)
|
||||
|
||||
---
|
||||
|
||||
## 修复 1:数据分发任务锁定
|
||||
|
||||
### 问题
|
||||
`DataCopierPanel` 是独立的任务管理系统,不与全局锁定机制集成。
|
||||
|
||||
### 修改文件
|
||||
1. `frontend/src/App.jsx`
|
||||
2. `frontend/src/DataCopierPanel.jsx`
|
||||
|
||||
### 修改内容
|
||||
|
||||
**App.jsx (1334 行)**:
|
||||
```javascript
|
||||
// 修改前
|
||||
<DataCopierPanel
|
||||
apiEndpoint={apiClient.defaults.baseURL}
|
||||
readOnly={isReadOnlyUser}
|
||||
/>
|
||||
|
||||
// 修改后
|
||||
<DataCopierPanel
|
||||
apiEndpoint={apiClient.defaults.baseURL}
|
||||
readOnly={isReadOnlyUser}
|
||||
onJobQueued={(taskId) => handleTaskStart(taskId, '数据分发任务已入队,正在处理...')}
|
||||
/>
|
||||
```
|
||||
|
||||
**DataCopierPanel.jsx (14 行)**:
|
||||
```javascript
|
||||
// 修改前
|
||||
const DataCopierPanel = ({ apiEndpoint, readOnly = false }) => {
|
||||
|
||||
// 修改后
|
||||
const DataCopierPanel = ({ apiEndpoint, readOnly = false, onJobQueued }) => {
|
||||
```
|
||||
|
||||
**DataCopierPanel.jsx (119-131 行)**:
|
||||
```javascript
|
||||
// 修改前
|
||||
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 行)**:
|
||||
```javascript
|
||||
// 修改前
|
||||
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] || '全部'}手动扫描...`);
|
||||
}
|
||||
// ...
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### 关键改进
|
||||
1. **在 API 调用之前立即锁定**:`onTaskStart(null, message)`
|
||||
2. **API 成功后更新任务 ID**:`onTaskStart(taskId, message)`
|
||||
3. **失败时自动解锁**:全局轮询检测到没有活跃任务时自动解锁
|
||||
|
||||
### 效果
|
||||
- 用户点击"扫描"按钮后,前端立即锁定
|
||||
- 即使任务执行很快(< 3 秒),用户也能看到锁定状态
|
||||
- 任务完成后,前端自动解锁
|
||||
|
||||
---
|
||||
|
||||
## 测试验证
|
||||
|
||||
### 测试 1:数据分发任务锁定
|
||||
1. 登录管理员账号
|
||||
2. 进入"数据分发" Tab
|
||||
3. 选择批次和目标目录
|
||||
4. 点击"开始复制"
|
||||
5. **预期**:前端立即锁定,显示"数据分发任务已入队,正在处理..."
|
||||
6. 等待任务完成
|
||||
7. **预期**:前端自动解锁
|
||||
|
||||
### 测试 2:扫描任务锁定
|
||||
1. 登录管理员账号
|
||||
2. 进入"数据管理" Tab
|
||||
3. 点击"扫描雷达数据"或"扫描 D-InSAR 结果"
|
||||
4. **预期**:前端立即锁定,显示"正在触发...手动扫描..."
|
||||
5. 等待任务完成(可能很快)
|
||||
6. **预期**:前端自动解锁
|
||||
|
||||
### 测试 3:多任务冲突
|
||||
1. 启动数据分发任务
|
||||
2. **预期**:前端锁定,无法启动其他任务
|
||||
3. 尝试点击其他操作按钮
|
||||
4. **预期**:按钮被禁用或操作被阻止
|
||||
|
||||
---
|
||||
|
||||
## 技术细节
|
||||
|
||||
### handleTaskStart 函数行为
|
||||
|
||||
```javascript
|
||||
// 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 自动解锁:
|
||||
|
||||
```javascript
|
||||
// hooks/useGlobalTaskControl.js:56-64
|
||||
if (hasRunningTasks !== isGlobalLockedRef.current) {
|
||||
setIsGlobalLocked(hasRunningTasks);
|
||||
if (!hasRunningTasks) {
|
||||
addLog('success', '后台任务已完成,正在同步最新数据...');
|
||||
setTimeout(() => {
|
||||
initializeAppDataRef.current?.({ refreshRadarSearch: true });
|
||||
}, 500);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**工作原理**:
|
||||
1. 每 3 秒轮询 `/tasks/active`
|
||||
2. 检测到没有活跃任务时,自动解锁
|
||||
3. 不需要手动调用解锁
|
||||
|
||||
---
|
||||
|
||||
## 修改总结
|
||||
|
||||
### 修改文件
|
||||
1. `frontend/src/App.jsx` - 1 处修改(添加 onJobQueued 回调)
|
||||
2. `frontend/src/DataCopierPanel.jsx` - 2 处修改(接收回调 + 调用回调)
|
||||
3. `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 冲突修复
|
||||
|
||||
---
|
||||
|
||||
## 下一步
|
||||
|
||||
1. ✅ 代码修改完成
|
||||
2. ⏳ 前端构建测试
|
||||
3. ⏳ 功能测试验证
|
||||
4. ⏳ 用户验收测试
|
||||
|
||||
---
|
||||
|
||||
**修复完成时间**:2026-03-05
|
||||
**修复人**:Claude Opus 4.6
|
||||
**状态**:✅ 代码修改完成,等待测试验证
|
||||
Reference in New Issue
Block a user