Files
ftb-project-management/apps/web/lib/bug.ts
Script Generator 273182bb0f feat: Bug 图片上传 + 转交 + 操作日志 + 开发中含自测
1. 开发中统计包含 in_progress + testing(自测)

2. Bug 支持上传图片:
   - BugCreateModal 加宽为 max-w-2xl
   - 新增拖拽/点击上传图片区域,转 base64 存储
   - 上传后可预览缩略图、可删除
   - BugDetailDrawer 展示截图列表,点击可放大

3. Bug 支持转交:
   - BugDetailDrawer 操作栏新增"转交"按钮
   - 选人下拉 + 备注输入 → 确认转交
   - transferBug store 方法:更新 assigneeId + 追加日志

4. Bug 操作日志:
   - BugLog interface: create/status_change/transfer/resolve
   - createBug 时记录创建日志
   - changeStatus 时记录状态变更/修复日志
   - transferBug 时记录转交日志
   - BugDetailDrawer 底部展示操作时间线

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-15 13:37:01 +08:00

90 lines
2.3 KiB
TypeScript

import type { Priority } from './derive';
export type BugStatus = 'open' | 'fixing' | 'fixed' | 'verifying' | 'closed' | 'rejected';
export type BugSeverity = 'critical' | 'major' | 'minor' | 'trivial';
export interface BugLog {
id: string;
action: 'create' | 'status_change' | 'transfer' | 'resolve';
fromValue?: string;
toValue?: string;
operator: string;
remark?: string;
createdAt: string;
}
export interface Bug {
id: string;
bugNo: string;
versionId: string;
testCaseId: string;
requirementId?: string;
title: string;
description: string;
severity: BugSeverity;
priority: Priority;
reportedBy: string;
assigneeId: string;
status: BugStatus;
images?: string[];
logs?: BugLog[];
resolvedAt?: string;
closedAt?: string;
resolution?: string;
createdAt: string;
updatedAt: string;
}
export const BUG_STATUS_LABEL: Record<BugStatus, string> = {
open: '待修复',
fixing: '修复中',
fixed: '已修复',
verifying: '验证中',
closed: '已关闭',
rejected: '已拒绝',
};
export const BUG_STATUS_COLOR: Record<BugStatus, string> = {
open: 'bg-red-50 text-red-600',
fixing: 'bg-blue-50 text-blue-600',
fixed: 'bg-indigo-50 text-indigo-600',
verifying: 'bg-purple-50 text-purple-600',
closed: 'bg-emerald-50 text-emerald-600',
rejected: 'bg-zinc-100 text-zinc-500',
};
export const BUG_SEVERITY_LABEL: Record<BugSeverity, string> = {
critical: '致命',
major: '严重',
minor: '一般',
trivial: '轻微',
};
export const BUG_SEVERITY_COLOR: Record<BugSeverity, string> = {
critical: 'bg-red-100 text-red-700',
major: 'bg-orange-50 text-orange-700',
minor: 'bg-yellow-50 text-yellow-700',
trivial: 'bg-zinc-100 text-zinc-600',
};
export const BUG_ALLOWED_TRANSITIONS: Record<BugStatus, BugStatus[]> = {
open: ['fixing', 'rejected'],
fixing: ['fixed'],
fixed: ['verifying'],
verifying: ['closed', 'open'],
closed: [],
rejected: [],
};
export function canBugTransition(from: BugStatus, to: BugStatus): boolean {
return BUG_ALLOWED_TRANSITIONS[from].includes(to);
}
export function generateBugNo(existingBugs: Bug[]): string {
const maxNum = existingBugs.reduce((max, b) => {
const num = parseInt(b.bugNo.replace('BUG-', ''), 10);
return isNaN(num) ? max : Math.max(max, num);
}, 0);
return `BUG-${String(maxNum + 1).padStart(3, '0')}`;
}