feat(平台): 补齐服务端持久化和AI拆解契约
This commit is contained in:
@@ -33,6 +33,7 @@ import { testCaseIntervals } from '@/lib/test-case';
|
||||
import { bugIntervals } from '@/lib/bug';
|
||||
import { planIntervals } from '@/lib/version-plan';
|
||||
import { formatDateTime } from '@/lib/format';
|
||||
import { getProjectAdoptedRequirementCandidates } from '@/lib/requirement-selector';
|
||||
|
||||
const PRIORITY_STYLE: Record<string, string> = {
|
||||
P0: 'bg-red-500/10 text-red-600',
|
||||
@@ -145,9 +146,10 @@ export default function VersionDetailPage() {
|
||||
);
|
||||
}
|
||||
|
||||
// 权限校验:只有参与人员可以访问
|
||||
// 权限校验:只有参与人员可以访问(超管不受限)
|
||||
const currentUserName = user?.name || '';
|
||||
const isMember = (version.members ?? []).length === 0 || (version.members ?? []).some((m) => m.name === currentUserName);
|
||||
const isSuperAdmin = !!currentRole && currentRole.permissions.includes('*');
|
||||
const isMember = isSuperAdmin || (version.members ?? []).length === 0 || (version.members ?? []).some((m) => m.name === currentUserName);
|
||||
if (!isMember) {
|
||||
return (
|
||||
<div className="flex h-full flex-col items-center justify-center gap-3">
|
||||
@@ -512,7 +514,7 @@ export default function VersionDetailPage() {
|
||||
{g.items.map((p) => (
|
||||
<a key={p.id} href={p.resultUrl} target="_blank" rel="noopener noreferrer" className="flex items-center gap-1.5 text-[12px] text-[var(--accent)] hover:underline">
|
||||
{p.resultType === 'file' ? <FileText className="h-3 w-3" /> : <Link2 className="h-3 w-3" />}
|
||||
<span className="truncate">{p.resultFileName || p.title}</span>
|
||||
<span className="truncate">{p.resultTitle || p.resultFileName || p.title}</span>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
@@ -887,17 +889,18 @@ export default function VersionDetailPage() {
|
||||
) : (activeTab === 'research' || activeTab === 'product' || activeTab === 'ui') ? (
|
||||
(() => {
|
||||
const pt = activeTab as 'research' | 'product' | 'ui';
|
||||
const versionReqs = requirements.filter((r) => r.versionId === version.id);
|
||||
const linkedReqs = versionReqs.map((r) => ({ id: r.id, title: r.title, code: r.code, productOwner: r.productOwner }));
|
||||
const projectAdoptedReqs = getProjectAdoptedRequirementCandidates(requirements, version.projectId);
|
||||
return (
|
||||
<PlanTab
|
||||
plans={plans}
|
||||
versionId={version.id}
|
||||
version={version}
|
||||
versionDeadline={version.expectedReleaseDate ?? undefined}
|
||||
currentUserName={user?.name ?? ''}
|
||||
planType={pt}
|
||||
versionMembers={version.members ?? []}
|
||||
linkedRequirements={pt !== 'research' ? linkedReqs : undefined}
|
||||
linkedRequirements={projectAdoptedReqs}
|
||||
allRequirements={requirements}
|
||||
onCreate={(data) => {
|
||||
createPlan(data);
|
||||
if ((pt === 'product') && data.linkedRequirementIds?.length) {
|
||||
|
||||
Reference in New Issue
Block a user