library-picturebook-activity/frontend/src/api/contests.ts

1273 lines
30 KiB
TypeScript
Raw Normal View History

2025-12-09 11:10:36 +08:00
import request from "@/utils/request";
import type { PaginationParams, PaginationResponse } from "@/types/api";
// ==================== 比赛相关类型 ====================
export interface Contest {
id: number;
contestName: string;
contestType: "individual" | "team";
contestState: "unpublished" | "published";
2026-01-08 09:17:46 +08:00
status: "ongoing" | "finished"; // 赛事进度状态
2025-12-09 11:10:36 +08:00
startTime: string;
endTime: string;
address?: string;
content?: string;
contestTenants?: number[];
coverUrl?: string;
posterUrl?: string;
contactName?: string;
contactPhone?: string;
contactQrcode?: string;
2026-01-08 09:17:46 +08:00
organizers?: string;
coOrganizers?: string;
sponsors?: string;
// 报名配置
2025-12-09 11:10:36 +08:00
registerStartTime: string;
registerEndTime: string;
registerState?: string;
2026-01-08 09:17:46 +08:00
requireAudit: boolean; // 是否需要审核
allowedGrades?: number[]; // 允许报名的年级
allowedClasses?: number[]; // 允许报名的班级
teamMinMembers?: number; // 团队最少人数
teamMaxMembers?: number; // 团队最多人数
// 作品配置
2025-12-09 11:10:36 +08:00
submitRule: "once" | "resubmit";
submitStartTime: string;
submitEndTime: string;
2026-01-08 09:17:46 +08:00
workType?: "image" | "video" | "document" | "code" | "other"; // 作品类型
workRequirement?: string; // 作品要求
// 评审配置
2025-12-09 11:10:36 +08:00
reviewRuleId?: number;
reviewStartTime: string;
reviewEndTime: string;
2026-01-08 09:17:46 +08:00
// 赛果配置
resultState: "unpublished" | "published"; // 赛果发布状态
2025-12-09 11:10:36 +08:00
resultPublishTime?: string;
creator?: number;
modifier?: number;
createTime?: string;
modifyTime?: string;
validState?: number;
attachments?: ContestAttachment[];
reviewRule?: ContestReviewRule;
_count?: {
registrations: number;
works: number;
teams: number;
judges: number;
};
}
export interface CreateContestForm {
2026-01-08 09:17:46 +08:00
id?: number; // 编辑模式时使用
2025-12-09 11:10:36 +08:00
contestName: string;
contestType: "individual" | "team";
startTime: string;
endTime: string;
address?: string;
content?: string;
contestTenants?: number[];
coverUrl?: string;
posterUrl?: string;
contactName?: string;
contactPhone?: string;
contactQrcode?: string;
2026-01-08 09:17:46 +08:00
organizers?: string;
coOrganizers?: string;
sponsors?: string;
// 报名配置
2025-12-09 11:10:36 +08:00
registerStartTime: string;
registerEndTime: string;
2026-01-08 09:17:46 +08:00
requireAudit?: boolean;
allowedGrades?: number[];
allowedClasses?: number[];
teamMinMembers?: number;
teamMaxMembers?: number;
// 作品配置
2025-12-09 11:10:36 +08:00
submitRule?: "once" | "resubmit";
submitStartTime: string;
submitEndTime: string;
2026-01-08 09:17:46 +08:00
workType?: "image" | "video" | "document" | "code" | "other";
workRequirement?: string;
// 评审配置
2025-12-09 11:10:36 +08:00
reviewStartTime: string;
reviewEndTime: string;
resultPublishTime?: string;
}
export interface UpdateContestForm extends Partial<CreateContestForm> {
contestState?: "unpublished" | "published";
}
export interface QueryContestParams extends PaginationParams {
contestName?: string;
contestState?: "unpublished" | "published";
2026-01-08 09:17:46 +08:00
status?: "ongoing" | "finished";
2025-12-09 11:10:36 +08:00
contestType?: string;
}
// ==================== 附件相关类型 ====================
export interface ContestAttachment {
id: number;
contestId: number;
fileName: string;
fileUrl: string;
format?: string;
fileType?: string;
size?: string;
creator?: number;
modifier?: number;
createTime?: string;
modifyTime?: string;
validState?: number;
}
export interface CreateAttachmentForm {
contestId: number;
fileName: string;
fileUrl: string;
format?: string;
fileType?: string;
size?: string;
}
// ==================== 评审规则相关类型 ====================
2026-01-08 09:17:46 +08:00
export interface ReviewDimension {
name: string;
percentage: number;
description?: string;
}
2025-12-09 11:10:36 +08:00
export interface ContestReviewRule {
id: number;
2026-01-08 09:17:46 +08:00
tenantId: number;
2025-12-09 11:10:36 +08:00
ruleName: string;
2026-01-08 09:17:46 +08:00
ruleDescription?: string;
judgeCount: number;
dimensions: ReviewDimension[];
calculationRule: "average" | "remove_max_min" | "remove_min";
2025-12-09 11:10:36 +08:00
creator?: number;
modifier?: number;
createTime?: string;
modifyTime?: string;
validState?: number;
2026-01-08 09:17:46 +08:00
contests?: Array<{
id: number;
contestName: string;
}>;
2025-12-09 11:10:36 +08:00
}
export interface CreateReviewRuleForm {
ruleName: string;
2026-01-08 09:17:46 +08:00
ruleDescription?: string;
judgeCount: number;
dimensions: ReviewDimension[];
calculationRule?: "average" | "remove_max_min" | "remove_min";
2025-12-09 11:10:36 +08:00
}
// ==================== 报名相关类型 ====================
export interface ContestRegistration {
id: number;
contestId: number;
tenantId: number;
registrationType?: "individual" | "team";
teamId?: number;
teamName?: string;
userId: number;
accountNo: string;
accountName: string;
role?: string;
registrationState: "pending" | "passed" | "rejected" | "withdrawn";
registrant?: number;
registrationTime: string;
reason?: string;
operator?: number;
operationDate?: string;
creator?: number;
modifier?: number;
createTime?: string;
modifyTime?: string;
contest?: Contest;
user?: {
id: number;
username: string;
nickname: string;
};
team?: ContestTeam;
_count?: {
works: number;
};
}
export interface CreateRegistrationForm {
contestId: number;
registrationType: "individual" | "team";
teamId?: number;
userId: number;
}
export interface ReviewRegistrationForm {
registrationState: "pending" | "passed" | "rejected" | "withdrawn";
reason?: string;
}
export interface QueryRegistrationParams extends PaginationParams {
contestId?: number;
registrationState?: "pending" | "passed" | "rejected" | "withdrawn";
registrationType?: string;
userId?: number;
}
// ==================== 团队相关类型 ====================
export interface ContestTeam {
id: number;
tenantId: number;
contestId: number;
teamName: string;
leaderUserId: number;
maxMembers?: number;
creator?: number;
modifier?: number;
createTime?: string;
modifyTime?: string;
validState?: number;
leader?: {
id: number;
username: string;
nickname: string;
};
members?: ContestTeamMember[];
contest?: Contest;
_count?: {
members: number;
registrations: number;
};
}
export interface ContestTeamMember {
id: number;
tenantId: number;
teamId: number;
userId: number;
role: "leader" | "member" | "mentor";
creator?: number;
modifier?: number;
createTime?: string;
modifyTime?: string;
user?: {
id: number;
username: string;
nickname: string;
};
}
export interface CreateTeamForm {
contestId: number;
teamName: string;
leaderUserId: number;
maxMembers?: number;
}
export interface InviteMemberForm {
userId: number;
role?: "leader" | "member" | "mentor";
}
// ==================== 作品相关类型 ====================
export interface ContestWork {
id: number;
tenantId: number;
contestId: number;
registrationId: number;
workNo?: string;
title: string;
description?: string;
files?: string[];
version: number;
isLatest: boolean;
status: "submitted" | "locked" | "reviewing" | "rejected" | "accepted";
submitTime: string;
submitterUserId?: number;
submitterAccountNo?: string;
submitSource: string;
previewUrl?: string;
aiModelMeta?: any;
creator?: number;
modifier?: number;
createTime?: string;
modifyTime?: string;
validState?: number;
contest?: Contest;
registration?: ContestRegistration;
attachments?: ContestWorkAttachment[];
_count?: {
scores: number;
assignments: number;
};
}
export interface ContestWorkAttachment {
id: number;
tenantId: number;
contestId: number;
workId: number;
fileName: string;
fileUrl: string;
format?: string;
fileType?: string;
size?: string;
creator?: number;
modifier?: number;
createTime?: string;
modifyTime?: string;
}
export interface SubmitWorkForm {
registrationId: number;
title: string;
description?: string;
files?: string[];
previewUrl?: string;
aiModelMeta?: any;
}
export interface QueryWorkParams extends PaginationParams {
contestId?: number;
registrationId?: number;
status?: "submitted" | "locked" | "reviewing" | "rejected" | "accepted";
title?: string;
}
// ==================== 评审相关类型 ====================
export interface ContestWorkJudgeAssignment {
id: number;
contestId: number;
workId: number;
judgeId: number;
assignmentTime: string;
status: "assigned" | "reviewing" | "completed";
creator?: number;
modifier?: number;
createTime?: string;
modifyTime?: string;
work?: ContestWork;
judge?: {
id: number;
username: string;
nickname: string;
};
scores?: ContestWorkScore[];
}
export interface ContestWorkScore {
id: number;
tenantId: number;
contestId: number;
workId: number;
assignmentId: number;
judgeId: number;
judgeName: string;
dimensionScores: any;
totalScore: number;
comments?: string;
scoreTime: string;
creator?: number;
modifier?: number;
createTime?: string;
modifyTime?: string;
validState?: number;
work?: ContestWork;
judge?: {
id: number;
username: string;
nickname: string;
};
}
export interface AssignWorkForm {
workId: number;
judgeIds: number[];
}
export interface CreateScoreForm {
workId: number;
assignmentId: number;
dimensionScores: any;
totalScore: number;
comments?: string;
}
// ==================== 公告相关类型 ====================
export interface ContestNotice {
id: number;
contestId: number;
title: string;
content: string;
noticeType: "system" | "manual" | "urgent";
priority: number;
publishTime?: string;
creator?: number;
modifier?: number;
createTime?: string;
modifyTime?: string;
validState?: number;
contest?: Contest;
}
export interface CreateNoticeForm {
contestId: number;
title: string;
content: string;
noticeType?: "system" | "manual" | "urgent";
priority?: number;
}
// ==================== 评委相关类型 ====================
export interface ContestJudge {
id: number;
contestId: number;
judgeId: number;
specialty?: string;
weight?: number;
description?: string;
creator?: number;
modifier?: number;
createTime?: string;
modifyTime?: string;
validState?: number;
contest?: Contest;
judge?: {
id: number;
username: string;
nickname: string;
email?: string;
2026-01-08 09:17:46 +08:00
phone?: string;
gender?: 'male' | 'female';
status?: 'enabled' | 'disabled';
tenantId?: number;
tenant?: {
id: number;
name: string;
};
contestJudges?: Array<{
contest: {
id: number;
contestName: string;
status: string;
};
}>;
2025-12-09 11:10:36 +08:00
};
_count?: {
assignedContestWorks: number;
scoredContestWorks: number;
};
}
export interface CreateJudgeForm {
contestId: number;
judgeId: number;
specialty?: string;
weight?: number;
description?: string;
}
// ==================== API 函数 ====================
// 比赛管理
export const contestsApi = {
// 获取比赛列表
getList: async (
params: QueryContestParams
): Promise<PaginationResponse<Contest>> => {
const response = await request.get<any, PaginationResponse<Contest>>(
"/contests",
{ params }
);
return response;
},
2026-01-08 09:17:46 +08:00
// 获取我参与的赛事列表
getMyContests: async (
params: QueryContestParams
): Promise<PaginationResponse<Contest>> => {
const response = await request.get<any, PaginationResponse<Contest>>(
"/contests/my-contests",
{ params }
);
return response;
},
2025-12-09 11:10:36 +08:00
// 获取比赛详情
getDetail: async (id: number): Promise<Contest> => {
const response = await request.get<any, Contest>(`/contests/${id}`);
return response;
},
// 创建比赛
create: async (data: CreateContestForm): Promise<Contest> => {
const response = await request.post<any, Contest>("/contests", data);
return response;
},
// 更新比赛
update: async (id: number, data: UpdateContestForm): Promise<Contest> => {
const response = await request.patch<any, Contest>(`/contests/${id}`, data);
return response;
},
// 发布/撤回比赛
publish: async (
id: number,
contestState: "unpublished" | "published"
): Promise<Contest> => {
const response = await request.patch<any, Contest>(
`/contests/${id}/publish`,
{ contestState }
);
return response;
},
// 删除比赛
delete: async (id: number): Promise<void> => {
return await request.delete<any, void>(`/contests/${id}`);
},
2026-01-08 09:17:46 +08:00
// 标记比赛完结
finish: async (id: number): Promise<Contest> => {
const response = await request.patch<any, Contest>(`/contests/${id}/finish`);
return response;
},
// 重新开启已完结的比赛
reopen: async (id: number): Promise<Contest> => {
const response = await request.patch<any, Contest>(`/contests/${id}/reopen`);
return response;
},
2025-12-09 11:10:36 +08:00
};
// 附件管理
export const attachmentsApi = {
// 获取比赛附件列表
getList: async (contestId: number): Promise<ContestAttachment[]> => {
const response = await request.get<any, ContestAttachment[]>(
`/contests/attachments/contest/${contestId}`
);
return response;
},
// 创建附件
create: async (data: CreateAttachmentForm): Promise<ContestAttachment> => {
const response = await request.post<any, ContestAttachment>(
"/contests/attachments",
data
);
return response;
},
// 删除附件
delete: async (id: number): Promise<void> => {
return await request.delete<any, void>(`/contests/attachments/${id}`);
},
};
// 评审规则
2026-01-08 09:17:46 +08:00
export interface ReviewRule {
id: number;
tenantId: number;
ruleName: string;
ruleDescription?: string;
judgeCount: number;
dimensions: ReviewDimension[];
calculationRule: "average" | "remove_max_min" | "remove_min";
validState: number;
contests?: Array<{
id: number;
contestName: string;
}>;
createTime?: string;
modifyTime?: string;
}
// 用于选择器的简化评审规则
export interface ReviewRuleForSelect {
id: number;
ruleName: string;
ruleDescription?: string;
judgeCount: number;
calculationRule: string;
}
export interface QueryReviewRuleParams {
ruleName?: string;
page?: number;
pageSize?: number;
}
2025-12-09 11:10:36 +08:00
export const reviewRulesApi = {
2026-01-08 09:17:46 +08:00
// 获取评审规则列表
getList: async (params?: QueryReviewRuleParams): Promise<{
list: ReviewRule[];
total: number;
page: number;
pageSize: number;
}> => {
const response = await request.get<any, {
list: ReviewRule[];
total: number;
page: number;
pageSize: number;
}>("/contests/review-rules", { params });
return response;
},
// 获取所有可用的评审规则(用于赛事创建时选择)
getForSelect: async (): Promise<ReviewRuleForSelect[]> => {
const response = await request.get<any, ReviewRuleForSelect[]>(
"/contests/review-rules/select"
);
return response;
},
// 获取评审规则详情
getDetail: async (id: number): Promise<ReviewRule> => {
const response = await request.get<any, ReviewRule>(
`/contests/review-rules/${id}`
2025-12-09 11:10:36 +08:00
);
return response;
},
// 创建评审规则
2026-01-08 09:17:46 +08:00
create: async (data: CreateReviewRuleForm): Promise<ReviewRule> => {
const response = await request.post<any, ReviewRule>(
2025-12-09 11:10:36 +08:00
"/contests/review-rules",
data
);
return response;
},
// 更新评审规则
update: async (
2026-01-08 09:17:46 +08:00
id: number,
2025-12-09 11:10:36 +08:00
data: Partial<CreateReviewRuleForm>
2026-01-08 09:17:46 +08:00
): Promise<ReviewRule> => {
const response = await request.patch<any, ReviewRule>(
`/contests/review-rules/${id}`,
2025-12-09 11:10:36 +08:00
data
);
return response;
},
2026-01-08 09:17:46 +08:00
// 删除评审规则
delete: async (id: number): Promise<void> => {
await request.delete(`/contests/review-rules/${id}`);
},
2025-12-09 11:10:36 +08:00
};
// 报名管理
export const registrationsApi = {
// 获取报名列表
getList: async (
params: QueryRegistrationParams
): Promise<PaginationResponse<ContestRegistration>> => {
const response = await request.get<
any,
PaginationResponse<ContestRegistration>
>("/contests/registrations", { params });
return response;
},
// 获取报名详情
getDetail: async (id: number): Promise<ContestRegistration> => {
const response = await request.get<any, ContestRegistration>(
`/contests/registrations/${id}`
);
return response;
},
// 创建报名
create: async (
data: CreateRegistrationForm
): Promise<ContestRegistration> => {
const response = await request.post<any, ContestRegistration>(
"/contests/registrations",
data
);
return response;
},
// 审核报名
review: async (
id: number,
data: ReviewRegistrationForm
): Promise<ContestRegistration> => {
const response = await request.patch<any, ContestRegistration>(
`/contests/registrations/${id}/review`,
data
);
return response;
},
// 删除报名
delete: async (id: number): Promise<void> => {
return await request.delete<any, void>(`/contests/registrations/${id}`);
},
};
// 团队管理
export const teamsApi = {
// 获取团队列表
getList: async (contestId: number): Promise<ContestTeam[]> => {
const response = await request.get<any, ContestTeam[]>(
`/contests/teams/contest/${contestId}`
);
return response;
},
// 获取团队详情
getDetail: async (id: number): Promise<ContestTeam> => {
const response = await request.get<any, ContestTeam>(
`/contests/teams/${id}`
);
return response;
},
// 创建团队
create: async (data: CreateTeamForm): Promise<ContestTeam> => {
const response = await request.post<any, ContestTeam>(
"/contests/teams",
data
);
return response;
},
// 更新团队
update: async (
id: number,
data: Partial<CreateTeamForm>
): Promise<ContestTeam> => {
const response = await request.patch<any, ContestTeam>(
`/contests/teams/${id}`,
data
);
return response;
},
// 邀请成员
inviteMember: async (
teamId: number,
data: InviteMemberForm
): Promise<ContestTeamMember> => {
const response = await request.post<any, ContestTeamMember>(
`/contests/teams/${teamId}/members`,
data
);
return response;
},
// 移除成员
removeMember: async (teamId: number, userId: number): Promise<void> => {
return await request.delete<any, void>(
`/contests/teams/${teamId}/members/${userId}`
);
},
// 删除团队
delete: async (id: number): Promise<void> => {
return await request.delete<any, void>(`/contests/teams/${id}`);
},
};
// 作品管理
export const worksApi = {
// 获取作品列表
getList: async (
params: QueryWorkParams
): Promise<PaginationResponse<ContestWork>> => {
const response = await request.get<any, PaginationResponse<ContestWork>>(
"/contests/works",
{ params }
);
return response;
},
// 获取作品详情
getDetail: async (id: number): Promise<ContestWork> => {
const response = await request.get<any, ContestWork>(
`/contests/works/${id}`
);
return response;
},
// 提交作品
submit: async (data: SubmitWorkForm): Promise<ContestWork> => {
const response = await request.post<any, ContestWork>(
"/contests/works/submit",
data
);
return response;
},
// 获取作品版本列表
getVersions: async (registrationId: number): Promise<ContestWork[]> => {
const response = await request.get<any, ContestWork[]>(
`/contests/works/registration/${registrationId}/versions`
);
return response;
},
// 删除作品
delete: async (id: number): Promise<void> => {
return await request.delete<any, void>(`/contests/works/${id}`);
},
};
2026-01-08 09:17:46 +08:00
// ==================== 评审进度相关类型 ====================
export interface ReviewProgress {
contest: {
id: number;
contestName: string;
reviewStartTime: string;
reviewEndTime: string;
reviewRule: ContestReviewRule | null;
};
summary: {
totalWorks: number;
assignedWorksCount: number;
scoredWorksCount: number;
unassignedWorksCount: number;
totalJudges: number;
totalAssignments: number;
totalScores: number;
pendingScoresCount: number;
};
progress: {
assignmentProgress: number;
scoringProgress: number;
overallProgress: number;
};
judgeProgress: JudgeProgressItem[];
unassignedWorks: UnassignedWork[];
pendingAssignments: PendingAssignment[];
}
export interface JudgeProgressItem {
judgeId: number;
judgeName: string;
specialty: string | null;
weight: number | null;
assignedCount: number;
scoredCount: number;
pendingCount: number;
progress: number;
}
export interface UnassignedWork {
id: number;
workNo: string | null;
title: string;
createTime: string;
registration: {
user: { id: number; nickname: string; username: string } | null;
team: { id: number; teamName: string } | null;
} | null;
}
export interface PendingAssignment {
id: number;
workId: number;
workNo: string | null;
workTitle: string;
judgeId: number;
judgeName: string;
status: string;
assignmentTime: string;
}
export interface WorkStatusStats {
submitted: number;
reviewing: number;
reviewed: number;
awarded: number;
total: number;
}
export interface BatchAssignForm {
workIds: number[];
judgeIds: number[];
}
export interface BatchAssignResult {
created: number;
skipped: number;
assignments: ContestWorkJudgeAssignment[];
}
export interface AutoAssignResult {
message: string;
worksCount?: number;
created: number;
judgesPerWork?: number;
}
2025-12-09 11:10:36 +08:00
// 评审管理
export const reviewsApi = {
// 分配作品给评委
assignWork: async (
contestId: number,
data: AssignWorkForm
): Promise<ContestWorkJudgeAssignment[]> => {
const response = await request.post<any, ContestWorkJudgeAssignment[]>(
`/contests/reviews/assign?contestId=${contestId}`,
data
);
return response;
},
2026-01-08 09:17:46 +08:00
// 批量分配作品给评委
batchAssignWorks: async (
contestId: number,
data: BatchAssignForm
): Promise<BatchAssignResult> => {
const response = await request.post<any, BatchAssignResult>(
`/contests/reviews/batch-assign?contestId=${contestId}`,
data
);
return response;
},
// 自动分配作品给评委
autoAssignWorks: async (contestId: number): Promise<AutoAssignResult> => {
const response = await request.post<any, AutoAssignResult>(
`/contests/reviews/auto-assign?contestId=${contestId}`
);
return response;
},
2025-12-09 11:10:36 +08:00
// 评分
score: async (data: CreateScoreForm): Promise<ContestWorkScore> => {
const response = await request.post<any, ContestWorkScore>(
"/contests/reviews/score",
data
);
return response;
},
// 更新评分
updateScore: async (
scoreId: number,
data: Partial<CreateScoreForm>
): Promise<ContestWorkScore> => {
const response = await request.patch<any, ContestWorkScore>(
`/contests/reviews/score/${scoreId}`,
data
);
return response;
},
// 获取分配给当前评委的作品
getAssignedWorks: async (
contestId: number
): Promise<ContestWorkJudgeAssignment[]> => {
const response = await request.get<any, ContestWorkJudgeAssignment[]>(
`/contests/reviews/assigned?contestId=${contestId}`
);
return response;
},
2026-01-08 09:17:46 +08:00
// 获取评审进度统计
getReviewProgress: async (contestId: number): Promise<ReviewProgress> => {
const response = await request.get<any, ReviewProgress>(
`/contests/reviews/progress/${contestId}`
);
return response;
},
// 获取作品状态统计
getWorkStatusStats: async (contestId: number): Promise<WorkStatusStats> => {
const response = await request.get<any, WorkStatusStats>(
`/contests/reviews/work-status/${contestId}`
);
return response;
},
2025-12-09 11:10:36 +08:00
// 获取作品评分列表
getWorkScores: async (workId: number): Promise<ContestWorkScore[]> => {
const response = await request.get<any, ContestWorkScore[]>(
`/contests/reviews/work/${workId}/scores`
);
return response;
},
// 计算最终得分
calculateFinalScore: async (
workId: number
): Promise<{
finalScore: number;
scoreCount: number;
calculationRule: string;
}> => {
const response = await request.get<
any,
{ finalScore: number; scoreCount: number; calculationRule: string }
>(`/contests/reviews/work/${workId}/final-score`);
return response;
},
};
// 公告管理
export const noticesApi = {
2026-01-08 09:17:46 +08:00
// 获取公告列表(按赛事)
2025-12-09 11:10:36 +08:00
getList: async (contestId: number): Promise<ContestNotice[]> => {
const response = await request.get<any, ContestNotice[]>(
`/contests/notices/contest/${contestId}`
);
return response;
},
2026-01-08 09:17:46 +08:00
// 获取所有公告(支持搜索和分页)
getAll: async (params?: {
title?: string;
publishDate?: string;
page?: number;
pageSize?: number;
}): Promise<PaginationResponse<ContestNotice>> => {
const response = await request.get<any, PaginationResponse<ContestNotice>>(
'/contests/notices',
{ params }
);
return response;
},
2025-12-09 11:10:36 +08:00
// 获取公告详情
getDetail: async (id: number): Promise<ContestNotice> => {
const response = await request.get<any, ContestNotice>(
`/contests/notices/${id}`
);
return response;
},
// 创建公告
create: async (data: CreateNoticeForm): Promise<ContestNotice> => {
const response = await request.post<any, ContestNotice>(
"/contests/notices",
data
);
return response;
},
// 更新公告
update: async (
id: number,
data: Partial<CreateNoticeForm>
): Promise<ContestNotice> => {
const response = await request.patch<any, ContestNotice>(
`/contests/notices/${id}`,
data
);
return response;
},
// 删除公告
delete: async (id: number): Promise<void> => {
return await request.delete<any, void>(`/contests/notices/${id}`);
},
};
2026-01-08 09:17:46 +08:00
// ==================== 赛果相关类型 ====================
export interface ContestResult {
id: number;
workNo: string | null;
title: string;
finalScore: number | null;
rank: number | null;
awardLevel: string | null;
awardName: string | null;
certificateUrl: string | null;
registration: {
user: { id: number; username: string; nickname: string } | null;
team: { id: number; teamName: string } | null;
} | null;
}
export interface ResultsResponse {
contest: {
id: number;
contestName: string;
resultState: string;
resultPublishTime: string | null;
reviewRule: ContestReviewRule | null;
};
list: ContestResult[];
total: number;
page: number;
pageSize: number;
awardDistribution: Record<string, number>;
}
export interface ResultsSummary {
contest: {
id: number;
contestName: string;
resultState: string;
resultPublishTime: string | null;
};
summary: {
totalWorks: number;
scoredWorks: number;
rankedWorks: number;
awardedWorks: number;
unscoredWorks: number;
};
awardDistribution: Record<string, number>;
scoreStats: {
avgScore: string | null;
maxScore: string | null;
minScore: string | null;
};
}
export interface SetAwardForm {
awardLevel: 'first' | 'second' | 'third' | 'excellent' | 'none';
awardName?: string;
certificateUrl?: string;
}
export interface BatchSetAwardsForm {
awards: Array<{
workId: number;
awardLevel: 'first' | 'second' | 'third' | 'excellent' | 'none';
awardName?: string;
}>;
}
export interface AutoSetAwardsForm {
first?: number;
second?: number;
third?: number;
excellent?: number;
}
// 赛果管理
export const resultsApi = {
// 计算所有作品的最终得分
calculateScores: async (contestId: number): Promise<{ message: string; calculatedCount: number; calculationRule: string }> => {
const response = await request.post<any, any>(
`/contests/results/${contestId}/calculate-scores`
);
return response;
},
// 计算排名
calculateRankings: async (contestId: number): Promise<{ message: string; rankedCount: number }> => {
const response = await request.post<any, any>(
`/contests/results/${contestId}/calculate-rankings`
);
return response;
},
// 设置单个作品奖项
setAward: async (workId: number, data: SetAwardForm): Promise<ContestResult> => {
const response = await request.patch<any, ContestResult>(
`/contests/results/work/${workId}/award`,
data
);
return response;
},
// 批量设置奖项
batchSetAwards: async (contestId: number, data: BatchSetAwardsForm): Promise<any> => {
const response = await request.post<any, any>(
`/contests/results/${contestId}/batch-set-awards`,
data
);
return response;
},
// 根据排名自动设置奖项
autoSetAwards: async (contestId: number, data: AutoSetAwardsForm): Promise<any> => {
const response = await request.post<any, any>(
`/contests/results/${contestId}/auto-set-awards`,
data
);
return response;
},
// 发布赛果
publish: async (contestId: number): Promise<any> => {
const response = await request.post<any, any>(
`/contests/results/${contestId}/publish`
);
return response;
},
// 撤回发布
unpublish: async (contestId: number): Promise<any> => {
const response = await request.post<any, any>(
`/contests/results/${contestId}/unpublish`
);
return response;
},
// 获取比赛结果列表
getResults: async (contestId: number, page = 1, pageSize = 20): Promise<ResultsResponse> => {
const response = await request.get<any, ResultsResponse>(
`/contests/results/${contestId}`,
{ params: { page, pageSize } }
);
return response;
},
// 获取比赛结果统计摘要
getSummary: async (contestId: number): Promise<ResultsSummary> => {
const response = await request.get<any, ResultsSummary>(
`/contests/results/${contestId}/summary`
);
return response;
},
};
2025-12-09 11:10:36 +08:00
// 评委管理
export const judgesApi = {
// 获取评委列表
getList: async (contestId: number): Promise<ContestJudge[]> => {
const response = await request.get<any, ContestJudge[]>(
`/contests/judges/contest/${contestId}`
);
return response;
},
// 获取评委详情
getDetail: async (id: number): Promise<ContestJudge> => {
const response = await request.get<any, ContestJudge>(
`/contests/judges/${id}`
);
return response;
},
// 添加评委
create: async (data: CreateJudgeForm): Promise<ContestJudge> => {
const response = await request.post<any, ContestJudge>(
"/contests/judges",
data
);
return response;
},
// 更新评委
update: async (
id: number,
data: Partial<CreateJudgeForm>
): Promise<ContestJudge> => {
const response = await request.patch<any, ContestJudge>(
`/contests/judges/${id}`,
data
);
return response;
},
// 删除评委
delete: async (id: number): Promise<void> => {
return await request.delete<any, void>(`/contests/judges/${id}`);
},
};