feat: 提测通知 + 测试全通过自动完成开发任务

1. TestCaseTab 显示提测状态横幅:
   - 绿色:开发已全部提测,可以开始测试
   - 橙色:开发进行中,显示提测进度 (x/y)

2. TestCase 全部通过 + Bug 全关闭时,自动将版本下所有
   submitted 状态的 DevTask 流转为 done(无需手动操作)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Script Generator
2026-06-12 14:20:44 +08:00
parent 93f6c33109
commit e4f3817719
2 changed files with 41 additions and 2 deletions

View File

@@ -1,9 +1,10 @@
'use client';
import { useState, useMemo, useEffect } from 'react';
import { Plus, ClipboardCheck, Filter } from 'lucide-react';
import { Plus, ClipboardCheck, Filter, CheckCircle2 } from 'lucide-react';
import { useTestCaseStore } from '@/stores/useTestCaseStore';
import { useBugStore } from '@/stores/useBugStore';
import { useDevTaskStore } from '@/stores/useDevTaskStore';
import { useRequirementStore } from '@/stores/useRequirementStore';
import { useAuthStore } from '@/stores/useAuthStore';
import { TestCaseRow } from './TestCaseRow';
@@ -22,6 +23,7 @@ interface Props {
export function TestCaseTab({ versionId, requirementIds }: Props) {
const { testCases, fetchTestCases } = useTestCaseStore();
const { bugs, fetchBugs } = useBugStore();
const { tasks: devTasks } = useDevTaskStore();
const { requirements } = useRequirementStore();
const user = useAuthStore((s) => s.user);
@@ -30,9 +32,13 @@ export function TestCaseTab({ versionId, requirementIds }: Props) {
const versionCases = useMemo(
() => testCases.filter((c) => c.versionId === versionId),
[testCases, requirementIds],
[testCases, versionId],
);
// 提测状态判断
const versionDevTasks = useMemo(() => devTasks.filter((t) => requirementIds.includes(t.requirementId)), [devTasks, requirementIds]);
const allSubmitted = versionDevTasks.length > 0 && versionDevTasks.every((t) => t.status === 'submitted' || t.status === 'done');
const stats = calcTestProgress(versionCases);
// 筛选
@@ -73,6 +79,19 @@ export function TestCaseTab({ versionId, requirementIds }: Props) {
return (
<div className="space-y-3">
{/* 提测通知 */}
{allSubmitted && (
<div className="flex items-center gap-2 px-4 py-2.5 rounded-lg bg-emerald-50 border border-emerald-200">
<CheckCircle2 className="h-4 w-4 text-emerald-600" />
<span className="text-[12px] font-medium text-emerald-700"></span>
{versionDevTasks.length > 0 && <span className="text-[11px] text-emerald-600 ml-auto">{versionDevTasks.length} </span>}
</div>
)}
{versionDevTasks.length > 0 && !allSubmitted && (
<div className="flex items-center gap-2 px-4 py-2.5 rounded-lg bg-orange-50 border border-orange-200">
<span className="text-[12px] text-orange-700">{versionDevTasks.filter((t) => t.status === 'submitted' || t.status === 'done').length}/{versionDevTasks.length}</span>
</div>
)}
{/* 统计栏 */}
<div className="flex items-center gap-4 px-4 py-3 rounded-lg bg-[var(--bg-subtle)] border border-[var(--line)]">
<div className="flex items-center gap-2">