+
+
{record.participantType === "individual" ? (
-
+
) : (
-
+
)}
-
{record.participantName}
+
+
+ {record.participantType === "team" && record.teamName
+ ? `${record.teamName} - ${record.participantName}`
+ : record.participantName
+ }
+
+
-
+
{record.participantType === "individual" ? "個人" : "團隊"}
diff --git a/components/admin/team-management.tsx b/components/admin/team-management.tsx
index 8cefac8..d42231f 100644
--- a/components/admin/team-management.tsx
+++ b/components/admin/team-management.tsx
@@ -79,11 +79,9 @@ export function TeamManagement() {
if (data.success) {
setApiTeams(data.data)
} else {
- console.error('獲取團隊數據失敗:', data.message)
setError('獲取團隊數據失敗')
}
} catch (error) {
- console.error('獲取團隊數據失敗:', error)
setError('獲取團隊數據失敗')
} finally {
setIsLoadingTeams(false)
@@ -105,11 +103,9 @@ export function TeamManagement() {
if (data.success) {
setAvailableUsers(data.data)
} else {
- console.error('獲取用戶列表失敗:', data.message)
setError('獲取用戶列表失敗')
}
} catch (error) {
- console.error('獲取用戶列表失敗:', error)
setError('獲取用戶列表失敗')
} finally {
setIsLoadingUsers(false)
diff --git a/components/app-detail-dialog.tsx b/components/app-detail-dialog.tsx
index aae243e..0bb3bf9 100644
--- a/components/app-detail-dialog.tsx
+++ b/components/app-detail-dialog.tsx
@@ -198,11 +198,8 @@ export function AppDetailDialog({ open, onOpenChange, app }: AppDetailDialogProp
if (department) params.append('department', department)
const url = `/api/apps/${app.id}/stats${params.toString() ? `?${params.toString()}` : ''}`
- console.log('🔍 調用統計 API:', url)
- console.log('🔍 應用 ID:', app.id)
const response = await fetch(url)
- console.log('🔍 API 響應狀態:', response.status, response.statusText)
if (!response.ok) {
console.error('❌ API 響應錯誤:', response.status, response.statusText)
@@ -210,10 +207,8 @@ export function AppDetailDialog({ open, onOpenChange, app }: AppDetailDialogProp
}
const data = await response.json()
- console.log('🔍 API 響應數據:', data)
if (data.success) {
- console.log('📊 應用統計數據加載成功:', data.data)
setAppStats(data.data)
setCurrentRating(data.data.basic.rating)
setReviewCount(data.data.basic.reviewCount)
@@ -272,14 +267,12 @@ export function AppDetailDialog({ open, onOpenChange, app }: AppDetailDialogProp
}, [startDate, endDate, open, app.id, handleDateRangeChange])
const handleTryApp = async () => {
- console.log('handleTryApp 被調用', { user: user?.id, appId: app.id })
if (user) {
addToRecentApps(app.id.toString())
// 記錄用戶活動
try {
- console.log('開始記錄用戶活動...')
const response = await fetch('/api/user/activity', {
method: 'POST',
headers: {
@@ -298,7 +291,6 @@ export function AppDetailDialog({ open, onOpenChange, app }: AppDetailDialogProp
})
if (response.ok) {
- console.log('活動記錄成功')
} else {
console.error('活動記錄失敗:', response.status, response.statusText)
}
@@ -306,7 +298,6 @@ export function AppDetailDialog({ open, onOpenChange, app }: AppDetailDialogProp
console.error('記錄活動失敗:', error)
}
} else {
- console.log('用戶未登入,跳過活動記錄')
}
// Increment view count when trying the app
diff --git a/components/competition/competition-detail-dialog.tsx b/components/competition/competition-detail-dialog.tsx
index 36e1414..d38cb23 100644
--- a/components/competition/competition-detail-dialog.tsx
+++ b/components/competition/competition-detail-dialog.tsx
@@ -59,7 +59,6 @@ export function CompetitionDetailDialog({
const handleTryApp = (appId: string) => {
incrementViewCount(appId)
addToRecentApps(appId)
- console.log(`Opening app ${appId}`)
}
const getTypeColor = (type: string) => {
diff --git a/components/competition/popularity-rankings.tsx b/components/competition/popularity-rankings.tsx
index 5154bcb..5f5116b 100644
--- a/components/competition/popularity-rankings.tsx
+++ b/components/competition/popularity-rankings.tsx
@@ -94,17 +94,14 @@ export function PopularityRankings() {
if (appsData.success) {
// 合併個人應用和團隊應用
const allApps = appsData.data.apps || []
- console.log('📱 載入的應用數據:', allApps)
setCompetitionApps(allApps)
}
if (teamsData.success) {
const teams = teamsData.data.teams || []
- console.log('👥 載入的團隊數據:', teams)
setCompetitionTeams(teams)
}
if (judgesData.success) {
const judges = judgesData.data.judges || []
- console.log('👨⚖️ 載入的評審數據:', judges)
setCompetitionJudges(judges)
}
} catch (error) {
diff --git a/components/favorites-page.tsx b/components/favorites-page.tsx
index 19cc42f..404178e 100644
--- a/components/favorites-page.tsx
+++ b/components/favorites-page.tsx
@@ -46,7 +46,6 @@ export function FavoritesPage() {
}, [user])
const handleUseApp = async (app: any) => {
- console.log('handleUseApp 被調用', { user: user?.id, appId: app.id, appName: app.name })
try {
// Increment view count when using the app
@@ -65,7 +64,6 @@ export function FavoritesPage() {
if (response.ok) {
// 記錄用戶活動
try {
- console.log('開始記錄用戶活動...')
const activityResponse = await fetch('/api/user/activity', {
method: 'POST',
headers: {
@@ -84,7 +82,6 @@ export function FavoritesPage() {
})
if (activityResponse.ok) {
- console.log('活動記錄成功')
} else {
console.error('活動記錄失敗:', activityResponse.status, activityResponse.statusText)
}
@@ -98,7 +95,6 @@ export function FavoritesPage() {
console.error('增加查看次數失敗:', response.status, response.statusText)
}
} else {
- console.log('用戶未登入,跳過活動記錄')
}
} catch (error) {
console.error('增加查看次數失敗:', error)
@@ -109,7 +105,6 @@ export function FavoritesPage() {
const url = app.appUrl.startsWith('http') ? app.appUrl : `https://${app.appUrl}`
window.open(url, "_blank", "noopener,noreferrer")
} else {
- console.log(`Opening app: ${app.name}`)
}
}
diff --git a/components/reviews/review-system.tsx b/components/reviews/review-system.tsx
index 4bdf2a9..de8469d 100644
--- a/components/reviews/review-system.tsx
+++ b/components/reviews/review-system.tsx
@@ -353,7 +353,6 @@ export function ReviewSystem({ appId, appName, currentRating, onRatingUpdate }:
{[5, 4, 3, 2, 1].map((rating) => {
const count = reviews.filter((r) => r.rating === rating).length
const percentage = (count / reviews.length) * 100
- console.log(`評分 ${rating}: count=${count}, percentage=${percentage}%`) // 調試信息
return (
diff --git a/contexts/competition-context.tsx b/contexts/competition-context.tsx
index 0b79f4c..355700c 100644
--- a/contexts/competition-context.tsx
+++ b/contexts/competition-context.tsx
@@ -126,12 +126,10 @@ export function CompetitionProvider({ children }: { children: ReactNode }) {
useEffect(() => {
const loadCompetitions = async () => {
try {
- console.log('🔄 開始載入競賽數據...')
// 載入所有競賽
const competitionsResponse = await fetch('/api/competitions')
const competitionsData = await competitionsResponse.json()
- console.log('📋 競賽API回應:', competitionsData)
if (competitionsData.success) {
if (competitionsData.data && competitionsData.data.length > 0) {
@@ -141,22 +139,18 @@ export function CompetitionProvider({ children }: { children: ReactNode }) {
judges: comp.judges || []
}))
setCompetitions(competitionsWithJudges)
- console.log('✅ 競賽數據載入成功:', competitionsWithJudges.length, '個競賽')
} else {
// 沒有競賽資料是正常情況,不報錯
setCompetitions([])
- console.log('ℹ️ 暫無競賽數據')
}
} else {
// 沒有競賽數據是正常情況,不報錯
setCompetitions([])
- console.log('ℹ️ 暫無競賽數據')
}
// 載入當前競賽
const currentResponse = await fetch('/api/competitions/current')
const currentData = await currentResponse.json()
- console.log('🏆 當前競賽API回應:', currentData)
if (currentData.success) {
if (currentData.data) {
@@ -166,36 +160,28 @@ export function CompetitionProvider({ children }: { children: ReactNode }) {
judges: currentData.data.judges || []
}
setCurrentCompetition(currentCompetitionWithJudges)
- console.log('✅ 當前競賽載入成功:', currentCompetitionWithJudges.name)
} else {
// 沒有當前競賽是正常情況,不報錯
setCurrentCompetition(null)
- console.log('ℹ️ 暫無當前競賽')
}
} else {
// 沒有當前競賽是正常情況,不報錯
setCurrentCompetition(null)
- console.log('ℹ️ 暫無當前競賽')
}
// 載入評審數據
- console.log('👨⚖️ 開始載入評審數據...')
const judgesResponse = await fetch('/api/admin/judges')
const judgesData = await judgesResponse.json()
- console.log('評審API回應:', judgesData)
if (judgesData.success) {
if (judgesData.data && judgesData.data.length > 0) {
setJudges(judgesData.data)
- console.log('✅ 評審數據載入成功:', judgesData.data.length, '個評審')
} else {
setJudges([])
- console.log('ℹ️ 暫無評審數據')
}
} else {
// 沒有評審數據是正常情況,不報錯
setJudges([])
- console.log('ℹ️ 暫無評審數據')
}
} catch (error) {
console.error('❌ 載入競賽數據失敗:', error)
@@ -283,12 +269,8 @@ export function CompetitionProvider({ children }: { children: ReactNode }) {
}
const deleteJudge = (id: string) => {
- console.log('🗑️ Context deleteJudge 被調用,ID:', id)
- console.log('🗑️ 刪除前的 judges 狀態:', judges.map(j => ({ id: j.id, name: j.name, is_active: j.is_active })))
-
setJudges((prev) => {
const filtered = prev.filter((judge) => judge.id !== id)
- console.log('🗑️ 刪除後的 judges 狀態:', filtered.map(j => ({ id: j.id, name: j.name, is_active: j.is_active })))
return filtered
})
diff --git a/lib/services/database-service.ts b/lib/services/database-service.ts
index f0d6246..fe24385 100644
--- a/lib/services/database-service.ts
+++ b/lib/services/database-service.ts
@@ -613,14 +613,41 @@ export class UserService extends DatabaseServiceBase {
`;
const reviewStats = await this.queryOne(reviewStatsSql);
- // 競賽統計
- const competitionStatsSql = `
- SELECT
- COUNT(*) as total_competitions,
- COUNT(CASE WHEN status = 'active' OR status = 'ongoing' THEN 1 END) as active_competitions
- FROM competitions
- `;
- const competitionStats = await this.queryOne(competitionStatsSql);
+ // 競賽統計 - 使用動態計算的狀態
+ const competitions = await CompetitionService.getAllCompetitions();
+
+ // 動態計算每個競賽的狀態
+ const now = new Date();
+ const competitionsWithCalculatedStatus = competitions.map(competition => {
+ const startDate = new Date(competition.start_date);
+ const endDate = new Date(competition.end_date);
+
+ let calculatedStatus = competition.status;
+
+ // 確保日期比較的準確性,使用 UTC 時間避免時區問題
+ const nowUTC = new Date(now.getTime() + now.getTimezoneOffset() * 60000);
+ const startDateUTC = new Date(startDate.getTime() + startDate.getTimezoneOffset() * 60000);
+ const endDateUTC = new Date(endDate.getTime() + endDate.getTimezoneOffset() * 60000);
+
+ // 根據實際日期計算狀態
+ if (nowUTC < startDateUTC) {
+ calculatedStatus = 'upcoming'; // 即將開始
+ } else if (nowUTC >= startDateUTC && nowUTC <= endDateUTC) {
+ calculatedStatus = 'active'; // 進行中
+ } else if (nowUTC > endDateUTC) {
+ calculatedStatus = 'completed'; // 已完成
+ }
+
+ return {
+ ...competition,
+ status: calculatedStatus
+ };
+ });
+
+ const competitionStats = {
+ total_competitions: competitionsWithCalculatedStatus.length,
+ active_competitions: competitionsWithCalculatedStatus.filter(c => c.status === 'active').length
+ };
// 計算增長率(與上個月比較)
const lastMonthUsersSql = `
@@ -903,7 +930,6 @@ export class JudgeService extends DatabaseServiceBase {
const fields = Object.keys(updates).filter(key => key !== 'id' && key !== 'created_at');
if (fields.length === 0) {
- console.log('沒有字段需要更新');
return true; // 沒有需要更新的字段,視為成功
}
@@ -916,11 +942,7 @@ export class JudgeService extends DatabaseServiceBase {
});
const sql = `UPDATE judges SET ${setClause}, updated_at = CURRENT_TIMESTAMP WHERE id = ?`;
- console.log('執行 SQL:', sql);
- console.log('參數:', [...values, id]);
-
const result = await DatabaseServiceBase.safeUpdate(sql, [...values, id]);
- console.log('更新結果:', result);
return result.affectedRows > 0;
}
@@ -938,38 +960,59 @@ export class JudgeService extends DatabaseServiceBase {
// 獲取評審的評分任務
static async getJudgeScoringTasks(judgeId: string, competitionId?: string): Promise
{
- let sql = `
- SELECT DISTINCT
- a.id,
- a.name,
- 'app' as type,
- 'individual' as participant_type,
- COALESCE(js.total_score, 0) as score,
- CASE
- WHEN js.total_score > 0 THEN 'completed'
- ELSE 'pending'
- END as status,
- js.submitted_at,
- t.name as team_name,
- CONCAT(COALESCE(t.name, '未知團隊'), ' - ', a.name) as display_name
- FROM apps a
- LEFT JOIN teams t ON a.team_id = t.id
- LEFT JOIN competition_apps ca ON a.id = ca.app_id
- LEFT JOIN judge_scores js ON a.id = js.app_id AND js.judge_id = ?
- WHERE ca.competition_id = ?
- `;
-
- const params = [judgeId];
+ let sql: string;
+ let params: any[];
if (competitionId) {
- params.push(competitionId);
+ // 獲取特定競賽的評分任務
+ sql = `
+ SELECT DISTINCT
+ a.id,
+ a.name,
+ 'app' as type,
+ 'individual' as participant_type,
+ COALESCE(js.total_score, 0) as score,
+ CASE
+ WHEN js.total_score > 0 THEN 'completed'
+ ELSE 'pending'
+ END as status,
+ js.submitted_at,
+ t.name as team_name,
+ a.name as display_name
+ FROM apps a
+ LEFT JOIN teams t ON a.team_id = t.id
+ LEFT JOIN competition_apps ca ON a.id = ca.app_id
+ LEFT JOIN judge_scores js ON a.id = js.app_id AND js.judge_id = ?
+ WHERE ca.competition_id = ?
+ ORDER BY a.name
+ `;
+ params = [judgeId, competitionId];
} else {
- // 如果沒有指定競賽,獲取所有競賽的任務
- sql = sql.replace('WHERE ca.competition_id = ?', 'WHERE ca.competition_id IS NOT NULL');
+ // 獲取所有競賽的任務
+ sql = `
+ SELECT DISTINCT
+ a.id,
+ a.name,
+ 'app' as type,
+ 'individual' as participant_type,
+ COALESCE(js.total_score, 0) as score,
+ CASE
+ WHEN js.total_score > 0 THEN 'completed'
+ ELSE 'pending'
+ END as status,
+ js.submitted_at,
+ t.name as team_name,
+ a.name as display_name
+ FROM apps a
+ LEFT JOIN teams t ON a.team_id = t.id
+ LEFT JOIN competition_apps ca ON a.id = ca.app_id
+ LEFT JOIN judge_scores js ON a.id = js.app_id AND js.judge_id = ?
+ WHERE ca.competition_id IS NOT NULL
+ ORDER BY a.name
+ `;
+ params = [judgeId];
}
- sql += ' ORDER BY a.name';
-
const results = await DatabaseServiceBase.safeQuery(sql, params);
return results;
}
@@ -1002,7 +1045,6 @@ export class TeamService extends DatabaseServiceBase {
];
const result = await DatabaseServiceBase.safeInsert(sql, params);
- console.log('團隊創建結果:', result);
return id;
}
@@ -1025,13 +1067,6 @@ export class TeamService extends DatabaseServiceBase {
ORDER BY t.created_at DESC
`;
const results = await DatabaseServiceBase.safeQuery(sql);
- console.log('🔍 getAllTeams 查詢結果:', results.slice(0, 2).map(r => ({
- id: r.id,
- name: r.name,
- leader_name: r.leader_name,
- member_count: r.member_count,
- submissionDate: r.submissionDate
- })));
return results;
}
@@ -1291,10 +1326,7 @@ export class TeamService extends DatabaseServiceBase {
WHERE a.team_id = ? AND a.is_active = 1
ORDER BY a.created_at DESC
`;
- console.log('📝 getTeamApps SQL:', sql);
- console.log('📝 getTeamApps 參數:', [teamId]);
const results = await DatabaseServiceBase.safeQuery(sql, [teamId]);
- console.log('📊 getTeamApps 結果:', results.length, '個應用');
return results;
}
@@ -1933,15 +1965,6 @@ export class CompetitionService extends DatabaseServiceBase {
const startDateUTC = new Date(startDate.getTime() + startDate.getTimezoneOffset() * 60000);
const endDateUTC = new Date(endDate.getTime() + endDate.getTimezoneOffset() * 60000);
- console.log('🔍 競賽狀態計算:', {
- competitionId,
- name: competition.name,
- now: nowUTC.toISOString(),
- startDate: startDateUTC.toISOString(),
- endDate: endDateUTC.toISOString(),
- originalStatus: competition.status
- });
-
// 根據實際日期計算狀態
if (nowUTC < startDateUTC) {
calculatedStatus = 'upcoming'; // 即將開始
@@ -1950,8 +1973,6 @@ export class CompetitionService extends DatabaseServiceBase {
} else if (nowUTC > endDateUTC) {
calculatedStatus = 'completed'; // 已完成
}
-
- console.log('🔍 計算後的狀態:', calculatedStatus);
// 轉換字段名稱以匹配前端期望的格式
return {
@@ -2977,14 +2998,41 @@ export class AppService extends DatabaseServiceBase {
`;
const reviewStats = await this.queryOne(reviewStatsSql);
- // 競賽統計
- const competitionStatsSql = `
- SELECT
- COUNT(*) as total_competitions,
- COUNT(CASE WHEN status = 'active' OR status = 'ongoing' THEN 1 END) as active_competitions
- FROM competitions
- `;
- const competitionStats = await this.queryOne(competitionStatsSql);
+ // 競賽統計 - 使用動態計算的狀態
+ const competitions = await CompetitionService.getAllCompetitions();
+
+ // 動態計算每個競賽的狀態
+ const now = new Date();
+ const competitionsWithCalculatedStatus = competitions.map(competition => {
+ const startDate = new Date(competition.start_date);
+ const endDate = new Date(competition.end_date);
+
+ let calculatedStatus = competition.status;
+
+ // 確保日期比較的準確性,使用 UTC 時間避免時區問題
+ const nowUTC = new Date(now.getTime() + now.getTimezoneOffset() * 60000);
+ const startDateUTC = new Date(startDate.getTime() + startDate.getTimezoneOffset() * 60000);
+ const endDateUTC = new Date(endDate.getTime() + endDate.getTimezoneOffset() * 60000);
+
+ // 根據實際日期計算狀態
+ if (nowUTC < startDateUTC) {
+ calculatedStatus = 'upcoming'; // 即將開始
+ } else if (nowUTC >= startDateUTC && nowUTC <= endDateUTC) {
+ calculatedStatus = 'active'; // 進行中
+ } else if (nowUTC > endDateUTC) {
+ calculatedStatus = 'completed'; // 已完成
+ }
+
+ return {
+ ...competition,
+ status: calculatedStatus
+ };
+ });
+
+ const competitionStats = {
+ total_competitions: competitionsWithCalculatedStatus.length,
+ active_competitions: competitionsWithCalculatedStatus.filter(c => c.status === 'active').length
+ };
// 計算增長率(與上個月比較)
const lastMonthUsersSql = `
@@ -3004,8 +3052,6 @@ export class AppService extends DatabaseServiceBase {
totalUsers: userStats.totalUsers,
activeUsers: userStats.activeUsers,
totalApps: appStats?.total_apps || 0,
- activeApps: appStats?.active_apps || 0,
- inactiveApps: appStats?.inactive_apps || 0,
totalCompetitions: competitionStats?.total_competitions || 0,
totalReviews: reviewStats?.total_reviews || 0,
totalViews: appStats?.total_views || 0,
@@ -3578,7 +3624,6 @@ export class ScoringService extends DatabaseServiceBase {
try {
const result = await DatabaseServiceBase.safeQuery(sql, [competitionId]);
- console.log('🔍 競賽規則查詢結果:', result);
return result;
} catch (error) {
console.error('❌ 獲取競賽規則失敗:', error);
@@ -3867,7 +3912,6 @@ export class ScoringService extends DatabaseServiceBase {
};
}> {
try {
- console.log('🔍 獲取評分完成度匯總,competitionId:', competitionId);
// 獲取競賽的評審列表 - 先嘗試從關聯表獲取,如果沒有則獲取所有評審
let judgesResult = await DatabaseServiceBase.safeQuery(`