feat(v2.4): 切换需求池领域主写

This commit is contained in:
2026-07-08 12:18:15 +08:00
parent 142800f75b
commit 5f5a211c99
11 changed files with 602 additions and 56 deletions

View File

@@ -432,7 +432,6 @@ function RequirementsPageContent() {
}, [scopedRequirements, search, statusFilter, priorityFilter, typeFilter, versionFilter, dateSort, requirementDevStatusMap]);
const appDataRequirementById = useMemo(() => new Map(requirements.map((item) => [item.id, item])), [requirements]);
const appDataRequirementIds = useMemo(() => new Set(appDataRequirementById.keys()), [appDataRequirementById]);
const usingV22Requirements = Boolean(v22RequirementQuery) && !v22RequirementsFailed;
const appTotalPages = Math.max(1, Math.ceil(filtered.length / pageSize));
const appPage = Math.min(page, appTotalPages);
@@ -450,7 +449,7 @@ function RequirementsPageContent() {
: filtered.length;
const displayPage = usingV22Requirements ? page : appPage;
const displayedScopeCount = usingV22Requirements ? total : scopedRequirements.length;
const canMutateRequirement = (req: Requirement) => requirementsLoaded && appDataRequirementIds.has(req.id);
const canMutateRequirement = (req: Requirement) => Boolean(req.productId);
const handlePageChange = (nextPage: number) => {
if (usingV22Requirements && nextPage > page && !v22CursorByPage[nextPage]) return;
setPage(nextPage);
@@ -789,7 +788,7 @@ function RequirementsPageContent() {
{canMutateRequirement(req) && req.status === 'pending_review' && (
<>
<button
onClick={() => updateRequirement(req.id, { status: 'adopted' })}
onClick={() => updateRequirement(req.id, { productId: req.productId, status: 'adopted' })}
className={`${REQUIREMENT_ACTION_BUTTON_BASE_CLASS} ${REQUIREMENT_ACTION_BUTTON_TONE_CLASS.success}`}
title="采纳"
aria-label="采纳需求"
@@ -809,7 +808,7 @@ function RequirementsPageContent() {
{/* 已采纳/已规划:关闭 */}
{canMutateRequirement(req) && (req.status === 'adopted' || req.status === 'planned') && canCloseRequirement(req.id, devTasksByRequirement.get(req.id) ?? []) && (
<button
onClick={() => updateRequirement(req.id, { status: 'closed' })}
onClick={() => updateRequirement(req.id, { productId: req.productId, status: 'closed' })}
className={`${REQUIREMENT_ACTION_BUTTON_BASE_CLASS} ${REQUIREMENT_ACTION_BUTTON_TONE_CLASS.warning}`}
title="关闭"
aria-label="关闭需求"
@@ -820,7 +819,7 @@ function RequirementsPageContent() {
{/* 删除:待评审/已拒绝/已关闭(已采纳后不能直接删,需走拒绝) */}
{canMutateRequirement(req) && (['pending_review', 'rejected', 'closed'] as const).includes(req.status as any) && (
<button
onClick={() => deleteRequirement(req.id)}
onClick={() => deleteRequirement(req.id, req.productId)}
className={`${REQUIREMENT_ACTION_BUTTON_BASE_CLASS} ${REQUIREMENT_ACTION_BUTTON_TONE_CLASS.danger}`}
title="删除"
aria-label="删除需求"
@@ -854,10 +853,10 @@ function RequirementsPageContent() {
resolveVersionName={resolveVersionName}
onClose={() => setViewingReq(null)}
onEdit={canMutateRequirement(viewingReq) && canEditRequirement(viewingReq.id, devTasksByRequirement.get(viewingReq.id) ?? []) ? () => handleEdit(viewingReq) : undefined}
onAdopt={canMutateRequirement(viewingReq) ? () => { updateRequirement(viewingReq.id, { status: 'adopted' }); setViewingReq(null); } : undefined}
onAdopt={canMutateRequirement(viewingReq) ? () => { updateRequirement(viewingReq.id, { productId: viewingReq.productId, status: 'adopted' }); setViewingReq(null); } : undefined}
onReject={canMutateRequirement(viewingReq) ? () => { setRejectingReq(viewingReq); setRejectReason(''); setViewingReq(null); } : undefined}
onCloseReq={canMutateRequirement(viewingReq) && canCloseRequirement(viewingReq.id, devTasksByRequirement.get(viewingReq.id) ?? []) ? () => { updateRequirement(viewingReq.id, { status: 'closed' }); setViewingReq(null); } : undefined}
onDelete={canMutateRequirement(viewingReq) ? () => { deleteRequirement(viewingReq.id); setViewingReq(null); } : undefined}
onCloseReq={canMutateRequirement(viewingReq) && canCloseRequirement(viewingReq.id, devTasksByRequirement.get(viewingReq.id) ?? []) ? () => { updateRequirement(viewingReq.id, { productId: viewingReq.productId, status: 'closed' }); setViewingReq(null); } : undefined}
onDelete={canMutateRequirement(viewingReq) ? () => { deleteRequirement(viewingReq.id, viewingReq.productId); setViewingReq(null); } : undefined}
/>
)}
@@ -882,7 +881,7 @@ function RequirementsPageContent() {
data.versionId,
data.versionId !== editingReq.versionId ? currentUserName : editingReq.addedToVersionBy,
);
updateRequirement(editingReq.id, { ...data, ...versionPatch });
updateRequirement(editingReq.id, { ...data, productId: editingReq.productId, ...versionPatch });
} else {
createRequirement(data);
}
@@ -947,7 +946,7 @@ function RequirementsPageContent() {
<button
onClick={() => {
if (!rejectReason.trim()) return;
updateRequirement(rejectingReq.id, { status: 'rejected', description: rejectingReq.description + `\n\n【拒绝原因】${rejectReason.trim()}` });
updateRequirement(rejectingReq.id, { productId: rejectingReq.productId, status: 'rejected', description: rejectingReq.description + `\n\n【拒绝原因】${rejectReason.trim()}` });
setRejectingReq(null);
}}
disabled={!rejectReason.trim()}