docs: 整理项目问题文档,修复审批列表数据混乱

- 新增 PROJECT_ISSUES.md 统一管理所有问题和解决方案
- 精简 CLAUDE.md,移除重复的问题记录部分
- 修复审批列表数据混乱问题(React 18 StrictMode + 状态管理)
- 修复首次加载不显示数据问题(requestIdRef 清理时机)
- 修复页码初始值错误(hasMore 默认值)
- 修复后端响应序列化问题(Eloquent 模型转数组)
- 添加审批人和抄送人重复校验
- 修复双 header 问题
- 调整申请页面 padding-bottom

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
root
2026-02-26 09:12:21 +08:00
parent 214992b163
commit b7919910f1
9 changed files with 559 additions and 220 deletions
+12 -7
View File
@@ -38,14 +38,19 @@ class ApprovalController extends BaseController
$page = (int) $request->get('page', 1);
$pageSize = (int) $request->get('page_size', 20);
// 添加日志
error_log("Approval list request: userId={$userId}, type={$type}, page={$page}");
try {
$result = $this->service->getList($userId, $type, $page, $pageSize);
$result = $this->service->getList($userId, $type, $page, $pageSize);
error_log("Approval list result: count=" . count($result['list']));
return $this->success($result);
// 使用 json() 全局函数返回 JSON
return json([
'code' => 0,
'message' => 'success',
'data' => $result,
]);
} catch (\Exception $e) {
error_log("❌ Error in list controller: " . $e->getMessage() . "\n" . $e->getTraceAsString());
return $this->error($e->getMessage());
}
}
/**
+27 -1
View File
@@ -183,10 +183,12 @@ class ApprovalService
switch ($type) {
case 'my':
$query->where('applicant_id', $userId);
error_log("🔍 Debug 'my' query: userId={$userId}");
break;
case 'pending':
// 获取用户待审批的订单
$pendingOrderIds = $this->getPendingOrderIds($userId);
error_log("🔍 Debug 'pending' query: userId={$userId}, pendingOrderIds=" . json_encode($pendingOrderIds));
$query->whereIn('id', $pendingOrderIds);
break;
case 'approved':
@@ -197,19 +199,43 @@ class ApprovalService
->pluck('order_id')
->unique()
->toArray();
error_log("🔍 Debug 'approved' query: userId={$userId}, approvedOrderIds=" . json_encode($approvedOrderIds));
$query->whereIn('id', $approvedOrderIds)
->whereIn('status', [ApprovalOrder::STATUS_APPROVED, ApprovalOrder::STATUS_REJECTED, ApprovalOrder::STATUS_CANCELLED]);
break;
}
$total = $query->count();
error_log("🔍 Debug total count: type={$type}, total={$total}");
$list = $query->orderBy('created_at', 'desc')
->offset(($page - 1) * $pageSize)
->limit($pageSize)
->get();
error_log("🔍 Debug list count: type={$type}, page={$page}, count=" . $list->count());
// 转换为数组避免序列化问题
$listArray = $list->map(function ($item) {
return [
'id' => $item->id,
'title' => $item->title,
'business_type' => $item->business_type,
'status' => $item->status,
'created_at' => $item->created_at ? $item->created_at->toDateTimeString() : null,
'applicant' => $item->applicant ? [
'id' => $item->applicant->id,
'name' => $item->applicant->name,
] : null,
'flow' => $item->flow ? [
'id' => $item->flow->id,
'name' => $item->flow->name,
] : null,
];
})->toArray();
return [
'list' => $list,
'list' => $listArray,
'total' => $total,
'page' => $page,
'page_size' => $pageSize,
@@ -103,6 +103,26 @@ class BusinessTripService
throw new \Exception('当前状态无法提交');
}
// 验证审批人和抄送人不能重复
$approverIds = array_column($approvers, 'id');
$ccUserIds = array_column($ccUsers, 'id');
// 检查审批人列表中是否有重复
if (count($approverIds) !== count(array_unique($approverIds))) {
throw new \Exception('审批人列表中有重复用户');
}
// 检查抄送人列表中是否有重复
if (count($ccUserIds) !== count(array_unique($ccUserIds))) {
throw new \Exception('抄送人列表中有重复用户');
}
// 检查审批人和抄送人是否有重叠
$overlap = array_intersect($approverIds, $ccUserIds);
if (!empty($overlap)) {
throw new \Exception('审批人和抄送人不能是同一个人');
}
// 获取审批流程(简化版:直接使用第一个审批人作为单人审批)
$flow = ApprovalFlow::where('business_type', 'business_trip')
->where('status', 1)