fix: 修复审批列表首次加载不显示和发起人审批人问题
- 移除 loadingRef,解决 React 18 StrictMode 下请求阻塞问题 - 提交申请时根据选择的审批人动态创建/更新审批节点 - 修改申请提交后跳转到审批列表而非出差列表 - 更新 PROJECT_ISSUES.md 记录所有问题和解决方案 修复问题: 1. 首次进入审批列表"我发起的"不显示数据 2. 发起人也是审批人时"待我审批"不显示 3. 申请提交后跳转到错误的页面 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+109
-8
@@ -31,27 +31,73 @@ const handleTabChange = (key: string) => {
|
||||
|
||||
---
|
||||
|
||||
## 2. 列表首次加载不显示数据问题
|
||||
## 2. 列表首次加载不显示数据问题(多次修复)
|
||||
|
||||
**问题**:首次进入审批列表时,"我发起的"不显示数据,需要切换其他 tab 再切换回来才显示
|
||||
|
||||
**原因**:
|
||||
**原因(版本1)**:
|
||||
- React 18 StrictMode 导致组件快速 mount/unmount
|
||||
- useEffect cleanup 函数中 `requestIdRef.current = null` 清空了请求 ID
|
||||
- 正在进行的 API 请求返回时,`requestIdRef.current` 已经是 null,导致响应被跳过
|
||||
- useEffect cleanup 函数中清空了 requestIdRef,导致正在进行的 API 请求响应被跳过
|
||||
|
||||
**解决方案**:
|
||||
**原因(版本2 - 最终问题)**:
|
||||
- 使用 `loadingRef.current` 检查是否正在加载
|
||||
- React 18 StrictMode 导致 useEffect 执行两次
|
||||
- 第一次请求设置 `loadingRef.current = true`
|
||||
- 第二次请求检查 `loadingRef.current` 为 true,被阻塞
|
||||
- 导致第二次请求没有发送,数据无法加载
|
||||
|
||||
**解决方案(最终版本)**:
|
||||
```typescript
|
||||
// 移除 loadingRef,只使用 requestId 追踪请求
|
||||
const requestIdRef = useRef<string>('')
|
||||
|
||||
const loadData = async (pageNum: number = 1, isRefresh: boolean = false, tab?: string) => {
|
||||
// 生成唯一的请求 ID(包含随机数避免冲突)
|
||||
const requestId = `${tab || activeTab}-${pageNum}-${Date.now()}-${Math.random()}`
|
||||
requestIdRef.current = requestId
|
||||
|
||||
const currentTab = tab || activeTab
|
||||
|
||||
setLoading(true)
|
||||
|
||||
try {
|
||||
const result = await approvalApi.getList({
|
||||
type: currentTab,
|
||||
page: pageNum,
|
||||
page_size: 20,
|
||||
})
|
||||
|
||||
// 检查是否是最新的请求
|
||||
if (requestIdRef.current !== requestId) {
|
||||
return // 跳过过期响应
|
||||
}
|
||||
|
||||
const newList = result?.list || []
|
||||
setList(newList)
|
||||
setHasMore(newList.length >= 20)
|
||||
setPage(pageNum)
|
||||
} catch (error: any) {
|
||||
console.error('Failed to load approvals:', error)
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
// useEffect cleanup 不做任何操作
|
||||
useEffect(() => {
|
||||
loadData(1, true)
|
||||
|
||||
return () => {
|
||||
mountedRef.current = false
|
||||
// 不清空 requestIdRef,让异步请求能够正常完成处理
|
||||
// 不清空任何 ref,让异步请求能够正常完成处理
|
||||
}
|
||||
}, [])
|
||||
```
|
||||
|
||||
**关键点**:
|
||||
- ❌ 不要使用 `loadingRef` 检查来阻塞请求
|
||||
- ❌ 不要在 cleanup 中清空 `requestIdRef`
|
||||
- ✅ 只使用 `requestId` 来标识和忽略过期响应
|
||||
- ✅ 在 requestId 中加入随机数避免 React 18 StrictMode 下的冲突
|
||||
|
||||
**相关文件**:`frontend/src/pages/approval/list.tsx`
|
||||
|
||||
---
|
||||
@@ -340,6 +386,61 @@ const loadData = async (tab?: string) => {
|
||||
### 20. Docker 容器 CMD
|
||||
**使用前台运行**:`php start.php start`(不要用 `-d`),避免容器退出
|
||||
|
||||
### 21. 发起人也是审批人时"待我审批"不显示
|
||||
|
||||
**问题**:用户提交申请后,既是发起人也是审批人,但"待我审批"中不显示该订单
|
||||
|
||||
**原因**:
|
||||
- `BusinessTripService::submit()` 中硬编码 `current_nodes => [1]`
|
||||
- 但数据库中节点 1 的审批人是其他用户(如用户 2)
|
||||
- 提交申请时没有根据用户选择的审批人创建/更新节点
|
||||
|
||||
**解决方案**:
|
||||
```php
|
||||
// 根据审批人创建审批节点
|
||||
$approverIds = array_column($approvers, 'id');
|
||||
$node = ApprovalNode::where('flow_id', $flow->id)
|
||||
->where('order', 0)
|
||||
->first();
|
||||
|
||||
if (!$node) {
|
||||
// 创建第一个审批节点
|
||||
$node = ApprovalNode::create([
|
||||
'flow_id' => $flow->id,
|
||||
'type' => count($approverIds) > 1 ? 'and_approve' : 'approver',
|
||||
'name' => '审批',
|
||||
'order' => 0,
|
||||
'approvers' => $approverIds,
|
||||
]);
|
||||
} else {
|
||||
// 更新现有节点的审批人
|
||||
$node->approvers = $approverIds;
|
||||
$node->save();
|
||||
}
|
||||
|
||||
// 使用创建的节点 ID
|
||||
$approvalOrder = ApprovalOrder::create([
|
||||
// ...
|
||||
'current_nodes' => [$node->id],
|
||||
// ...
|
||||
]);
|
||||
```
|
||||
|
||||
**相关文件**:`backend/app/service/BusinessTripService.php`
|
||||
|
||||
### 22. 申请提交后跳转到错误的页面
|
||||
|
||||
**问题**:提交申请后跳转到出差列表 (`/business-trip`),而不是审批列表 (`/approval`)
|
||||
|
||||
**解决方案**:
|
||||
```typescript
|
||||
// 修改申请页面跳转逻辑
|
||||
Toast.show(t('businessTrip.submitSuccess'))
|
||||
navigate('/approval') // 改为跳转到审批列表
|
||||
```
|
||||
|
||||
**相关文件**:`frontend/src/pages/business-trip/apply.tsx`
|
||||
|
||||
---
|
||||
|
||||
## 文件修改记录
|
||||
|
||||
Reference in New Issue
Block a user