mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-05 01:50:27 +08:00
fix: Issue Manager completed过滤器现在可以显示归档议题
- 添加 loadIssueHistory() 函数从 /api/issues/history 加载归档议题 - 修改 filterIssuesByStatus() 在选择 completed 过滤器时加载历史数据 - 修改 renderIssueView() 合并当前已完成议题和归档议题 - 修改 renderIssueCard() 显示 "Archived" 标签区分归档议题 - 修改 openIssueDetail() 支持从缓存加载归档议题详情 - 添加 .issue-card.archived 和 .issue-archived-badge CSS样式 Fixes: https://github.com/catlog22/Claude-Code-Workflow/issues/76 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -128,6 +128,29 @@
|
||||
box-shadow: 0 4px 12px hsl(var(--foreground) / 0.08);
|
||||
}
|
||||
|
||||
/* Archived Issue Card */
|
||||
.issue-card.archived {
|
||||
opacity: 0.85;
|
||||
background: hsl(var(--muted) / 0.3);
|
||||
}
|
||||
|
||||
.issue-card.archived:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.issue-archived-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 0.125rem 0.375rem;
|
||||
background: hsl(var(--muted));
|
||||
color: hsl(var(--muted-foreground));
|
||||
font-size: 0.625rem;
|
||||
font-weight: 500;
|
||||
border-radius: 0.25rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.025em;
|
||||
}
|
||||
|
||||
.issue-card-header {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
// ========== Issue State ==========
|
||||
var issueData = {
|
||||
issues: [],
|
||||
historyIssues: [], // Archived/completed issues from history
|
||||
queue: { tasks: [], solutions: [], conflicts: [], execution_groups: [], grouped_items: {} },
|
||||
selectedIssue: null,
|
||||
selectedSolution: null,
|
||||
@@ -58,6 +59,18 @@ async function loadIssueData() {
|
||||
}
|
||||
}
|
||||
|
||||
async function loadIssueHistory() {
|
||||
try {
|
||||
const response = await fetch('/api/issues/history?path=' + encodeURIComponent(projectPath));
|
||||
if (!response.ok) throw new Error('Failed to load issue history');
|
||||
const data = await response.json();
|
||||
issueData.historyIssues = data.issues || [];
|
||||
} catch (err) {
|
||||
console.error('Failed to load issue history:', err);
|
||||
issueData.historyIssues = [];
|
||||
}
|
||||
}
|
||||
|
||||
async function loadQueueData() {
|
||||
try {
|
||||
const response = await fetch('/api/queue?path=' + encodeURIComponent(projectPath));
|
||||
@@ -93,10 +106,21 @@ function renderIssueView() {
|
||||
if (!container) return;
|
||||
|
||||
const issues = issueData.issues || [];
|
||||
const historyIssues = issueData.historyIssues || [];
|
||||
|
||||
// Apply both status and search filters
|
||||
let filteredIssues = issueData.statusFilter === 'all'
|
||||
? issues
|
||||
: issues.filter(i => i.status === issueData.statusFilter);
|
||||
let filteredIssues;
|
||||
if (issueData.statusFilter === 'all') {
|
||||
filteredIssues = issues;
|
||||
} else if (issueData.statusFilter === 'completed') {
|
||||
// For 'completed' filter, include both current completed issues and archived history issues
|
||||
const currentCompleted = issues.filter(i => i.status === 'completed');
|
||||
// Mark history issues as archived for visual distinction
|
||||
const archivedIssues = historyIssues.map(i => ({ ...i, _isArchived: true }));
|
||||
filteredIssues = [...currentCompleted, ...archivedIssues];
|
||||
} else {
|
||||
filteredIssues = issues.filter(i => i.status === issueData.statusFilter);
|
||||
}
|
||||
|
||||
if (issueData.searchQuery) {
|
||||
const query = issueData.searchQuery.toLowerCase();
|
||||
@@ -309,12 +333,15 @@ function renderIssueCard(issue) {
|
||||
failed: 'failed'
|
||||
};
|
||||
|
||||
const isArchived = issue._isArchived;
|
||||
|
||||
return `
|
||||
<div class="issue-card" onclick="openIssueDetail('${issue.id}')">
|
||||
<div class="issue-card ${isArchived ? 'archived' : ''}" onclick="openIssueDetail('${issue.id}'${isArchived ? ', true' : ''})">
|
||||
<div class="flex items-start justify-between mb-3">
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="issue-id font-mono text-sm">${issue.id}</span>
|
||||
<span class="issue-status ${statusColors[issue.status] || ''}">${issue.status || 'unknown'}</span>
|
||||
${isArchived ? '<span class="issue-archived-badge">' + (t('issues.archived') || 'Archived') + '</span>' : ''}
|
||||
</div>
|
||||
<span class="issue-priority" title="${t('issues.priority') || 'Priority'}: ${issue.priority || 3}">
|
||||
${renderPriorityStars(issue.priority || 3)}
|
||||
@@ -360,8 +387,12 @@ function renderPriorityStars(priority) {
|
||||
return stars;
|
||||
}
|
||||
|
||||
function filterIssuesByStatus(status) {
|
||||
async function filterIssuesByStatus(status) {
|
||||
issueData.statusFilter = status;
|
||||
// Load history data when filtering by 'completed' status
|
||||
if (status === 'completed' && issueData.historyIssues.length === 0) {
|
||||
await loadIssueHistory();
|
||||
}
|
||||
renderIssueView();
|
||||
}
|
||||
|
||||
@@ -725,7 +756,7 @@ async function saveQueueOrder(groupId, newOrder) {
|
||||
}
|
||||
|
||||
// ========== Detail Panel ==========
|
||||
async function openIssueDetail(issueId) {
|
||||
async function openIssueDetail(issueId, isArchived = false) {
|
||||
const panel = document.getElementById('issueDetailPanel');
|
||||
if (!panel) return;
|
||||
|
||||
@@ -733,7 +764,23 @@ async function openIssueDetail(issueId) {
|
||||
panel.classList.remove('hidden');
|
||||
lucide.createIcons();
|
||||
|
||||
const detail = await loadIssueDetail(issueId);
|
||||
let detail;
|
||||
if (isArchived) {
|
||||
// For archived issues, get detail from historyIssues (already loaded)
|
||||
const historyIssue = issueData.historyIssues.find(i => i.id === issueId);
|
||||
if (historyIssue) {
|
||||
// Mark as archived and provide minimal detail structure
|
||||
detail = {
|
||||
...historyIssue,
|
||||
_isArchived: true,
|
||||
solutions: historyIssue.solutions || [],
|
||||
tasks: historyIssue.tasks || []
|
||||
};
|
||||
}
|
||||
} else {
|
||||
detail = await loadIssueDetail(issueId);
|
||||
}
|
||||
|
||||
if (!detail) {
|
||||
panel.innerHTML = '<div class="p-8 text-center text-destructive">Failed to load issue</div>';
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user