feat: 需求池重构 + 联动引擎 + 开发状态推导
架构:新建 lib/linkage-engine.ts 联动引擎 - deriveReqDevStatus(): 从 devTasks 推导需求开发状态 - canEditRequirement(): 开发中的需求不可编辑 - checkVersionChangeRisk(): 版本变更风险检查 - 所有跨模块推导逻辑集中在此文件 功能改动: 1. 导航改名"需求"→"需求池" 2. 新建需求:所属产品/项目必填,移除产品负责人字段 3. 需求表格新增"开发状态"列: 未排期/待开发/开发中/已完成(从 devTasks 实时推导) 4. 开发中的需求:编辑按钮禁用 5. 需求设 versionId → 版本详情关联需求天然兼容 (版本详情通过 filter(r.versionId === versionId) 读取) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -11,7 +11,7 @@ const NAV_GROUPS = [
|
||||
{ label: '产品', path: '/products', icon: Package },
|
||||
{ label: '项目', path: '/projects', icon: FolderKanban },
|
||||
{ label: '版本', path: '/versions', icon: Tag },
|
||||
{ label: '需求', path: '/requirements', icon: Lightbulb },
|
||||
{ label: '需求池', path: '/requirements', icon: Lightbulb },
|
||||
{ label: '加班记录', path: '/overtime', icon: Clock },
|
||||
],
|
||||
},
|
||||
|
||||
@@ -115,19 +115,18 @@ export function RequirementModal({
|
||||
};
|
||||
|
||||
const handleSubmit = () => {
|
||||
if (!title.trim()) return;
|
||||
if (!title.trim() || !productId || !projectId) return;
|
||||
onSubmit({
|
||||
title: title.trim(),
|
||||
description: description.trim(),
|
||||
sourceType,
|
||||
sourceTarget: sourceTarget || undefined,
|
||||
productId: productId || undefined,
|
||||
projectId: projectId || undefined,
|
||||
productId,
|
||||
projectId,
|
||||
versionId: versionId || undefined,
|
||||
platforms: selectedPlatforms,
|
||||
typeId: typeId || undefined,
|
||||
priority,
|
||||
productOwner: productOwner.trim() || undefined,
|
||||
parentId: parentId || undefined,
|
||||
});
|
||||
};
|
||||
@@ -241,7 +240,7 @@ export function RequirementModal({
|
||||
<div className="grid grid-cols-3 gap-3">
|
||||
<div>
|
||||
<label className="text-[12px] font-medium text-[var(--ink-soft)] mb-1.5 block">
|
||||
所属产品
|
||||
所属产品 <span className="text-red-500">*</span>
|
||||
</label>
|
||||
<select
|
||||
value={productId}
|
||||
@@ -256,7 +255,7 @@ export function RequirementModal({
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-[12px] font-medium text-[var(--ink-soft)] mb-1.5 block">
|
||||
所属项目
|
||||
所属项目 <span className="text-red-500">*</span>
|
||||
</label>
|
||||
<select
|
||||
value={projectId}
|
||||
@@ -379,20 +378,6 @@ export function RequirementModal({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 9. 产品负责人 */}
|
||||
<div>
|
||||
<label className="text-[12px] font-medium text-[var(--ink-soft)] mb-1.5 block">
|
||||
产品负责人
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={productOwner}
|
||||
onChange={(e) => setProductOwner(e.target.value)}
|
||||
placeholder="请输入负责人姓名"
|
||||
className="h-9 w-full rounded-lg border border-[var(--line)] bg-[var(--bg-card)] px-3 text-[13px] text-[var(--ink)] placeholder:text-[var(--ink-muted)] outline-none focus:border-[var(--accent)]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 10. 关联父需求 */}
|
||||
<div>
|
||||
<label className="text-[12px] font-medium text-[var(--ink-soft)] mb-1.5 block">
|
||||
|
||||
Reference in New Issue
Block a user