feat: 版本详情完整功能 + 数据串联 + 登录模块
- 版本详情:关联需求Tab(从需求池添加已采纳需求/移除释放) - 版本详情:调研/产品方案/UI设计Tab(计划CRUD、完成提交成果、耗时统计) - 版本详情:超期校验(结束日期超版本截止需填写原因) - 版本详情:概览统计卡片(加班时长/排名/原因占比) - 数据串联:产品→项目→版本→需求→加班全链路贯通 - 版本管理:规划中版本可删除,删除释放关联需求 - 数据清理:仅保留翻台宝/值班,需求池10条值班待评审需求 - 修复:列表页overflow裁剪菜单问题(4个页面统一修复) - 新增:登录模块、AuthGuard、VersionPlan store Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,7 @@ interface RequirementModalProps {
|
||||
initial?: Requirement | null;
|
||||
products: { id: string; name: string }[];
|
||||
projects: { id: string; name: string; productId: string }[];
|
||||
versions: { id: string; name: string; projectId: string }[];
|
||||
sourceTargets: SourceTarget[];
|
||||
types: DictItem[];
|
||||
platforms: DictItem[];
|
||||
@@ -36,6 +37,7 @@ export function RequirementModal({
|
||||
initial,
|
||||
products,
|
||||
projects,
|
||||
versions,
|
||||
sourceTargets,
|
||||
types,
|
||||
platforms,
|
||||
@@ -56,6 +58,7 @@ export function RequirementModal({
|
||||
const [effort, setEffort] = useState<Effort>('M');
|
||||
const [productOwner, setProductOwner] = useState('');
|
||||
const [parentId, setParentId] = useState('');
|
||||
const [versionId, setVersionId] = useState('');
|
||||
|
||||
const [platformDropOpen, setPlatformDropOpen] = useState(false);
|
||||
|
||||
@@ -64,6 +67,11 @@ export function RequirementModal({
|
||||
[projects, productId],
|
||||
);
|
||||
|
||||
const filteredVersions = useMemo(
|
||||
() => projectId ? versions.filter((v) => v.projectId === projectId) : [],
|
||||
[versions, projectId],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (initial) {
|
||||
setTitle(initial.title);
|
||||
@@ -72,6 +80,7 @@ export function RequirementModal({
|
||||
setSourceTarget(initial.sourceTarget || '');
|
||||
setProductId(initial.productId || '');
|
||||
setProjectId(initial.projectId || '');
|
||||
setVersionId(initial.versionId || '');
|
||||
setSelectedPlatforms(initial.platforms || []);
|
||||
setTypeId(initial.typeId || '');
|
||||
setPriority(initial.priority || 'P2');
|
||||
@@ -85,6 +94,7 @@ export function RequirementModal({
|
||||
setSourceTarget('');
|
||||
setProductId('');
|
||||
setProjectId('');
|
||||
setVersionId('');
|
||||
setSelectedPlatforms([]);
|
||||
setTypeId('');
|
||||
setPriority('P2');
|
||||
@@ -113,6 +123,7 @@ export function RequirementModal({
|
||||
sourceTarget: sourceTarget || undefined,
|
||||
productId: productId || undefined,
|
||||
projectId: projectId || undefined,
|
||||
versionId: versionId || undefined,
|
||||
platforms: selectedPlatforms,
|
||||
typeId: typeId || undefined,
|
||||
priority,
|
||||
@@ -226,15 +237,15 @@ export function RequirementModal({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 4. 所属产品 → 项目 */}
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
{/* 4. 所属产品 → 项目 → 版本 */}
|
||||
<div className="grid grid-cols-3 gap-3">
|
||||
<div>
|
||||
<label className="text-[12px] font-medium text-[var(--ink-soft)] mb-1.5 block">
|
||||
所属产品
|
||||
</label>
|
||||
<select
|
||||
value={productId}
|
||||
onChange={(e) => { setProductId(e.target.value); setProjectId(''); }}
|
||||
onChange={(e) => { setProductId(e.target.value); setProjectId(''); setVersionId(''); }}
|
||||
className="h-9 w-full rounded-lg border border-[var(--line)] bg-[var(--bg-card)] px-3 text-[13px] text-[var(--ink)] outline-none focus:border-[var(--accent)]"
|
||||
>
|
||||
<option value="">请选择产品</option>
|
||||
@@ -249,7 +260,7 @@ export function RequirementModal({
|
||||
</label>
|
||||
<select
|
||||
value={projectId}
|
||||
onChange={(e) => setProjectId(e.target.value)}
|
||||
onChange={(e) => { setProjectId(e.target.value); setVersionId(''); }}
|
||||
className="h-9 w-full rounded-lg border border-[var(--line)] bg-[var(--bg-card)] px-3 text-[13px] text-[var(--ink)] outline-none focus:border-[var(--accent)]"
|
||||
>
|
||||
<option value="">请选择项目</option>
|
||||
@@ -258,6 +269,21 @@ export function RequirementModal({
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-[12px] font-medium text-[var(--ink-soft)] mb-1.5 block">
|
||||
所属版本
|
||||
</label>
|
||||
<select
|
||||
value={versionId}
|
||||
onChange={(e) => setVersionId(e.target.value)}
|
||||
className="h-9 w-full rounded-lg border border-[var(--line)] bg-[var(--bg-card)] px-3 text-[13px] text-[var(--ink)] outline-none focus:border-[var(--accent)]"
|
||||
>
|
||||
<option value="">请选择版本</option>
|
||||
{filteredVersions.map((v) => (
|
||||
<option key={v.id} value={v.id}>{v.name}</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 5. 支持端 (multi-select) */}
|
||||
|
||||
Reference in New Issue
Block a user