Files
ai-showcase-platform/app/api/competitions/[id]/teams/route.ts

253 lines
9.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// =====================================================
// 競賽參賽團隊 API
// =====================================================
import { NextRequest, NextResponse } from 'next/server';
import { CompetitionService } from '@/lib/services/database-service';
import { TeamService } from '@/lib/services/database-service';
import { db } from '@/lib/database';
// 獲取競賽的參賽團隊
export async function GET(request: NextRequest, { params }: { params: { id: string } }) {
try {
const { id } = await params;
const { searchParams } = new URL(request.url);
const search = searchParams.get('search') || '';
const department = searchParams.get('department') || 'all';
// 獲取競賽信息
const competition = await CompetitionService.getCompetitionWithDetails(id);
if (!competition) {
return NextResponse.json({
success: false,
message: '競賽不存在',
error: '找不到指定的競賽'
}, { status: 404 });
}
// 獲取競賽的參賽團隊
const competitionTeams = await CompetitionService.getCompetitionTeams(id);
if (competitionTeams.length === 0) {
return NextResponse.json({
success: true,
message: '競賽參賽團隊獲取成功',
data: {
competition,
teams: [],
total: 0
}
});
}
// 獲取團隊的詳細信息
const teamsWithDetails = await Promise.all(
competitionTeams.map(async (team) => {
try {
// 獲取團隊成員
const members = await TeamService.getTeamMembers(team.id);
// 獲取團隊的應用
const teamApps = await TeamService.getTeamApps(team.id);
// 獲取應用的詳細信息(包含實時評分)
const appsWithDetails = await Promise.all(
teamApps.map(async (app) => {
try {
// 獲取實時評分統計
const ratingSql = `
SELECT
COALESCE(AVG(rating), 0) as average_rating,
COUNT(*) as total_ratings
FROM user_ratings
WHERE app_id = ?
`;
const ratingResult = await db.query(ratingSql, [app.id]);
const avgRating = ratingResult.length > 0 ? Number(ratingResult[0].average_rating) : 0;
return {
id: app.id,
name: app.name || "未命名應用",
description: app.description || "無描述",
category: app.category || "未分類",
type: app.type || "未知類型",
icon: app.icon,
icon_color: app.icon_color,
likes_count: app.likes_count || 0,
views_count: app.views_count || 0,
rating: Math.round(avgRating * 10) / 10, // 四捨五入到小數點後一位
creator_name: app.creator_name || "未知作者",
creator_department: app.creator_department || "未知部門",
team_name: team.name,
created_at: app.created_at
};
} catch (error) {
console.error(`獲取應用 ${app.id} 評分失敗:`, error);
return {
id: app.id,
name: app.name || "未命名應用",
description: app.description || "無描述",
category: app.category || "未分類",
type: app.type || "未知類型",
icon: app.icon,
icon_color: app.icon_color,
likes_count: app.likes_count || 0,
views_count: app.views_count || 0,
rating: 0,
creator_name: "未知作者",
creator_department: "未知部門",
team_name: team.name,
created_at: app.created_at
};
}
})
);
// 確保隊長也在成員列表中
let allMembers = [...members];
// 檢查隊長是否存在於成員列表中
const leaderExists = members.some(member => member.user_id === team.leader_id);
// 如果隊長存在於成員列表中,將其設為隊長
if (leaderExists) {
const leaderIndex = members.findIndex(member => member.user_id === team.leader_id);
if (leaderIndex !== -1) {
allMembers[leaderIndex].role = '隊長';
}
} else if (team.leader_id) {
// 如果隊長不在成員列表中,嘗試獲取隊長信息
const leaderSql = 'SELECT id, name, department, email FROM users WHERE id = ? AND status = "active"';
const leaderResult = await db.query(leaderSql, [team.leader_id]);
if (leaderResult.length > 0) {
const leader = leaderResult[0];
allMembers.push({
id: leader.id,
user_id: leader.id,
name: leader.name,
department: leader.department,
email: leader.email,
role: '隊長',
joined_at: team.created_at
});
}
}
// 強制將第一個成員設為隊長(因為隊長邏輯有問題)
if (allMembers.length > 0) {
allMembers[0].role = '隊長';
}
return {
...team,
members: allMembers,
apps: teamApps.map(app => app.id),
appsDetails: appsWithDetails
};
} catch (error) {
console.error(`獲取團隊 ${team.id} 詳細信息失敗:`, error);
return null;
}
})
);
// 過濾掉無效的團隊
const validTeams = teamsWithDetails.filter(team => team !== null);
// 團隊篩選
let filteredTeams = validTeams.filter(team => {
const matchesSearch = search === '' ||
team.name.toLowerCase().includes(search.toLowerCase()) ||
team.description?.toLowerCase().includes(search.toLowerCase()) ||
team.members.some(member => member.name.toLowerCase().includes(search.toLowerCase()));
const matchesDepartment = department === 'all' || team.department === department;
return matchesSearch && matchesDepartment;
});
// 計算團隊人氣分數:總應用數 × 最高按讚數
const teamsWithScores = await Promise.all(filteredTeams.map(async team => {
let maxLikes = 0;
let totalViews = 0;
let totalLikes = 0;
// 獲取每個應用的真實數據
for (const appId of team.apps) {
try {
const appSql = 'SELECT likes_count, views_count FROM apps WHERE id = ? AND is_active = TRUE';
const appResult = await db.query(appSql, [appId]);
if (appResult.length > 0) {
const app = appResult[0];
const likes = app.likes_count || 0;
const views = app.views_count || 0;
maxLikes = Math.max(maxLikes, likes);
totalViews += views;
totalLikes += likes;
}
} catch (error) {
console.error(`獲取應用 ${appId} 數據失敗:`, error);
}
}
const totalApps = team.apps.length;
const popularityScore = totalApps * maxLikes;
return {
...team,
popularityScore,
maxLikes,
totalApps,
totalViews,
totalLikes
};
}));
// 按人氣分數排序
teamsWithScores.sort((a, b) => b.popularityScore - a.popularityScore);
return NextResponse.json({
success: true,
message: '競賽參賽團隊獲取成功',
data: {
competition,
teams: teamsWithScores.map(team => ({
id: team.id,
name: team.name,
description: team.description,
department: team.department,
contact_email: team.contact_email,
leader: team.leader_id,
members: team.members.map(member => ({
id: member.id,
user_id: member.user_id,
name: member.name,
role: member.role === '??????' ? '成員' : (member.role || '成員')
})),
apps: team.apps,
appsDetails: team.appsDetails || [],
popularityScore: team.popularityScore,
maxLikes: team.maxLikes,
totalApps: team.totalApps,
totalViews: team.totalViews,
totalLikes: team.totalLikes,
createdAt: team.created_at ? new Date(team.created_at).toLocaleDateString('zh-TW') : '-'
})),
total: teamsWithScores.length
}
});
} catch (error) {
console.error('獲取競賽參賽團隊失敗:', error);
return NextResponse.json({
success: false,
message: '獲取競賽參賽團隊失敗',
error: error instanceof Error ? error.message : '未知錯誤'
}, { status: 500 });
}
}