修正評審評分機制問題
This commit is contained in:
@@ -93,6 +93,8 @@ export async function GET(request: NextRequest) {
|
|||||||
|
|
||||||
// 構建每日使用數據
|
// 構建每日使用數據
|
||||||
const dailyUsageData = []
|
const dailyUsageData = []
|
||||||
|
console.log('🔍 開始構建每日使用數據...')
|
||||||
|
|
||||||
for (let i = 6; i >= 0; i--) {
|
for (let i = 6; i >= 0; i--) {
|
||||||
const date = new Date(Date.now() - i * 24 * 60 * 60 * 1000)
|
const date = new Date(Date.now() - i * 24 * 60 * 60 * 1000)
|
||||||
const dateStr = date.toISOString().split('T')[0]
|
const dateStr = date.toISOString().split('T')[0]
|
||||||
@@ -111,7 +113,7 @@ export async function GET(request: NextRequest) {
|
|||||||
const memoryPeak = Math.min(85, 25 + dailyUsers * 0.7 + dailySessions * 0.04)
|
const memoryPeak = Math.min(85, 25 + dailyUsers * 0.7 + dailySessions * 0.04)
|
||||||
const requests = dailySessions + dailyActivity
|
const requests = dailySessions + dailyActivity
|
||||||
|
|
||||||
dailyUsageData.push({
|
const dayData = {
|
||||||
date: `${date.getMonth() + 1}/${date.getDate()}`,
|
date: `${date.getMonth() + 1}/${date.getDate()}`,
|
||||||
fullDate: date.toLocaleDateString("zh-TW"),
|
fullDate: date.toLocaleDateString("zh-TW"),
|
||||||
dayName: dayName,
|
dayName: dayName,
|
||||||
@@ -121,8 +123,13 @@ export async function GET(request: NextRequest) {
|
|||||||
avgCpu: Math.round(avgCpu),
|
avgCpu: Math.round(avgCpu),
|
||||||
memoryPeak: Math.round(memoryPeak),
|
memoryPeak: Math.round(memoryPeak),
|
||||||
requests: requests
|
requests: requests
|
||||||
})
|
}
|
||||||
|
|
||||||
|
dailyUsageData.push(dayData)
|
||||||
|
console.log(`📊 ${dateStr}:`, dayData)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log('✅ 每日使用數據構建完成:', dailyUsageData)
|
||||||
|
|
||||||
// 獲取應用類別分布
|
// 獲取應用類別分布
|
||||||
const categoryDataResult = await db.query(`
|
const categoryDataResult = await db.query(`
|
||||||
@@ -146,6 +153,8 @@ export async function GET(request: NextRequest) {
|
|||||||
apps: item.app_count
|
apps: item.app_count
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
console.log('📊 類別數據:', categoryData)
|
||||||
|
|
||||||
// 獲取熱門應用排行
|
// 獲取熱門應用排行
|
||||||
const topAppsResult = await db.query(`
|
const topAppsResult = await db.query(`
|
||||||
|
76
app/api/admin/debug-competition-data/route.ts
Normal file
76
app/api/admin/debug-competition-data/route.ts
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
// =====================================================
|
||||||
|
// 調試競賽數據 API
|
||||||
|
// =====================================================
|
||||||
|
|
||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
import { DatabaseServiceBase } from '@/lib/services/database-service';
|
||||||
|
|
||||||
|
export async function GET(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const { searchParams } = new URL(request.url);
|
||||||
|
const competitionId = searchParams.get('competitionId') || '07e2303e-9647-11f0-b5d9-6e36c63cdb98';
|
||||||
|
|
||||||
|
console.log('🔍 開始調試競賽數據...');
|
||||||
|
console.log('競賽ID:', competitionId);
|
||||||
|
|
||||||
|
// 1. 檢查競賽是否存在
|
||||||
|
const competitionCheck = await DatabaseServiceBase.safeQuery(
|
||||||
|
'SELECT * FROM competitions WHERE id = ?',
|
||||||
|
[competitionId]
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log('📊 競賽檢查結果:', competitionCheck);
|
||||||
|
|
||||||
|
// 2. 檢查競賽應用關聯
|
||||||
|
const competitionAppsCheck = await DatabaseServiceBase.safeQuery(
|
||||||
|
'SELECT * FROM competition_apps WHERE competition_id = ?',
|
||||||
|
[competitionId]
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log('📊 競賽應用關聯檢查結果:', competitionAppsCheck);
|
||||||
|
|
||||||
|
// 3. 檢查所有應用程式
|
||||||
|
const allAppsCheck = await DatabaseServiceBase.safeQuery(
|
||||||
|
'SELECT id, name, is_active FROM apps WHERE is_active = 1 LIMIT 10',
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log('📊 所有應用程式檢查結果:', allAppsCheck);
|
||||||
|
|
||||||
|
// 4. 檢查競賽規則
|
||||||
|
const competitionRulesCheck = await DatabaseServiceBase.safeQuery(
|
||||||
|
'SELECT * FROM competition_rules WHERE competition_id = ?',
|
||||||
|
[competitionId]
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log('📊 競賽規則檢查結果:', competitionRulesCheck);
|
||||||
|
|
||||||
|
// 5. 檢查評審
|
||||||
|
const judgesCheck = await DatabaseServiceBase.safeQuery(
|
||||||
|
'SELECT id, name, title, department FROM judges WHERE is_active = 1 LIMIT 5',
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log('📊 評審檢查結果:', judgesCheck);
|
||||||
|
|
||||||
|
return NextResponse.json({
|
||||||
|
success: true,
|
||||||
|
message: '調試數據獲取成功',
|
||||||
|
data: {
|
||||||
|
competition: competitionCheck,
|
||||||
|
competitionApps: competitionAppsCheck,
|
||||||
|
allApps: allAppsCheck,
|
||||||
|
competitionRules: competitionRulesCheck,
|
||||||
|
judges: judgesCheck
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ 調試競賽數據失敗:', error);
|
||||||
|
return NextResponse.json({
|
||||||
|
success: false,
|
||||||
|
message: '調試競賽數據失敗',
|
||||||
|
error: error instanceof Error ? error.message : '未知錯誤'
|
||||||
|
}, { status: 500 });
|
||||||
|
}
|
||||||
|
}
|
@@ -8,7 +8,12 @@ export async function GET(request: NextRequest) {
|
|||||||
const judgeId = searchParams.get('judgeId');
|
const judgeId = searchParams.get('judgeId');
|
||||||
const competitionId = searchParams.get('competitionId');
|
const competitionId = searchParams.get('competitionId');
|
||||||
|
|
||||||
|
console.log('🔍 評審任務API - 接收請求');
|
||||||
|
console.log('judgeId:', judgeId);
|
||||||
|
console.log('competitionId:', competitionId);
|
||||||
|
|
||||||
if (!judgeId) {
|
if (!judgeId) {
|
||||||
|
console.log('❌ 缺少評審ID');
|
||||||
return NextResponse.json({
|
return NextResponse.json({
|
||||||
success: false,
|
success: false,
|
||||||
message: '缺少評審ID',
|
message: '缺少評審ID',
|
||||||
@@ -17,8 +22,12 @@ export async function GET(request: NextRequest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 獲取評審信息
|
// 獲取評審信息
|
||||||
|
console.log('🔍 開始獲取評審信息...');
|
||||||
const judge = await JudgeService.getJudgeById(judgeId);
|
const judge = await JudgeService.getJudgeById(judgeId);
|
||||||
|
console.log('📊 評審信息查詢結果:', judge);
|
||||||
|
|
||||||
if (!judge) {
|
if (!judge) {
|
||||||
|
console.log('❌ 評審不存在');
|
||||||
return NextResponse.json({
|
return NextResponse.json({
|
||||||
success: false,
|
success: false,
|
||||||
message: '評審不存在',
|
message: '評審不存在',
|
||||||
@@ -27,17 +36,22 @@ export async function GET(request: NextRequest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 獲取評審的評分任務
|
// 獲取評審的評分任務
|
||||||
|
console.log('🔍 開始獲取評分任務...');
|
||||||
let scoringTasks = [];
|
let scoringTasks = [];
|
||||||
|
|
||||||
if (competitionId) {
|
if (competitionId) {
|
||||||
// 獲取特定競賽的評分任務
|
// 獲取特定競賽的評分任務
|
||||||
|
console.log('📊 獲取特定競賽的評分任務');
|
||||||
scoringTasks = await JudgeService.getJudgeScoringTasks(judgeId, competitionId);
|
scoringTasks = await JudgeService.getJudgeScoringTasks(judgeId, competitionId);
|
||||||
} else {
|
} else {
|
||||||
// 獲取所有評分任務
|
// 獲取所有評分任務
|
||||||
|
console.log('📊 獲取所有評分任務');
|
||||||
scoringTasks = await JudgeService.getJudgeScoringTasks(judgeId);
|
scoringTasks = await JudgeService.getJudgeScoringTasks(judgeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NextResponse.json({
|
console.log('📊 評分任務查詢結果:', scoringTasks);
|
||||||
|
|
||||||
|
const response = {
|
||||||
success: true,
|
success: true,
|
||||||
message: '評分任務獲取成功',
|
message: '評分任務獲取成功',
|
||||||
data: {
|
data: {
|
||||||
@@ -46,14 +60,17 @@ export async function GET(request: NextRequest) {
|
|||||||
name: judge.name,
|
name: judge.name,
|
||||||
title: judge.title,
|
title: judge.title,
|
||||||
department: judge.department,
|
department: judge.department,
|
||||||
specialty: judge.specialty || '評審專家'
|
specialty: '評審專家'
|
||||||
},
|
},
|
||||||
tasks: scoringTasks
|
tasks: scoringTasks
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
|
console.log('✅ API回應:', response);
|
||||||
|
return NextResponse.json(response);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('獲取評分任務失敗:', error);
|
console.error('❌ 獲取評分任務失敗:', error);
|
||||||
return NextResponse.json({
|
return NextResponse.json({
|
||||||
success: false,
|
success: false,
|
||||||
message: '獲取評分任務失敗',
|
message: '獲取評分任務失敗',
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import { useState } from "react"
|
import { useState, useEffect } from "react"
|
||||||
|
import { useSearchParams } from "next/navigation"
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/ui/button"
|
||||||
import { Input } from "@/components/ui/input"
|
import { Input } from "@/components/ui/input"
|
||||||
@@ -22,6 +23,7 @@ interface Judge {
|
|||||||
interface ScoringItem {
|
interface ScoringItem {
|
||||||
id: string
|
id: string
|
||||||
name: string
|
name: string
|
||||||
|
display_name?: string
|
||||||
type: "individual" | "team"
|
type: "individual" | "team"
|
||||||
status: "pending" | "completed"
|
status: "pending" | "completed"
|
||||||
score?: number
|
score?: number
|
||||||
@@ -29,6 +31,7 @@ interface ScoringItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function JudgeScoringPage() {
|
export default function JudgeScoringPage() {
|
||||||
|
const searchParams = useSearchParams()
|
||||||
const [isLoggedIn, setIsLoggedIn] = useState(false)
|
const [isLoggedIn, setIsLoggedIn] = useState(false)
|
||||||
const [judgeId, setJudgeId] = useState("")
|
const [judgeId, setJudgeId] = useState("")
|
||||||
const [accessCode, setAccessCode] = useState("")
|
const [accessCode, setAccessCode] = useState("")
|
||||||
@@ -44,6 +47,18 @@ export default function JudgeScoringPage() {
|
|||||||
const [showAccessCode, setShowAccessCode] = useState(false)
|
const [showAccessCode, setShowAccessCode] = useState(false)
|
||||||
const [isLoading, setIsLoading] = useState(false)
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
const [competitionRules, setCompetitionRules] = useState<any[]>([])
|
const [competitionRules, setCompetitionRules] = useState<any[]>([])
|
||||||
|
const [competitionId, setCompetitionId] = useState<string>("")
|
||||||
|
|
||||||
|
// 從URL參數中獲取競賽ID
|
||||||
|
useEffect(() => {
|
||||||
|
const competitionIdParam = searchParams.get('competitionId')
|
||||||
|
if (competitionIdParam) {
|
||||||
|
setCompetitionId(competitionIdParam)
|
||||||
|
} else {
|
||||||
|
// 如果沒有URL參數,使用默認的競賽ID
|
||||||
|
setCompetitionId('07e2303e-9647-11f0-b5d9-6e36c63cdb98')
|
||||||
|
}
|
||||||
|
}, [searchParams])
|
||||||
|
|
||||||
const handleLogin = async () => {
|
const handleLogin = async () => {
|
||||||
setError("")
|
setError("")
|
||||||
@@ -62,11 +77,21 @@ export default function JudgeScoringPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
console.log('🔍 開始登入流程...')
|
||||||
|
console.log('評審ID:', judgeId)
|
||||||
|
console.log('競賽ID:', competitionId)
|
||||||
|
|
||||||
// 獲取評審的評分任務
|
// 獲取評審的評分任務
|
||||||
const response = await fetch(`/api/judge/scoring-tasks?judgeId=${judgeId}&competitionId=0fffae9a-9539-11f0-b5d9-6e36c63cdb98`)
|
const response = await fetch(`/api/judge/scoring-tasks?judgeId=${judgeId}&competitionId=${competitionId}`)
|
||||||
const data = await response.json()
|
const data = await response.json()
|
||||||
|
|
||||||
|
console.log('📊 評分任務API回應:', data)
|
||||||
|
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
|
console.log('✅ 登入成功')
|
||||||
|
console.log('評審信息:', data.data.judge)
|
||||||
|
console.log('評分任務:', data.data.tasks)
|
||||||
|
|
||||||
setCurrentJudge(data.data.judge)
|
setCurrentJudge(data.data.judge)
|
||||||
setScoringItems(data.data.tasks)
|
setScoringItems(data.data.tasks)
|
||||||
setIsLoggedIn(true)
|
setIsLoggedIn(true)
|
||||||
@@ -76,10 +101,11 @@ export default function JudgeScoringPage() {
|
|||||||
// 載入競賽規則
|
// 載入競賽規則
|
||||||
await loadCompetitionRules()
|
await loadCompetitionRules()
|
||||||
} else {
|
} else {
|
||||||
|
console.error('❌ 登入失敗:', data.message)
|
||||||
setError(data.message || "登入失敗")
|
setError(data.message || "登入失敗")
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('登入失敗:', err)
|
console.error('❌ 登入失敗:', err)
|
||||||
setError("登入失敗,請重試")
|
setError("登入失敗,請重試")
|
||||||
} finally {
|
} finally {
|
||||||
setIsLoading(false)
|
setIsLoading(false)
|
||||||
@@ -88,18 +114,27 @@ export default function JudgeScoringPage() {
|
|||||||
|
|
||||||
const loadCompetitionRules = async () => {
|
const loadCompetitionRules = async () => {
|
||||||
try {
|
try {
|
||||||
// 使用正確的競賽ID
|
console.log('🔍 開始載入競賽規則...')
|
||||||
const response = await fetch('/api/competitions/0fffae9a-9539-11f0-b5d9-6e36c63cdb98/rules')
|
console.log('競賽ID:', competitionId)
|
||||||
|
|
||||||
|
// 使用動態的競賽ID
|
||||||
|
const response = await fetch(`/api/competitions/${competitionId}/rules`)
|
||||||
const data = await response.json()
|
const data = await response.json()
|
||||||
|
|
||||||
|
console.log('📊 競賽規則API回應:', data)
|
||||||
|
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
|
console.log('✅ 競賽規則載入成功:', data.data)
|
||||||
setCompetitionRules(data.data)
|
setCompetitionRules(data.data)
|
||||||
|
} else {
|
||||||
|
console.error('❌ 競賽規則載入失敗:', data.message)
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('載入競賽規則失敗:', err)
|
console.error('❌ 載入競賽規則失敗:', err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const handleStartScoring = async (item: ScoringItem) => {
|
const handleStartScoring = async (item: ScoringItem) => {
|
||||||
setSelectedItem(item)
|
setSelectedItem(item)
|
||||||
|
|
||||||
@@ -169,7 +204,7 @@ export default function JudgeScoringPage() {
|
|||||||
participantType: 'app',
|
participantType: 'app',
|
||||||
scores: scores,
|
scores: scores,
|
||||||
comments: comments.trim(),
|
comments: comments.trim(),
|
||||||
competitionId: '0fffae9a-9539-11f0-b5d9-6e36c63cdb98', // 正確的競賽ID
|
competitionId: competitionId, // 動態競賽ID
|
||||||
isEdit: selectedItem.status === "completed", // 如果是重新評分,標記為編輯模式
|
isEdit: selectedItem.status === "completed", // 如果是重新評分,標記為編輯模式
|
||||||
recordId: selectedItem.status === "completed" ? selectedItem.id : null
|
recordId: selectedItem.status === "completed" ? selectedItem.id : null
|
||||||
})
|
})
|
||||||
|
@@ -55,16 +55,20 @@ export function AnalyticsDashboard() {
|
|||||||
const loadAnalyticsData = async () => {
|
const loadAnalyticsData = async () => {
|
||||||
try {
|
try {
|
||||||
setIsLoading(true)
|
setIsLoading(true)
|
||||||
|
console.log('🔄 開始載入分析數據...')
|
||||||
const response = await fetch('/api/admin/analytics')
|
const response = await fetch('/api/admin/analytics')
|
||||||
const data = await response.json()
|
const data = await response.json()
|
||||||
|
|
||||||
|
console.log('📊 API回應數據:', data)
|
||||||
|
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
setAnalyticsData(data.data)
|
setAnalyticsData(data.data)
|
||||||
|
console.log('✅ 分析數據載入成功')
|
||||||
} else {
|
} else {
|
||||||
console.error('載入分析數據失敗:', data.error)
|
console.error('❌ 載入分析數據失敗:', data.error)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('載入分析數據錯誤:', error)
|
console.error('❌ 載入分析數據錯誤:', error)
|
||||||
} finally {
|
} finally {
|
||||||
setIsLoading(false)
|
setIsLoading(false)
|
||||||
}
|
}
|
||||||
@@ -111,23 +115,30 @@ export function AnalyticsDashboard() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const recentDates = getRecentDates()
|
const recentDates = getRecentDates()
|
||||||
const dailyUsageData = [
|
|
||||||
{ ...recentDates[0], users: 245, sessions: 189, cpuPeak: 65, avgCpu: 45, memoryPeak: 58, requests: 1240 },
|
// 使用API提供的真實數據,如果沒有則使用默認數據
|
||||||
{ ...recentDates[1], users: 267, sessions: 203, cpuPeak: 68, avgCpu: 48, memoryPeak: 62, requests: 1356 },
|
const dailyUsageData = analyticsData.dailyUsageData && analyticsData.dailyUsageData.length > 0
|
||||||
{ ...recentDates[2], users: 289, sessions: 221, cpuPeak: 72, avgCpu: 52, memoryPeak: 65, requests: 1478 },
|
? analyticsData.dailyUsageData
|
||||||
{ ...recentDates[3], users: 312, sessions: 245, cpuPeak: 75, avgCpu: 55, memoryPeak: 68, requests: 1589 },
|
: [
|
||||||
{ ...recentDates[4], users: 298, sessions: 234, cpuPeak: 73, avgCpu: 53, memoryPeak: 66, requests: 1523 },
|
{ ...recentDates[0], users: 0, sessions: 0, cpuPeak: 20, avgCpu: 15, memoryPeak: 25, requests: 0 },
|
||||||
{ ...recentDates[5], users: 334, sessions: 267, cpuPeak: 78, avgCpu: 58, memoryPeak: 71, requests: 1678 },
|
{ ...recentDates[1], users: 0, sessions: 0, cpuPeak: 20, avgCpu: 15, memoryPeak: 25, requests: 0 },
|
||||||
{ ...recentDates[6], users: 356, sessions: 289, cpuPeak: 82, avgCpu: 62, memoryPeak: 75, requests: 1789 },
|
{ ...recentDates[2], users: 0, sessions: 0, cpuPeak: 20, avgCpu: 15, memoryPeak: 25, requests: 0 },
|
||||||
]
|
{ ...recentDates[3], users: 0, sessions: 0, cpuPeak: 20, avgCpu: 15, memoryPeak: 25, requests: 0 },
|
||||||
|
{ ...recentDates[4], users: 0, sessions: 0, cpuPeak: 20, avgCpu: 15, memoryPeak: 25, requests: 0 },
|
||||||
|
{ ...recentDates[5], users: 0, sessions: 0, cpuPeak: 20, avgCpu: 15, memoryPeak: 25, requests: 0 },
|
||||||
|
{ ...recentDates[6], users: 0, sessions: 0, cpuPeak: 20, avgCpu: 15, memoryPeak: 25, requests: 0 },
|
||||||
|
]
|
||||||
|
|
||||||
const categoryData = [
|
// 使用API提供的真實類別數據,如果沒有則使用默認數據
|
||||||
{ name: "AI工具", value: 35, color: "#3b82f6", users: 3083, apps: 45 },
|
const categoryData = analyticsData.categoryData && analyticsData.categoryData.length > 0
|
||||||
{ name: "數據分析", value: 25, color: "#ef4444", users: 1565, apps: 32 },
|
? analyticsData.categoryData
|
||||||
{ name: "自動化", value: 20, color: "#10b981", users: 856, apps: 25 },
|
: [
|
||||||
{ name: "機器學習", value: 15, color: "#f59e0b", users: 743, apps: 19 },
|
{ name: "AI工具", value: 35, color: "#3b82f6", users: 0, apps: 0 },
|
||||||
{ name: "其他", value: 5, color: "#8b5cf6", users: 234, apps: 6 },
|
{ name: "數據分析", value: 25, color: "#ef4444", users: 0, apps: 0 },
|
||||||
]
|
{ name: "自動化", value: 20, color: "#10b981", users: 0, apps: 0 },
|
||||||
|
{ name: "機器學習", value: 15, color: "#f59e0b", users: 0, apps: 0 },
|
||||||
|
{ name: "其他", value: 5, color: "#8b5cf6", users: 0, apps: 0 },
|
||||||
|
]
|
||||||
|
|
||||||
const topApps = [
|
const topApps = [
|
||||||
{ name: "智能客服助手", views: 1234, rating: 4.8, category: "AI工具" },
|
{ name: "智能客服助手", views: 1234, rating: 4.8, category: "AI工具" },
|
||||||
|
@@ -960,11 +960,16 @@ export class JudgeService extends DatabaseServiceBase {
|
|||||||
|
|
||||||
// 獲取評審的評分任務
|
// 獲取評審的評分任務
|
||||||
static async getJudgeScoringTasks(judgeId: string, competitionId?: string): Promise<any[]> {
|
static async getJudgeScoringTasks(judgeId: string, competitionId?: string): Promise<any[]> {
|
||||||
|
console.log('🔍 JudgeService.getJudgeScoringTasks 被調用');
|
||||||
|
console.log('judgeId:', judgeId);
|
||||||
|
console.log('competitionId:', competitionId);
|
||||||
|
|
||||||
let sql: string;
|
let sql: string;
|
||||||
let params: any[];
|
let params: any[];
|
||||||
|
|
||||||
if (competitionId) {
|
if (competitionId) {
|
||||||
// 獲取特定競賽的評分任務
|
// 獲取特定競賽的評分任務
|
||||||
|
// 使用 UNION 來合併個人競賽和團隊競賽的應用程式
|
||||||
sql = `
|
sql = `
|
||||||
SELECT DISTINCT
|
SELECT DISTINCT
|
||||||
a.id,
|
a.id,
|
||||||
@@ -977,16 +982,37 @@ export class JudgeService extends DatabaseServiceBase {
|
|||||||
ELSE 'pending'
|
ELSE 'pending'
|
||||||
END as status,
|
END as status,
|
||||||
js.submitted_at,
|
js.submitted_at,
|
||||||
t.name as team_name,
|
NULL as team_name,
|
||||||
a.name as display_name
|
a.name as display_name
|
||||||
FROM apps a
|
FROM apps a
|
||||||
|
INNER JOIN competition_apps ca ON a.id = ca.app_id
|
||||||
|
LEFT JOIN app_judge_scores js ON a.id = js.app_id AND js.judge_id = ?
|
||||||
|
WHERE ca.competition_id = ? AND a.is_active = 1
|
||||||
|
|
||||||
|
UNION ALL
|
||||||
|
|
||||||
|
SELECT DISTINCT
|
||||||
|
a.id,
|
||||||
|
a.name,
|
||||||
|
'app' as type,
|
||||||
|
'team' 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(t.name, ' - ', a.name) as display_name
|
||||||
|
FROM apps a
|
||||||
|
INNER JOIN competition_teams ct ON a.team_id = ct.team_id
|
||||||
LEFT JOIN teams t ON a.team_id = t.id
|
LEFT JOIN teams t ON a.team_id = t.id
|
||||||
LEFT JOIN competition_apps ca ON a.id = ca.app_id
|
LEFT JOIN app_judge_scores js ON a.id = js.app_id AND js.judge_id = ?
|
||||||
LEFT JOIN judge_scores js ON a.id = js.app_id AND js.judge_id = ?
|
WHERE ct.competition_id = ? AND a.is_active = 1
|
||||||
WHERE ca.competition_id = ?
|
|
||||||
ORDER BY a.name
|
ORDER BY display_name
|
||||||
`;
|
`;
|
||||||
params = [judgeId, competitionId];
|
params = [judgeId, competitionId, judgeId, competitionId];
|
||||||
} else {
|
} else {
|
||||||
// 獲取所有競賽的任務
|
// 獲取所有競賽的任務
|
||||||
sql = `
|
sql = `
|
||||||
@@ -1001,19 +1027,46 @@ export class JudgeService extends DatabaseServiceBase {
|
|||||||
ELSE 'pending'
|
ELSE 'pending'
|
||||||
END as status,
|
END as status,
|
||||||
js.submitted_at,
|
js.submitted_at,
|
||||||
t.name as team_name,
|
NULL as team_name,
|
||||||
a.name as display_name
|
a.name as display_name
|
||||||
FROM apps a
|
FROM apps a
|
||||||
|
INNER JOIN competition_apps ca ON a.id = ca.app_id
|
||||||
|
LEFT JOIN app_judge_scores js ON a.id = js.app_id AND js.judge_id = ?
|
||||||
|
WHERE a.is_active = 1
|
||||||
|
|
||||||
|
UNION ALL
|
||||||
|
|
||||||
|
SELECT DISTINCT
|
||||||
|
a.id,
|
||||||
|
a.name,
|
||||||
|
'app' as type,
|
||||||
|
'team' 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(t.name, ' - ', a.name) as display_name
|
||||||
|
FROM apps a
|
||||||
|
INNER JOIN competition_teams ct ON a.team_id = ct.team_id
|
||||||
LEFT JOIN teams t ON a.team_id = t.id
|
LEFT JOIN teams t ON a.team_id = t.id
|
||||||
LEFT JOIN competition_apps ca ON a.id = ca.app_id
|
LEFT JOIN app_judge_scores js ON a.id = js.app_id AND js.judge_id = ?
|
||||||
LEFT JOIN judge_scores js ON a.id = js.app_id AND js.judge_id = ?
|
WHERE a.is_active = 1
|
||||||
WHERE ca.competition_id IS NOT NULL
|
|
||||||
ORDER BY a.name
|
ORDER BY display_name
|
||||||
`;
|
`;
|
||||||
params = [judgeId];
|
params = [judgeId, judgeId];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log('🔍 執行SQL查詢:');
|
||||||
|
console.log('SQL:', sql);
|
||||||
|
console.log('參數:', params);
|
||||||
|
|
||||||
const results = await DatabaseServiceBase.safeQuery(sql, params);
|
const results = await DatabaseServiceBase.safeQuery(sql, params);
|
||||||
|
console.log('📊 查詢結果:', results);
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user