From 2597a075143b8887f74ad836ac5b83a8794e9647 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B3=E4=BD=A9=E5=BA=AD?= Date: Sat, 27 Sep 2025 01:06:26 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E7=8D=8E=E5=8B=B5=E5=B0=88?= =?UTF-8?q?=E5=8D=80=E8=A9=95=E5=AF=A9=E5=9C=98=E8=B3=87=E6=96=99=E7=95=B0?= =?UTF-8?q?=E5=B8=B8=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/admin/competition-management.tsx | 96 ++++++++++------- .../competition/award-detail-dialog.tsx | 102 +++++++++++++----- database-awards-extension.sql | 27 +++++ 3 files changed, 160 insertions(+), 65 deletions(-) create mode 100644 database-awards-extension.sql diff --git a/components/admin/competition-management.tsx b/components/admin/competition-management.tsx index be5acea..99e5c32 100644 --- a/components/admin/competition-management.tsx +++ b/components/admin/competition-management.tsx @@ -2143,11 +2143,17 @@ export function CompetitionManagement() { if (teamsData.success && teamsData.data && teamsData.data.teams) { console.log('✅ 競賽團隊載入成功:', teamsData.data.teams.length, '個團隊') - updatedCompetition.teams = teamsData.data.teams - // 同時更新dbTeams + // 確保團隊數據的唯一性,避免重複的ID + const uniqueTeams = teamsData.data.teams.filter((team: any, index: number, self: any[]) => + self.findIndex(t => t.id === team.id) === index + ) + updatedCompetition.teams = uniqueTeams + console.log('🔍 去重後的團隊數量:', uniqueTeams.length) + + // 同時更新dbTeams,確保不重複添加 setDbTeams(prev => { const existingIds = prev.map(t => t.id) - const newTeams = teamsData.data.teams.filter((t: any) => !existingIds.includes(t.id)) + const newTeams = uniqueTeams.filter((t: any) => !existingIds.includes(t.id)) return [...prev, ...newTeams] }) } else { @@ -3195,8 +3201,8 @@ export function CompetitionManagement() { ) } - return paginatedTeams.map((team) => ( - + return paginatedTeams.map((team, index) => ( +
@@ -4067,7 +4073,7 @@ export function CompetitionManagement() { if (links && links.production) { linkItems.push( ); @@ -4538,7 +4544,7 @@ export function CompetitionManagement() {
{ const updatedRules = [...newCompetition.individualConfig.rules] updatedRules[index] = { ...rule, name: e.target.value } @@ -4557,7 +4563,7 @@ export function CompetitionManagement() {
{ const updatedRules = [...newCompetition.individualConfig.rules] updatedRules[index] = { ...rule, description: e.target.value } @@ -4579,7 +4585,7 @@ export function CompetitionManagement() { type="number" min="0" max="100" - value={rule.weight || 0} + value={rule.weight ?? 0} onChange={(e) => { const updatedRules = [...newCompetition.individualConfig.rules] updatedRules[index] = { ...rule, weight: Number.parseInt(e.target.value) || 0 } @@ -4672,7 +4678,7 @@ export function CompetitionManagement() {
{ const updatedAwardTypes = [...newCompetition.individualConfig.awardTypes] updatedAwardTypes[index] = { ...awardType, name: e.target.value } @@ -4725,7 +4731,7 @@ export function CompetitionManagement() {
{ const updatedAwardTypes = [...newCompetition.individualConfig.awardTypes] updatedAwardTypes[index] = { ...awardType, description: e.target.value } @@ -4744,7 +4750,7 @@ export function CompetitionManagement() {
{ const updatedRules = [...newCompetition.teamConfig.rules] updatedRules[index] = { ...rule, name: e.target.value } @@ -4969,7 +4975,7 @@ export function CompetitionManagement() {
{ const updatedRules = [...newCompetition.teamConfig.rules] updatedRules[index] = { ...rule, description: e.target.value } @@ -4991,7 +4997,7 @@ export function CompetitionManagement() { type="number" min="0" max="100" - value={rule.weight || 0} + value={rule.weight ?? 0} onChange={(e) => { const updatedRules = [...newCompetition.teamConfig.rules] updatedRules[index] = { ...rule, weight: Number.parseInt(e.target.value) || 0 } @@ -5084,7 +5090,7 @@ export function CompetitionManagement() {
{ const updatedAwardTypes = [...newCompetition.teamConfig.awardTypes] updatedAwardTypes[index] = { ...awardType, name: e.target.value } @@ -5138,7 +5144,7 @@ export function CompetitionManagement() {
{ const updatedAwardTypes = [...newCompetition.teamConfig.awardTypes] updatedAwardTypes[index] = { ...awardType, description: e.target.value } @@ -5157,7 +5163,7 @@ export function CompetitionManagement() {
{ const updatedRules = [...newCompetition.rules] updatedRules[index] = { ...rule, name: e.target.value } @@ -5363,7 +5369,7 @@ export function CompetitionManagement() {
{ const updatedRules = [...newCompetition.rules] updatedRules[index] = { ...rule, description: e.target.value } @@ -5379,7 +5385,7 @@ export function CompetitionManagement() { type="number" min="0" max="100" - value={rule.weight || 0} + value={rule.weight ?? 0} onChange={(e) => { const updatedRules = [...newCompetition.rules] updatedRules[index] = { ...rule, weight: Number.parseInt(e.target.value) || 0 } @@ -5468,7 +5474,7 @@ export function CompetitionManagement() {
{ const updatedAwardTypes = [...newCompetition.awardTypes] updatedAwardTypes[index] = { ...awardType, name: e.target.value } @@ -5510,7 +5516,7 @@ export function CompetitionManagement() {
{ const updatedAwardTypes = [...newCompetition.awardTypes] updatedAwardTypes[index] = { ...awardType, description: e.target.value } @@ -5523,7 +5529,7 @@ export function CompetitionManagement() {
{ // 檢查是否為自定義獎項類型 const customAwardType = competitionAwardTypes.find(type => type.id === value) @@ -8095,8 +8109,12 @@ export function CompetitionManagement() { } else if (shouldShowTeam) { // 團體賽:只顯示團隊,不顯示 app return competitionTeams.length > 0 ? ( - competitionTeams.map((team) => ( - + competitionTeams + .filter((team: any, index: number, self: any[]) => + self.findIndex(t => t.id === team.id) === index + ) + .map((team: any, index: number) => ( +
{team.name} @@ -8226,7 +8244,7 @@ export function CompetitionManagement() { })} placeholder="https://app.example.com" /> -

生產環境應用連結

+

APP 應用連結

{/* 網站預覽內容 */} @@ -8574,7 +8592,7 @@ export function CompetitionManagement() { {/* 照片說明 */} { const updatedPhotos = newAward.photos.map(p => p.id === photo.id ? { ...p, caption: e.target.value } : p @@ -8925,7 +8943,7 @@ export function CompetitionManagement() {
- 生產環境 + APP 連結
([]) const competition = competitions.find((c) => c.id === award.competitionId) const judgeScores = getJudgeScores(award.id) const appData = getAppData(award.id) + // 載入競賽評審團資訊 + useEffect(() => { + if (open && award.competitionId) { + const loadCompetitionJudges = async () => { + try { + console.log('🔍 載入競賽評審團:', award.competitionId); + const response = await fetch(`/api/competitions/${award.competitionId}/judges`); + const data = await response.json(); + + if (data.success && data.data && data.data.judges) { + console.log('✅ 獲取到評審團:', data.data.judges.length, '位'); + setCompetitionJudges(data.data.judges); + } else { + console.error('❌ 獲取評審團失敗:', data.message); + setCompetitionJudges([]); + } + } catch (error) { + console.error('❌ 載入評審團失敗:', error); + setCompetitionJudges([]); + } + }; + + loadCompetitionJudges(); + } + }, [open, award.competitionId]); + // Competition photos - empty for production const getCompetitionPhotos = () => { return [] @@ -224,10 +251,20 @@ export function AwardDetailDialog({ open, onOpenChange, award }: AwardDetailDial 競賽描述: {competition.description}

-

+

競賽期間: {competition.startDate} ~ {competition.endDate}

+

+ 評審團: + {competitionJudges && competitionJudges.length > 0 ? ( + + {competitionJudges.length} 位評審 + + ) : ( + 暫無評審信息 + )} +

)} @@ -251,7 +288,7 @@ export function AwardDetailDialog({ open, onOpenChange, award }: AwardDetailDial

正式應用

-

生產環境

+

APP 連結