From ab69968bda8462e19d5f853d06fd8f2739a1fc55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=85=E6=88=BF?= Date: Wed, 3 Dec 2025 13:51:22 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=89=8D=E7=AB=AF=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .claude/settings.local.json | 3 +- src/api/martial/activity.js | 211 ++ src/api/martial/activitySchedule.js | 291 +++ src/api/martial/deduction.js | 138 ++ src/api/martial/deductionItem.js | 118 ++ src/api/martial/exception.js | 262 +++ src/api/martial/export.js | 287 +++ src/api/martial/info.js | 221 +++ src/api/martial/infoPublish.js | 259 +++ src/api/martial/judgeInvite.js | 213 ++ src/api/martial/judgeProject.js | 248 +++ src/api/martial/live.js | 203 ++ src/api/martial/liveUpdate.js | 221 +++ src/api/martial/project.js | 138 ++ src/api/martial/result.js | 234 +++ src/api/martial/scheduleAthlete.js | 239 +++ src/api/martial/schedulePlan.js | 196 ++ src/api/martial/score.js | 91 + .../martial/CompetitionSelector.vue | 186 ++ src/components/martial/MedalDialog.vue | 330 ++++ src/components/martial/ProjectSelector.vue | 186 ++ src/components/martial/ScoreInput.vue | 268 +++ src/router/views/index.js | 114 +- src/views/martial/activity/index.vue | 1249 ++++++++++++ src/views/martial/banner/index.vue | 2 +- src/views/martial/competition/index.vue | 1130 +++++++---- src/views/martial/competition/list.vue | 499 ++++- src/views/martial/deduction/index.vue | 698 +++++++ src/views/martial/dispatch/index.vue | 2 +- src/views/martial/exception/index.vue | Bin 0 -> 34562 bytes src/views/martial/export/index.vue | 698 +++++++ src/views/martial/info/index.vue | 1194 ++++++++++++ src/views/martial/judgeInvite/index.vue | Bin 0 -> 31762 bytes src/views/martial/judgeProject/index.vue | 1722 +++++++++++++++++ src/views/martial/live/index.vue | Bin 0 -> 27988 bytes src/views/martial/participant/index.vue | 1116 +++++++---- src/views/martial/participant/list.vue | 417 +++- src/views/martial/project/index.vue | 837 ++++++++ src/views/martial/registration/index.vue | 6 +- src/views/martial/result/index.vue | 786 ++++++++ src/views/martial/schedule/index.vue | 2 +- src/views/martial/scheduleAthlete/index.vue | 1231 ++++++++++++ src/views/martial/schedulePlan/index.vue | Bin 0 -> 41181 bytes vite.config.js | 10 +- 44 files changed, 15366 insertions(+), 890 deletions(-) create mode 100644 src/api/martial/activity.js create mode 100644 src/api/martial/activitySchedule.js create mode 100644 src/api/martial/deduction.js create mode 100644 src/api/martial/deductionItem.js create mode 100644 src/api/martial/exception.js create mode 100644 src/api/martial/export.js create mode 100644 src/api/martial/info.js create mode 100644 src/api/martial/infoPublish.js create mode 100644 src/api/martial/judgeInvite.js create mode 100644 src/api/martial/judgeProject.js create mode 100644 src/api/martial/live.js create mode 100644 src/api/martial/liveUpdate.js create mode 100644 src/api/martial/project.js create mode 100644 src/api/martial/result.js create mode 100644 src/api/martial/scheduleAthlete.js create mode 100644 src/api/martial/schedulePlan.js create mode 100644 src/components/martial/CompetitionSelector.vue create mode 100644 src/components/martial/MedalDialog.vue create mode 100644 src/components/martial/ProjectSelector.vue create mode 100644 src/components/martial/ScoreInput.vue create mode 100644 src/views/martial/activity/index.vue create mode 100644 src/views/martial/deduction/index.vue create mode 100644 src/views/martial/exception/index.vue create mode 100644 src/views/martial/export/index.vue create mode 100644 src/views/martial/info/index.vue create mode 100644 src/views/martial/judgeInvite/index.vue create mode 100644 src/views/martial/judgeProject/index.vue create mode 100644 src/views/martial/live/index.vue create mode 100644 src/views/martial/project/index.vue create mode 100644 src/views/martial/result/index.vue create mode 100644 src/views/martial/scheduleAthlete/index.vue create mode 100644 src/views/martial/schedulePlan/index.vue diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 2a6f195..d23611c 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -3,7 +3,8 @@ "allow": [ "Bash(dir:*)", "Bash(npm run build:*)", - "Bash(findstr:*)" + "Bash(findstr:*)", + "WebFetch(domain:www.cmiassn.org)" ], "deny": [], "ask": [] diff --git a/src/api/martial/activity.js b/src/api/martial/activity.js new file mode 100644 index 0000000..ea92ffc --- /dev/null +++ b/src/api/martial/activity.js @@ -0,0 +1,211 @@ +import request from '@/axios'; + +// ==================== 活动日程管理接口 ==================== + +/** + * 活动日程分页查询 + * @param {Number} current - 当前页,默认1 + * @param {Number} size - 每页条数,默认10 + * @param {Object} params - 查询参数 + * @param {Number} params.competitionId - 赛事ID + * @param {String} params.activityType - 活动类型(可选) + * @param {String} params.activityName - 活动名称(可选) + * @param {String} params.startDate - 开始日期(可选) + * @param {String} params.endDate - 结束日期(可选) + */ +export const getActivityScheduleList = (current, size, params) => { + return request({ + url: '/api/blade-martial/activity-schedule/list', + method: 'get', + params: { + current, + size, + ...params + } + }) +} + +/** + * 获取活动日程详情 + * @param {Number} id - 活动ID + */ +export const getActivityScheduleDetail = (id) => { + return request({ + url: '/api/blade-martial/activity-schedule/detail', + method: 'get', + params: { id } + }) +} + +/** + * 添加活动日程 + * @param {Object} data - 活动数据 + * @param {Number} data.competitionId - 赛事ID + * @param {String} data.activityType - 活动类型(opening_ceremony/closing_ceremony/competition/training/meeting/other) + * @param {String} data.activityName - 活动名称 + * @param {String} data.description - 活动描述 + * @param {String} data.startTime - 开始时间 + * @param {String} data.endTime - 结束时间 + * @param {String} data.location - 活动地点 + * @param {Number} data.venueId - 场地ID(可选) + * @param {String} data.organizer - 组织者 + * @param {String} data.participants - 参与人员(可选) + * @param {String} data.remarks - 备注(可选) + */ +export const addActivity = (data) => { + return request({ + url: '/api/blade-martial/activity-schedule/add', + method: 'post', + data + }) +} + +/** + * 修改活动日程 + * @param {Object} data - 活动数据 + */ +export const updateActivity = (data) => { + return request({ + url: '/api/blade-martial/activity-schedule/update', + method: 'post', + data + }) +} + +/** + * 删除活动日程 + * @param {String} ids - 活动ID,多个用逗号分隔 + */ +export const removeActivity = (ids) => { + return request({ + url: '/api/blade-martial/activity-schedule/remove', + method: 'post', + params: { ids } + }) +} + +/** + * 获取日历视图数据 + * @param {Number} competitionId - 赛事ID + * @param {String} month - 月份(格式: YYYY-MM) + */ +export const getActivityCalendar = (competitionId, month) => { + return request({ + url: '/api/blade-martial/activity-schedule/calendar', + method: 'get', + params: { competitionId, month } + }) +} + +/** + * 检查活动时间冲突 + * @param {Object} data - 活动数据 + * @param {Number} data.competitionId - 赛事ID + * @param {String} data.startTime - 开始时间 + * @param {String} data.endTime - 结束时间 + * @param {Number} data.venueId - 场地ID(可选) + * @param {Number} data.excludeId - 排除的活动ID(编辑时使用) + */ +export const checkActivityConflict = (data) => { + return request({ + url: '/api/blade-martial/activity-schedule/check-conflict', + method: 'post', + data + }) +} + +/** + * 复制活动 + * @param {Object} data - 复制数据 + * @param {Number} data.sourceId - 源活动ID + * @param {String} data.newStartTime - 新开始时间 + * @param {String} data.newEndTime - 新结束时间 + */ +export const copyActivity = (data) => { + return request({ + url: '/api/blade-martial/activity-schedule/copy', + method: 'post', + data + }) +} + +/** + * 按日期查询活动 + * @param {Number} competitionId - 赛事ID + * @param {String} date - 日期(格式: YYYY-MM-DD) + */ +export const getActivitiesByDate = (competitionId, date) => { + return request({ + url: '/api/blade-martial/activity-schedule/by-date', + method: 'get', + params: { competitionId, date } + }) +} + +/** + * 获取活动统计 + * @param {Number} competitionId - 赛事ID + */ +export const getActivityStatistics = (competitionId) => { + return request({ + url: '/api/blade-martial/activity-schedule/statistics', + method: 'get', + params: { competitionId } + }) +} + +/** + * 按类型统计活动 + * @param {Number} competitionId - 赛事ID + */ +export const getActivityByType = (competitionId) => { + return request({ + url: '/api/blade-martial/activity-schedule/statistics-by-type', + method: 'get', + params: { competitionId } + }) +} + +/** + * 导出活动日程 + * @param {Object} params - 导出参数 + */ +export const exportActivitySchedule = (params) => { + return request({ + url: '/api/blade-martial/activity-schedule/export', + method: 'get', + params, + responseType: 'blob' + }) +} + +/** + * 导入活动日程 + * @param {File} file - Excel文件 + * @param {Number} competitionId - 赛事ID + */ +export const importActivitySchedule = (file, competitionId) => { + const formData = new FormData() + formData.append('file', file) + formData.append('competitionId', competitionId) + return request({ + url: '/api/blade-martial/activity-schedule/import', + method: 'post', + data: formData, + headers: { + 'Content-Type': 'multipart/form-data' + } + }) +} + +/** + * 批量添加活动 + * @param {Array} data - 活动数据数组 + */ +export const batchAddActivities = (data) => { + return request({ + url: '/api/blade-martial/activity-schedule/batch-add', + method: 'post', + data + }) +} diff --git a/src/api/martial/activitySchedule.js b/src/api/martial/activitySchedule.js new file mode 100644 index 0000000..1a3cc4a --- /dev/null +++ b/src/api/martial/activitySchedule.js @@ -0,0 +1,291 @@ +import request from '@/axios'; + +// ==================== 武术赛事活动日程管理接口 ==================== + +/** + * 活动日程分页查询 + * @param {Number} current - 当前页,默认1 + * @param {Number} size - 每页条数,默认10 + * @param {Object} params - 查询参数 + * @param {Number} params.competitionId - 赛事ID + * @param {String} params.activityDate - 活动日期(可选) + * @param {Number} params.activityType - 活动类型(可选) + */ +export const getActivityScheduleList = (current, size, params) => { + return request({ + url: '/api/blade-martial/activitySchedule/list', + method: 'get', + params: { + current, + size, + ...params + } + }) +} + +/** + * 获取活动日程详情 + * @param {Number} id - 活动日程ID + */ +export const getActivityScheduleDetail = (id) => { + return request({ + url: '/api/blade-martial/activitySchedule/detail', + method: 'get', + params: { id } + }) +} + +/** + * 新增活动日程 + * @param {Object} data - 活动日程数据 + * @param {Number} data.competitionId - 赛事ID + * @param {String} data.activityDate - 活动日期 + * @param {String} data.startTime - 开始时间 + * @param {String} data.endTime - 结束时间 + * @param {Number} data.activityType - 活动类型(1开幕式2闭幕式3比赛4培训5会议6其他) + * @param {String} data.activityName - 活动名称 + * @param {String} data.activityLocation - 活动地点 + * @param {String} data.activityDescription - 活动描述 + * @param {String} data.organizer - 组织者 + * @param {String} data.participants - 参与人员 + * @param {Number} data.sortOrder - 排序序号 + */ +export const addActivity = (data) => { + return request({ + url: '/api/blade-martial/activitySchedule/save', + method: 'post', + data + }) +} + +/** + * 修改活动日程 + * @param {Object} data - 活动日程数据 + */ +export const updateActivity = (data) => { + return request({ + url: '/api/blade-martial/activitySchedule/update', + method: 'post', + data + }) +} + +/** + * 删除活动日程 + * @param {String} ids - 活动日程ID,多个用逗号分隔 + */ +export const removeActivity = (ids) => { + return request({ + url: '/api/blade-martial/activitySchedule/remove', + method: 'post', + params: { ids } + }) +} + +/** + * 批量添加活动日程 + * @param {Array} data - 活动日程数据数组 + */ +export const batchAddActivities = (data) => { + return request({ + url: '/api/blade-martial/activitySchedule/batch-save', + method: 'post', + data + }) +} + +/** + * 获取某日期的活动日程 + * @param {Number} competitionId - 赛事ID + * @param {String} activityDate - 活动日期 + */ +export const getActivitiesByDate = (competitionId, activityDate) => { + return request({ + url: '/api/blade-martial/activitySchedule/list-by-date', + method: 'get', + params: { competitionId, activityDate } + }) +} + +/** + * 获取日期范围内的活动日程 + * @param {Number} competitionId - 赛事ID + * @param {String} startDate - 开始日期 + * @param {String} endDate - 结束日期 + */ +export const getActivitiesByDateRange = (competitionId, startDate, endDate) => { + return request({ + url: '/api/blade-martial/activitySchedule/list-by-range', + method: 'get', + params: { competitionId, startDate, endDate } + }) +} + +/** + * 获取某类型的活动日程 + * @param {Number} competitionId - 赛事ID + * @param {Number} activityType - 活动类型 + */ +export const getActivitiesByType = (competitionId, activityType) => { + return request({ + url: '/api/blade-martial/activitySchedule/list-by-type', + method: 'get', + params: { competitionId, activityType } + }) +} + +/** + * 获取赛事的所有活动日程(不分页) + * @param {Number} competitionId - 赛事ID + */ +export const getAllActivities = (competitionId) => { + return request({ + url: '/api/blade-martial/activitySchedule/all', + method: 'get', + params: { competitionId } + }) +} + +/** + * 调整活动日程顺序 + * @param {Object} data - 调整参数 + * @param {Number} data.id - 活动日程ID + * @param {Number} data.targetOrder - 目标顺序 + */ +export const adjustActivityOrder = (data) => { + return request({ + url: '/api/blade-martial/activitySchedule/adjust-order', + method: 'post', + data + }) +} + +/** + * 检查活动时间冲突 + * @param {Object} data - 检查参数 + * @param {Number} data.competitionId - 赛事ID + * @param {String} data.activityDate - 活动日期 + * @param {String} data.startTime - 开始时间 + * @param {String} data.endTime - 结束时间 + * @param {String} data.activityLocation - 活动地点 + * @param {Number} data.excludeId - 排除的活动ID(编辑时使用) + */ +export const checkActivityConflict = (data) => { + return request({ + url: '/api/blade-martial/activitySchedule/check-conflict', + method: 'post', + data + }) +} + +/** + * 复制活动日程到其他日期 + * @param {Object} data - 复制参数 + * @param {Number} data.sourceActivityId - 源活动ID + * @param {String} data.targetDate - 目标日期 + */ +export const copyActivity = (data) => { + return request({ + url: '/api/blade-martial/activitySchedule/copy', + method: 'post', + data + }) +} + +/** + * 获取活动日程日历视图数据 + * @param {Number} competitionId - 赛事ID + * @param {String} month - 月份(格式:YYYY-MM) + */ +export const getActivityCalendar = (competitionId, month) => { + return request({ + url: '/api/blade-martial/activitySchedule/calendar', + method: 'get', + params: { competitionId, month } + }) +} + +/** + * 发布活动日程 + * @param {Number} id - 活动日程ID + */ +export const publishActivity = (id) => { + return request({ + url: '/api/blade-martial/activitySchedule/publish', + method: 'post', + params: { id } + }) +} + +/** + * 取消活动日程 + * @param {Number} id - 活动日程ID + * @param {String} cancelReason - 取消原因 + */ +export const cancelActivity = (id, cancelReason) => { + return request({ + url: '/api/blade-martial/activitySchedule/cancel', + method: 'post', + params: { id }, + data: { cancelReason } + }) +} + +/** + * 完成活动日程 + * @param {Number} id - 活动日程ID + * @param {String} completionNote - 完成备注 + */ +export const completeActivity = (id, completionNote) => { + return request({ + url: '/api/blade-martial/activitySchedule/complete', + method: 'post', + params: { id }, + data: { completionNote } + }) +} + +/** + * 导出活动日程 + * @param {Object} params - 导出参数 + */ +export const exportActivities = (params) => { + return request({ + url: '/api/blade-martial/activitySchedule/export', + method: 'get', + params, + responseType: 'blob' + }) +} + +/** + * 导入活动日程 + * @param {Number} competitionId - 赛事ID + * @param {File} file - Excel文件 + */ +export const importActivities = (competitionId, file) => { + const formData = new FormData() + formData.append('competitionId', competitionId) + formData.append('file', file) + return request({ + url: '/api/blade-martial/activitySchedule/import', + method: 'post', + data: formData, + headers: { + 'Content-Type': 'multipart/form-data' + } + }) +} + +/** + * 打印活动日程表 + * @param {Number} competitionId - 赛事ID + */ +export const printActivitySchedule = (competitionId) => { + return request({ + url: '/api/blade-martial/activitySchedule/print', + method: 'get', + params: { competitionId }, + responseType: 'blob' + }) +} diff --git a/src/api/martial/deduction.js b/src/api/martial/deduction.js new file mode 100644 index 0000000..9ac8456 --- /dev/null +++ b/src/api/martial/deduction.js @@ -0,0 +1,138 @@ +import request from '@/axios'; + +// ==================== 扣分项管理接口 ==================== + +/** + * 扣分项分页查询 + * @param {Number} current - 当前页,默认1 + * @param {Number} size - 每页条数,默认10 + * @param {Object} params - 查询参数 + * @param {Number} params.projectId - 项目ID + * @param {String} params.itemName - 扣分项名称(可选) + */ +export const getDeductionList = (current, size, params) => { + return request({ + url: '/api/blade-martial/deductionItem/list', + method: 'get', + params: { + current, + size, + ...params + } + }) +} + +/** + * 获取扣分项详情 + * @param {Number} id - 扣分项ID + */ +export const getDeductionDetail = (id) => { + return request({ + url: '/api/blade-martial/deductionItem/detail', + method: 'get', + params: { id } + }) +} + +/** + * 新增扣分项 + * @param {Object} data - 扣分项数据 + * @param {Number} data.projectId - 项目ID + * @param {String} data.itemName - 扣分项名称 + * @param {Number} data.deductionPoints - 扣分值 + * @param {String} data.description - 描述说明 + * @param {Number} data.sortOrder - 排序序号 + */ +export const addDeduction = (data) => { + return request({ + url: '/api/blade-martial/deductionItem/save', + method: 'post', + data + }) +} + +/** + * 修改扣分项 + * @param {Object} data - 扣分项数据 + */ +export const updateDeduction = (data) => { + return request({ + url: '/api/blade-martial/deductionItem/update', + method: 'post', + data + }) +} + +/** + * 删除扣分项 + * @param {String} ids - 扣分项ID,多个用逗号分隔 + */ +export const removeDeduction = (ids) => { + return request({ + url: '/api/blade-martial/deductionItem/remove', + method: 'post', + params: { ids } + }) +} + +/** + * 获取项目的扣分项列表(不分页) + * @param {Number} projectId - 项目ID + */ +export const getDeductionsByProject = (projectId) => { + return request({ + url: '/api/blade-martial/deductionItem/list-by-project', + method: 'get', + params: { projectId } + }) +} + +/** + * 克隆扣分项 + * @param {Object} data - 克隆数据 + * @param {Number} data.sourceProjectId - 源项目ID + * @param {Number} data.targetProjectId - 目标项目ID + */ +export const cloneDeductions = (data) => { + return request({ + url: '/api/blade-martial/deductionItem/clone', + method: 'post', + data + }) +} + +/** + * 更新扣分项排序 + * @param {Array} sortData - 排序数据数组 [{id, sortOrder}, ...] + */ +export const updateDeductionOrder = (sortData) => { + return request({ + url: '/api/blade-martial/deductionItem/update-order', + method: 'post', + data: sortData + }) +} + +/** + * 导出扣分项模板 + */ +export const exportDeductionTemplate = () => { + return request({ + url: '/api/blade-martial/deductionItem/export-template', + method: 'get', + responseType: 'blob' + }) +} + +/** + * 导出扣分项列表 + * @param {Object} params - 查询参数 + */ +export const exportDeductions = (params) => { + return request({ + url: '/api/blade-martial/deductionItem/export', + method: 'get', + params, + responseType: 'blob' + }) +} diff --git a/src/api/martial/deductionItem.js b/src/api/martial/deductionItem.js new file mode 100644 index 0000000..4d9c023 --- /dev/null +++ b/src/api/martial/deductionItem.js @@ -0,0 +1,118 @@ +import request from '@/axios'; + +// ==================== 武术赛事扣分项管理接口 ==================== + +/** + * 扣分项分页查询 + * @param {Number} current - 当前页,默认1 + * @param {Number} size - 每页条数,默认10 + * @param {Object} params - 查询参数 + * @param {Number} params.projectId - 项目ID + * @param {String} params.itemName - 扣分项名称(可选) + */ +export const getDeductionList = (current, size, params) => { + return request({ + url: '/api/blade-martial/deductionItem/list', + method: 'get', + params: { + current, + size, + ...params + } + }) +} + +/** + * 获取扣分项详情 + * @param {Number} id - 扣分项ID + */ +export const getDeductionDetail = (id) => { + return request({ + url: '/api/blade-martial/deductionItem/detail', + method: 'get', + params: { id } + }) +} + +/** + * 新增扣分项 + * @param {Object} data - 扣分项数据 + * @param {Number} data.projectId - 项目ID + * @param {String} data.itemName - 扣分项名称 + * @param {Number} data.deductionPoints - 扣分值 + * @param {String} data.description - 描述 + * @param {Number} data.sortOrder - 排序序号 + */ +export const addDeduction = (data) => { + return request({ + url: '/api/blade-martial/deductionItem/save', + method: 'post', + data + }) +} + +/** + * 修改扣分项 + * @param {Object} data - 扣分项数据 + */ +export const updateDeduction = (data) => { + return request({ + url: '/api/blade-martial/deductionItem/update', + method: 'post', + data + }) +} + +/** + * 删除扣分项 + * @param {String} ids - 扣分项ID,多个用逗号分隔 + */ +export const removeDeduction = (ids) => { + return request({ + url: '/api/blade-martial/deductionItem/remove', + method: 'post', + params: { ids } + }) +} + +/** + * 获取项目的扣分项列表(不分页) + * @param {Number} projectId - 项目ID + */ +export const getDeductionsByProject = (projectId) => { + return request({ + url: '/api/blade-martial/deductionItem/list-by-project', + method: 'get', + params: { projectId } + }) +} + +/** + * 批量导入扣分项 + * @param {Number} projectId - 项目ID + * @param {File} file - Excel文件 + */ +export const importDeductions = (projectId, file) => { + const formData = new FormData() + formData.append('projectId', projectId) + formData.append('file', file) + return request({ + url: '/api/blade-martial/deductionItem/import', + method: 'post', + data: formData, + headers: { + 'Content-Type': 'multipart/form-data' + } + }) +} + +/** + * 导出扣分项模板 + */ +export const exportDeductionTemplate = () => { + return request({ + url: '/api/blade-martial/deductionItem/export-template', + method: 'get', + responseType: 'blob' + }) +} diff --git a/src/api/martial/exception.js b/src/api/martial/exception.js new file mode 100644 index 0000000..6d06c08 --- /dev/null +++ b/src/api/martial/exception.js @@ -0,0 +1,262 @@ +import request from '@/axios'; + +// ==================== 武术赛事异常事件管理接口 ==================== + +/** + * 异常事件分页查询 + * @param {Number} current - 当前页,默认1 + * @param {Number} size - 每页条数,默认10 + * @param {Object} params - 查询参数 + * @param {Number} params.competitionId - 赛事ID + * @param {Number} params.exceptionType - 异常类型(可选) + * @param {Number} params.severity - 严重程度(可选) + * @param {Number} params.status - 处理状态(可选) + */ +export const getExceptionList = (current, size, params) => { + return request({ + url: '/api/blade-martial/exception/list', + method: 'get', + params: { + current, + size, + ...params + } + }) +} + +/** + * 获取异常事件详情 + * @param {Number} id - 异常事件ID + */ +export const getExceptionDetail = (id) => { + return request({ + url: '/api/blade-martial/exception/detail', + method: 'get', + params: { id } + }) +} + +/** + * 上报异常事件 + * @param {Object} data - 异常事件数据 + * @param {Number} data.competitionId - 赛事ID + * @param {Number} data.projectId - 项目ID(可选) + * @param {Number} data.venueId - 场地ID(可选) + * @param {Number} data.exceptionType - 异常类型(1设备故障2人员问题3时间冲突4评分异常5安全事故6其他) + * @param {Number} data.severity - 严重程度(1轻微2一般3严重4紧急) + * @param {String} data.title - 标题 + * @param {String} data.description - 描述 + * @param {String} data.reporterName - 上报人姓名 + * @param {String} data.reporterPhone - 上报人电话 + * @param {Array} data.images - 图片URL数组(可选) + */ +export const reportException = (data) => { + return request({ + url: '/api/blade-martial/exception/report', + method: 'post', + data + }) +} + +/** + * 修改异常事件 + * @param {Object} data - 异常事件数据 + */ +export const updateException = (data) => { + return request({ + url: '/api/blade-martial/exception/update', + method: 'post', + data + }) +} + +/** + * 删除异常事件 + * @param {String} ids - 异常事件ID,多个用逗号分隔 + */ +export const removeException = (ids) => { + return request({ + url: '/api/blade-martial/exception/remove', + method: 'post', + params: { ids } + }) +} + +/** + * 处理异常事件 + * @param {Object} data - 处理数据 + * @param {Number} data.id - 异常事件ID + * @param {String} data.handlerName - 处理人姓名 + * @param {String} data.handleResult - 处理结果 + * @param {String} data.handleNote - 处理备注 + */ +export const handleException = (data) => { + return request({ + url: '/api/blade-martial/exception/handle', + method: 'post', + data + }) +} + +/** + * 关闭异常事件 + * @param {Number} id - 异常事件ID + * @param {String} closeReason - 关闭原因 + */ +export const closeException = (id, closeReason) => { + return request({ + url: '/api/blade-martial/exception/close', + method: 'post', + params: { id }, + data: { closeReason } + }) +} + +/** + * 重新打开异常事件 + * @param {Number} id - 异常事件ID + * @param {String} reopenReason - 重开原因 + */ +export const reopenException = (id, reopenReason) => { + return request({ + url: '/api/blade-martial/exception/reopen', + method: 'post', + params: { id }, + data: { reopenReason } + }) +} + +/** + * 分配异常事件 + * @param {Object} data - 分配数据 + * @param {Number} data.id - 异常事件ID + * @param {String} data.assigneeName - 分配人姓名 + * @param {String} data.assigneePhone - 分配人电话 + */ +export const assignException = (data) => { + return request({ + url: '/api/blade-martial/exception/assign', + method: 'post', + data + }) +} + +/** + * 获取待处理异常事件列表 + * @param {Number} competitionId - 赛事ID + * @param {Number} severity - 严重程度(可选) + */ +export const getPendingExceptions = (competitionId, severity) => { + return request({ + url: '/api/blade-martial/exception/pending', + method: 'get', + params: { competitionId, severity } + }) +} + +/** + * 获取我的异常事件列表 + * @param {Number} competitionId - 赛事ID + * @param {String} assigneeName - 分配人姓名 + */ +export const getMyExceptions = (competitionId, assigneeName) => { + return request({ + url: '/api/blade-martial/exception/my-exceptions', + method: 'get', + params: { competitionId, assigneeName } + }) +} + +/** + * 获取异常事件统计 + * @param {Number} competitionId - 赛事ID + */ +export const getExceptionStatistics = (competitionId) => { + return request({ + url: '/api/blade-martial/exception/statistics', + method: 'get', + params: { competitionId } + }) +} + +/** + * 按类型统计异常事件 + * @param {Number} competitionId - 赛事ID + */ +export const getExceptionByType = (competitionId) => { + return request({ + url: '/api/blade-martial/exception/statistics-by-type', + method: 'get', + params: { competitionId } + }) +} + +/** + * 按严重程度统计异常事件 + * @param {Number} competitionId - 赛事ID + */ +export const getExceptionBySeverity = (competitionId) => { + return request({ + url: '/api/blade-martial/exception/statistics-by-severity', + method: 'get', + params: { competitionId } + }) +} + +/** + * 上传异常事件图片 + * @param {File} file - 图片文件 + */ +export const uploadExceptionImage = (file) => { + const formData = new FormData() + formData.append('file', file) + return request({ + url: '/api/blade-martial/exception/upload-image', + method: 'post', + data: formData, + headers: { + 'Content-Type': 'multipart/form-data' + } + }) +} + +/** + * 添加异常处理记录 + * @param {Object} data - 处理记录数据 + * @param {Number} data.exceptionId - 异常事件ID + * @param {String} data.operatorName - 操作人姓名 + * @param {String} data.operationType - 操作类型 + * @param {String} data.operationNote - 操作备注 + */ +export const addExceptionLog = (data) => { + return request({ + url: '/api/blade-martial/exception/add-log', + method: 'post', + data + }) +} + +/** + * 获取异常处理记录 + * @param {Number} exceptionId - 异常事件ID + */ +export const getExceptionLogs = (exceptionId) => { + return request({ + url: '/api/blade-martial/exception/logs', + method: 'get', + params: { exceptionId } + }) +} + +/** + * 导出异常事件报表 + * @param {Object} params - 导出参数 + */ +export const exportExceptions = (params) => { + return request({ + url: '/api/blade-martial/exception/export', + method: 'get', + params, + responseType: 'blob' + }) +} diff --git a/src/api/martial/export.js b/src/api/martial/export.js new file mode 100644 index 0000000..6f3e8f5 --- /dev/null +++ b/src/api/martial/export.js @@ -0,0 +1,287 @@ +import request from '@/axios'; + +// ==================== 武术赛事导出打印接口 ==================== + +/** + * 导出成绩单(Excel) + * @param {Object} params - 导出参数 + * @param {Number} params.competitionId - 赛事ID + * @param {Number} params.projectId - 项目ID(可选) + * @param {String} params.category - 分组类别(可选) + * @param {Boolean} params.includeRanking - 是否包含排名(默认true) + * @param {Boolean} params.includeMedal - 是否包含奖牌(默认true) + */ +export const exportResults = (params) => { + return request({ + url: '/api/blade-martial/export/results', + method: 'get', + params, + responseType: 'blob' + }) +} + +/** + * 导出运动员名单(Excel) + * @param {Object} params - 导出参数 + * @param {Number} params.competitionId - 赛事ID + * @param {Number} params.projectId - 项目ID(可选) + * @param {String} params.category - 分组类别(可选) + * @param {String} params.teamName - 团队名称(可选) + * @param {Number} params.status - 报名状态(可选) + */ +export const exportAthletes = (params) => { + return request({ + url: '/api/blade-martial/export/athletes', + method: 'get', + params, + responseType: 'blob' + }) +} + +/** + * 导出赛程表(Excel) + * @param {Object} params - 导出参数 + * @param {Number} params.competitionId - 赛事ID + * @param {Number} params.venueId - 场地ID(可选) + * @param {String} params.scheduleDate - 赛程日期(可选) + * @param {Number} params.projectId - 项目ID(可选) + */ +export const exportSchedule = (params) => { + return request({ + url: '/api/blade-martial/export/schedule', + method: 'get', + params, + responseType: 'blob' + }) +} + +/** + * 导出评分表(Excel) + * @param {Object} params - 导出参数 + * @param {Number} params.competitionId - 赛事ID + * @param {Number} params.projectId - 项目ID(可选) + * @param {Number} params.judgeId - 裁判ID(可选) + * @param {String} params.scoreDate - 评分日期(可选) + */ +export const exportScores = (params) => { + return request({ + url: '/api/blade-martial/export/scores', + method: 'get', + params, + responseType: 'blob' + }) +} + +/** + * 导出裁判名单(Excel) + * @param {Object} params - 导出参数 + * @param {Number} params.competitionId - 赛事ID + * @param {String} params.judgeLevel - 裁判等级(可选) + * @param {Number} params.projectId - 项目ID(可选) + */ +export const exportReferees = (params) => { + return request({ + url: '/api/blade-martial/export/referees', + method: 'get', + params, + responseType: 'blob' + }) +} + +/** + * 导出奖牌榜(Excel) + * @param {Object} params - 导出参数 + * @param {Number} params.competitionId - 赛事ID + * @param {String} params.groupBy - 分组方式(team/region) + */ +export const exportMedalRanking = (params) => { + return request({ + url: '/api/blade-martial/export/medal-ranking', + method: 'get', + params, + responseType: 'blob' + }) +} + +// ==================== 证书生成接口 ==================== + +/** + * 生成单个证书(HTML/PDF) + * @param {Number} resultId - 成绩ID + * @param {String} format - 格式(html/pdf)默认pdf + */ +export const generateCertificate = (resultId, format = 'pdf') => { + return request({ + url: `/api/blade-martial/export/certificate/${resultId}`, + method: 'get', + params: { format }, + responseType: format === 'pdf' ? 'blob' : 'json' + }) +} + +/** + * 批量生成证书 + * @param {Object} data - 生成参数 + * @param {Array} data.resultIds - 成绩ID数组 + * @param {Number} data.projectId - 项目ID(可选,为空时使用resultIds) + * @param {Number} data.competitionId - 赛事ID(可选,为空时使用resultIds) + * @param {String} data.format - 格式(html/pdf)默认pdf + * @param {Boolean} data.mergeFiles - 是否合并为一个文件(默认false) + */ +export const batchCertificates = (data) => { + return request({ + url: '/api/blade-martial/export/certificates/batch', + method: 'post', + data, + responseType: 'blob' + }) +} + +/** + * 获取证书数据(用于预览) + * @param {Number} resultId - 成绩ID + */ +export const getCertificateData = (resultId) => { + return request({ + url: `/api/blade-martial/export/certificate/data/${resultId}`, + method: 'get' + }) +} + +/** + * 获取证书模板列表 + * @param {Number} competitionId - 赛事ID(可选) + */ +export const getCertificateTemplates = (competitionId) => { + return request({ + url: '/api/blade-martial/export/certificate/templates', + method: 'get', + params: { competitionId } + }) +} + +/** + * 上传证书模板 + * @param {File} file - 模板文件 + * @param {String} templateName - 模板名称 + * @param {Number} competitionId - 赛事ID(可选) + */ +export const uploadCertificateTemplate = (file, templateName, competitionId) => { + const formData = new FormData() + formData.append('file', file) + formData.append('templateName', templateName) + if (competitionId) { + formData.append('competitionId', competitionId) + } + return request({ + url: '/api/blade-martial/export/certificate/template/upload', + method: 'post', + data: formData, + headers: { + 'Content-Type': 'multipart/form-data' + } + }) +} + +// ==================== 报表导出接口 ==================== + +/** + * 导出赛事统计报表 + * @param {Number} competitionId - 赛事ID + */ +export const exportCompetitionReport = (competitionId) => { + return request({ + url: '/api/blade-martial/export/competition-report', + method: 'get', + params: { competitionId }, + responseType: 'blob' + }) +} + +/** + * 导出项目统计报表 + * @param {Number} projectId - 项目ID + */ +export const exportProjectReport = (projectId) => { + return request({ + url: '/api/blade-martial/export/project-report', + method: 'get', + params: { projectId }, + responseType: 'blob' + }) +} + +/** + * 导出裁判工作量统计 + * @param {Object} params - 导出参数 + * @param {Number} params.competitionId - 赛事ID + * @param {String} params.startDate - 开始日期(可选) + * @param {String} params.endDate - 结束日期(可选) + */ +export const exportJudgeWorkload = (params) => { + return request({ + url: '/api/blade-martial/export/judge-workload', + method: 'get', + params, + responseType: 'blob' + }) +} + +/** + * 导出报名统计报表 + * @param {Number} competitionId - 赛事ID + */ +export const exportRegistrationReport = (competitionId) => { + return request({ + url: '/api/blade-martial/export/registration-report', + method: 'get', + params: { competitionId }, + responseType: 'blob' + }) +} + +// ==================== 打印接口 ==================== + +/** + * 打印签到表 + * @param {Object} params - 打印参数 + * @param {Number} params.competitionId - 赛事ID + * @param {Number} params.projectId - 项目ID(可选) + * @param {String} params.scheduleDate - 赛程日期(可选) + */ +export const printSignInSheet = (params) => { + return request({ + url: '/api/blade-martial/export/print/sign-in', + method: 'get', + params, + responseType: 'blob' + }) +} + +/** + * 打印秩序册 + * @param {Number} competitionId - 赛事ID + */ +export const printProgramBook = (competitionId) => { + return request({ + url: '/api/blade-martial/export/print/program-book', + method: 'get', + params: { competitionId }, + responseType: 'blob' + }) +} + +/** + * 打印成绩公告 + * @param {Object} params - 打印参数 + * @param {Number} params.projectId - 项目ID + * @param {Number} params.competitionId - 赛事ID + */ +export const printResultAnnouncement = (params) => { + return request({ + url: '/api/blade-martial/export/print/result-announcement', + method: 'get', + params, + responseType: 'blob' + }) +} diff --git a/src/api/martial/info.js b/src/api/martial/info.js new file mode 100644 index 0000000..c2fc4b9 --- /dev/null +++ b/src/api/martial/info.js @@ -0,0 +1,221 @@ +import request from '@/axios'; + +// ==================== o ==================== + +/** + * oh + * @param {Number} current - SMu ؤ1 + * @param {Number} size - up ؤ10 + * @param {Object} params - p + * @param {Number} params.competitionId - [ID + * @param {String} params.infoType - o{announcementlJ/notice/news/rules + * @param {String} params.title - !" + * @param {Number} params.publishStatus - 0/1/2 + * @param {Boolean} params.isTop - /&nv + * @param {Boolean} params.isImportant - /&́ + */ +export const getInfoPublishList = (current, size, params) => { + return request({ + url: '/api/blade-martial/info-publish/list', + method: 'get', + params: { + current, + size, + ...params + } + }) +} + +/** + * o + * @param {Number} id - oID + */ +export const getInfoPublishDetail = (id) => { + return request({ + url: '/api/blade-martial/info-publish/detail', + method: 'get', + params: { id } + }) +} + +/** + * o + * @param {Object} data - opn + * @param {Number} data.competitionId - [ID + * @param {String} data.infoType - o{ + * @param {String} data.title -  + * @param {String} data.coverImage - bURL + * @param {String} data.summary - X + * @param {String} data.content - ̇, + * @param {Array} data.attachments - DURLp + * @param {String} data.publishTime -  ks + * @param {Boolean} data.isTop - /&nv + * @param {Boolean} data.isImportant - /&́ + */ +export const publishInfo = (data) => { + return request({ + url: '/api/blade-martial/info-publish/publish', + method: 'post', + data + }) +} + +/** + * o + * @param {Object} data - opn + */ +export const updateInfoPublish = (data) => { + return request({ + url: '/api/blade-martial/info-publish/update', + method: 'post', + data + }) +} + +/** + * do + * @param {String} ids - oID *( + */ +export const removeInfoPublish = (ids) => { + return request({ + url: '/api/blade-martial/info-publish/remove', + method: 'post', + params: { ids } + }) +} + +/** + * bnv + * @param {Number} id - oID + * @param {Boolean} isTop - /&nv + */ +export const toggleTop = (id, isTop) => { + return request({ + url: '/api/blade-martial/info-publish/toggle-top', + method: 'post', + data: { id, isTop } + }) +} + +/** + * b́ + * @param {Number} id - oID + * @param {Boolean} isImportant - /&́ + */ +export const toggleImportant = (id, isImportant) => { + return request({ + url: '/api/blade-martial/info-publish/toggle-important', + method: 'post', + data: { id, isImportant } + }) +} + +/** + * + b + * @param {File} file - G + */ +export const uploadCoverImage = (file) => { + const formData = new FormData() + formData.append('file', file) + return request({ + url: '/api/blade-martial/info-publish/upload-cover', + method: 'post', + data: formData, + headers: { + 'Content-Type': 'multipart/form-data' + } + }) +} + +/** + * + D + * @param {File} file - D + * @param {Function} onProgress - + ۦ + */ +export const uploadAttachment = (file, onProgress) => { + const formData = new FormData() + formData.append('file', file) + return request({ + url: '/api/blade-martial/info-publish/upload-attachment', + method: 'post', + data: formData, + headers: { + 'Content-Type': 'multipart/form-data' + }, + onUploadProgress: onProgress + }) +} + +/** + * y + D + * @param {Array} files - Dp + */ +export const batchUploadAttachments = (files) => { + const formData = new FormData() + files.forEach(file => { + formData.append('files', file) + }) + return request({ + url: '/api/blade-martial/info-publish/batch-upload-attachments', + method: 'post', + data: formData, + headers: { + 'Content-Type': 'multipart/form-data' + } + }) +} + +/** + * +/ o + * @param {Number} id - oID + * @param {Number} publishStatus - 1/2 + */ +export const updatePublishStatus = (id, publishStatus) => { + return request({ + url: '/api/blade-martial/info-publish/update-status', + method: 'post', + data: { id, publishStatus } + }) +} + +/** + * oߡ + * @param {Number} competitionId - [ID + */ +export const getInfoStatistics = (competitionId) => { + return request({ + url: '/api/blade-martial/info-publish/statistics', + method: 'get', + params: { competitionId } + }) +} + +/** + *  + * @param {Number} id - oID + */ +export const incrementViewCount = (id) => { + return request({ + url: '/api/blade-martial/info-publish/increment-view', + method: 'post', + data: { id } + }) +} + +/** + * oU + * @param {Object} params - p + */ +export const exportInfoPublish = (params) => { + return request({ + url: '/api/blade-martial/info-publish/export', + method: 'get', + params, + responseType: 'blob' + }) +} diff --git a/src/api/martial/infoPublish.js b/src/api/martial/infoPublish.js new file mode 100644 index 0000000..933254f --- /dev/null +++ b/src/api/martial/infoPublish.js @@ -0,0 +1,259 @@ +import request from '@/axios'; + +// ==================== 武术赛事信息发布管理接口 ==================== + +/** + * 信息发布分页查询 + * @param {Number} current - 当前页,默认1 + * @param {Number} size - 每页条数,默认10 + * @param {Object} params - 查询参数 + * @param {Number} params.competitionId - 赛事ID + * @param {Number} params.infoType - 信息类型(可选) + * @param {Number} params.publishStatus - 发布状态(可选) + * @param {String} params.title - 标题(可选) + */ +export const getInfoPublishList = (current, size, params) => { + return request({ + url: '/api/blade-martial/infoPublish/list', + method: 'get', + params: { + current, + size, + ...params + } + }) +} + +/** + * 获取信息发布详情 + * @param {Number} id - 信息ID + */ +export const getInfoPublishDetail = (id) => { + return request({ + url: '/api/blade-martial/infoPublish/detail', + method: 'get', + params: { id } + }) +} + +/** + * 发布信息 + * @param {Object} data - 信息数据 + * @param {Number} data.competitionId - 赛事ID + * @param {Number} data.infoType - 信息类型(1公告2通知3新闻4规则5其他) + * @param {String} data.title - 标题 + * @param {String} data.content - 内容 + * @param {String} data.summary - 摘要(可选) + * @param {String} data.coverImage - 封面图片(可选) + * @param {Array} data.attachments - 附件URL数组(可选) + * @param {Number} data.isTop - 是否置顶(0否1是) + * @param {Number} data.isImportant - 是否重要(0否1是) + * @param {String} data.publishTime - 发布时间(可选,为空则立即发布) + */ +export const publishInfo = (data) => { + return request({ + url: '/api/blade-martial/infoPublish/publish', + method: 'post', + data + }) +} + +/** + * 修改信息 + * @param {Object} data - 信息数据 + */ +export const updateInfo = (data) => { + return request({ + url: '/api/blade-martial/infoPublish/update', + method: 'post', + data + }) +} + +/** + * 删除信息 + * @param {String} ids - 信息ID,多个用逗号分隔 + */ +export const removeInfo = (ids) => { + return request({ + url: '/api/blade-martial/infoPublish/remove', + method: 'post', + params: { ids } + }) +} + +/** + * 撤回信息 + * @param {Number} id - 信息ID + */ +export const withdrawInfo = (id) => { + return request({ + url: '/api/blade-martial/infoPublish/withdraw', + method: 'post', + params: { id } + }) +} + +/** + * 置顶/取消置顶信息 + * @param {Number} id - 信息ID + * @param {Number} isTop - 是否置顶(0否1是) + */ +export const toggleTop = (id, isTop) => { + return request({ + url: '/api/blade-martial/infoPublish/toggle-top', + method: 'post', + params: { id, isTop } + }) +} + +/** + * 设置/取消重要信息 + * @param {Number} id - 信息ID + * @param {Number} isImportant - 是否重要(0否1是) + */ +export const toggleImportant = (id, isImportant) => { + return request({ + url: '/api/blade-martial/infoPublish/toggle-important', + method: 'post', + params: { id, isImportant } + }) +} + +/** + * 获取已发布信息列表(不分页) + * @param {Number} competitionId - 赛事ID + * @param {Number} infoType - 信息类型(可选) + * @param {Number} limit - 获取数量(默认10) + */ +export const getPublishedInfoList = (competitionId, infoType, limit = 10) => { + return request({ + url: '/api/blade-martial/infoPublish/published', + method: 'get', + params: { competitionId, infoType, limit } + }) +} + +/** + * 获取置顶信息列表 + * @param {Number} competitionId - 赛事ID + */ +export const getTopInfoList = (competitionId) => { + return request({ + url: '/api/blade-martial/infoPublish/top-info', + method: 'get', + params: { competitionId } + }) +} + +/** + * 获取重要信息列表 + * @param {Number} competitionId - 赛事ID + */ +export const getImportantInfoList = (competitionId) => { + return request({ + url: '/api/blade-martial/infoPublish/important-info', + method: 'get', + params: { competitionId } + }) +} + +/** + * 搜索信息 + * @param {Object} params - 搜索参数 + * @param {Number} params.competitionId - 赛事ID + * @param {String} params.keyword - 关键词 + * @param {Number} params.infoType - 信息类型(可选) + * @param {String} params.startTime - 开始时间(可选) + * @param {String} params.endTime - 结束时间(可选) + */ +export const searchInfo = (params) => { + return request({ + url: '/api/blade-martial/infoPublish/search', + method: 'get', + params + }) +} + +/** + * 增加阅读量 + * @param {Number} id - 信息ID + */ +export const increaseViewCount = (id) => { + return request({ + url: '/api/blade-martial/infoPublish/view', + method: 'post', + params: { id } + }) +} + +/** + * 上传封面图片 + * @param {File} file - 图片文件 + */ +export const uploadCoverImage = (file) => { + const formData = new FormData() + formData.append('file', file) + return request({ + url: '/api/blade-martial/infoPublish/upload-cover', + method: 'post', + data: formData, + headers: { + 'Content-Type': 'multipart/form-data' + } + }) +} + +/** + * 上传附件 + * @param {File} file - 附件文件 + */ +export const uploadAttachment = (file) => { + const formData = new FormData() + formData.append('file', file) + return request({ + url: '/api/blade-martial/infoPublish/upload-attachment', + method: 'post', + data: formData, + headers: { + 'Content-Type': 'multipart/form-data' + } + }) +} + +/** + * 下载附件 + * @param {String} attachmentUrl - 附件URL + */ +export const downloadAttachment = (attachmentUrl) => { + return request({ + url: '/api/blade-martial/infoPublish/download', + method: 'get', + params: { attachmentUrl }, + responseType: 'blob' + }) +} + +/** + * 获取信息统计 + * @param {Number} competitionId - 赛事ID + */ +export const getInfoStatistics = (competitionId) => { + return request({ + url: '/api/blade-martial/infoPublish/statistics', + method: 'get', + params: { competitionId } + }) +} + +/** + * 批量发布信息 + * @param {Array} data - 信息数据数组 + */ +export const batchPublishInfo = (data) => { + return request({ + url: '/api/blade-martial/infoPublish/batch-publish', + method: 'post', + data + }) +} diff --git a/src/api/martial/judgeInvite.js b/src/api/martial/judgeInvite.js new file mode 100644 index 0000000..0b715fc --- /dev/null +++ b/src/api/martial/judgeInvite.js @@ -0,0 +1,213 @@ +import request from '@/axios'; + +// ==================== 武术赛事裁判邀请管理接口 ==================== + +/** + * 裁判邀请分页查询 + * @param {Number} current - 当前页,默认1 + * @param {Number} size - 每页条数,默认10 + * @param {Object} params - 查询参数 + * @param {Number} params.competitionId - 赛事ID + * @param {String} params.judgeName - 裁判姓名(可选) + * @param {String} params.judgeLevel - 裁判等级(可选) + * @param {Number} params.inviteStatus - 邀请状态(可选) + */ +export const getJudgeInviteList = (current, size, params) => { + return request({ + url: '/api/blade-martial/judgeInvite/list', + method: 'get', + params: { + current, + size, + ...params + } + }) +} + +/** + * 获取裁判邀请详情 + * @param {Number} id - 邀请ID + */ +export const getJudgeInviteDetail = (id) => { + return request({ + url: '/api/blade-martial/judgeInvite/detail', + method: 'get', + params: { id } + }) +} + +/** + * 发送邀请 + * @param {Object} data - 邀请数据 + * @param {Number} data.competitionId - 赛事ID + * @param {String} data.judgeName - 裁判姓名 + * @param {String} data.judgeLevel - 裁判等级 + * @param {String} data.contactPhone - 联系电话 + * @param {String} data.contactEmail - 联系邮箱 + * @param {String} data.inviteMessage - 邀请信息(可选) + */ +export const sendInvite = (data) => { + return request({ + url: '/api/blade-martial/judgeInvite/send', + method: 'post', + data + }) +} + +/** + * 修改邀请 + * @param {Object} data - 邀请数据 + */ +export const updateInvite = (data) => { + return request({ + url: '/api/blade-martial/judgeInvite/update', + method: 'post', + data + }) +} + +/** + * 删除邀请 + * @param {String} ids - 邀请ID,多个用逗号分隔 + */ +export const removeInvite = (ids) => { + return request({ + url: '/api/blade-martial/judgeInvite/remove', + method: 'post', + params: { ids } + }) +} + +/** + * 批量发送邀请 + * @param {Object} data - 批量邀请参数 + * @param {Number} data.competitionId - 赛事ID + * @param {Array} data.judges - 裁判信息数组 + * @param {String} data.inviteMessage - 邀请信息(可选) + */ +export const batchSendInvites = (data) => { + return request({ + url: '/api/blade-martial/judgeInvite/batch-send', + method: 'post', + data + }) +} + +/** + * 重新发送邀请 + * @param {Number} id - 邀请ID + */ +export const resendInvite = (id) => { + return request({ + url: '/api/blade-martial/judgeInvite/resend', + method: 'post', + params: { id } + }) +} + +/** + * 裁判回复邀请 + * @param {Object} data - 回复数据 + * @param {Number} data.inviteId - 邀请ID + * @param {String} data.inviteToken - 邀请令牌 + * @param {Number} data.replyStatus - 回复状态(1接受2拒绝) + * @param {String} data.replyNote - 回复备注 + */ +export const replyInvite = (data) => { + return request({ + url: '/api/blade-martial/judgeInvite/reply', + method: 'post', + data + }) +} + +/** + * 取消邀请 + * @param {Number} id - 邀请ID + * @param {String} cancelReason - 取消原因 + */ +export const cancelInvite = (id, cancelReason) => { + return request({ + url: '/api/blade-martial/judgeInvite/cancel', + method: 'post', + params: { id }, + data: { cancelReason } + }) +} + +/** + * 确认邀请 + * @param {Number} id - 邀请ID + */ +export const confirmInvite = (id) => { + return request({ + url: '/api/blade-martial/judgeInvite/confirm', + method: 'post', + params: { id } + }) +} + +/** + * 获取邀请统计 + * @param {Number} competitionId - 赛事ID + */ +export const getInviteStatistics = (competitionId) => { + return request({ + url: '/api/blade-martial/judgeInvite/statistics', + method: 'get', + params: { competitionId } + }) +} + +/** + * 获取已接受邀请的裁判列表 + * @param {Number} competitionId - 赛事ID + */ +export const getAcceptedJudges = (competitionId) => { + return request({ + url: '/api/blade-martial/judgeInvite/accepted-judges', + method: 'get', + params: { competitionId } + }) +} + +/** + * 从裁判库导入 + * @param {Object} data - 导入参数 + * @param {Number} data.competitionId - 赛事ID + * @param {Array} data.judgeIds - 裁判ID数组(从裁判库选择) + */ +export const importFromJudgePool = (data) => { + return request({ + url: '/api/blade-martial/judgeInvite/import-from-pool', + method: 'post', + data + }) +} + +/** + * 导出邀请名单 + * @param {Object} params - 导出参数 + */ +export const exportInvites = (params) => { + return request({ + url: '/api/blade-martial/judgeInvite/export', + method: 'get', + params, + responseType: 'blob' + }) +} + +/** + * 发送提醒消息 + * @param {Number} id - 邀请ID + * @param {String} reminderMessage - 提醒消息 + */ +export const sendReminder = (id, reminderMessage) => { + return request({ + url: '/api/blade-martial/judgeInvite/send-reminder', + method: 'post', + params: { id }, + data: { reminderMessage } + }) +} diff --git a/src/api/martial/judgeProject.js b/src/api/martial/judgeProject.js new file mode 100644 index 0000000..3729380 --- /dev/null +++ b/src/api/martial/judgeProject.js @@ -0,0 +1,248 @@ +import request from '@/axios'; + +// ==================== 武术赛事裁判-项目关联管理接口 ==================== + +/** + * 裁判-项目关联分页查询 + * @param {Number} current - 当前页,默认1 + * @param {Number} size - 每页条数,默认10 + * @param {Object} params - 查询参数 + * @param {Number} params.competitionId - 赛事ID + * @param {Number} params.judgeId - 裁判ID(可选) + * @param {Number} params.projectId - 项目ID(可选) + * @param {String} params.role - 角色(可选) + */ +export const getJudgeProjectList = (current, size, params) => { + return request({ + url: '/api/blade-martial/judge-project/list', + method: 'get', + params: { + current, + size, + ...params + } + }) +} + +/** + * 获取裁判-项目关联详情 + * @param {Number} id - 关联ID + */ +export const getJudgeProjectDetail = (id) => { + return request({ + url: '/api/blade-martial/judge-project/detail', + method: 'get', + params: { id } + }) +} + +/** + * 分配裁判到项目 + * @param {Object} data - 分配数据 + * @param {Number} data.competitionId - 赛事ID + * @param {Number} data.judgeId - 裁判ID + * @param {String} data.judgeName - 裁判姓名 + * @param {Number} data.projectId - 项目ID + * @param {String} data.projectName - 项目名称 + * @param {String} data.role - 角色(主裁、副裁、执裁) + */ +export const assignJudge = (data) => { + return request({ + url: '/api/blade-martial/judge-project/assign', + method: 'post', + data + }) +} + +/** + * 修改分配 + * @param {Object} data - 分配数据 + */ +export const updateAssignment = (data) => { + return request({ + url: '/api/blade-martial/judge-project/update', + method: 'post', + data + }) +} + +/** + * 删除分配 + * @param {String} ids - 关联ID,多个用逗号分隔 + */ +export const removeAssignment = (ids) => { + return request({ + url: '/api/blade-martial/judge-project/remove', + method: 'post', + params: { ids } + }) +} + +/** + * 批量分配裁判 + * @param {Object} data - 批量分配参数 + * @param {Number} data.competitionId - 赛事ID + * @param {Array} data.assignments - 分配信息数组 + * @param {Number} data.assignments[].judgeId - 裁判ID + * @param {Number} data.assignments[].projectId - 项目ID + * @param {String} data.assignments[].role - 角色 + */ +export const batchAssignJudges = (data) => { + return request({ + url: '/api/blade-martial/judge-project/batch-assign', + method: 'post', + data + }) +} + +/** + * 自动分配裁判 + * @param {Object} data - 自动分配参数 + * @param {Number} data.competitionId - 赛事ID + * @param {Number} data.projectId - 项目ID(可选) + * @param {String} data.strategy - 分配策略(balance负载均衡/level按等级) + */ +export const autoAssignJudges = (data) => { + return request({ + url: '/api/blade-martial/judge-project/auto-assign', + method: 'post', + data + }) +} + +/** + * 获取项目的裁判列表 + * @param {Number} projectId - 项目ID + */ +export const getJudgesByProject = (projectId) => { + return request({ + url: '/api/blade-martial/judge-project/judges-by-project', + method: 'get', + params: { projectId } + }) +} + +/** + * 获取裁判的项目列表 + * @param {Number} judgeId - 裁判ID + * @param {Number} competitionId - 赛事ID + */ +export const getProjectsByJudge = (judgeId, competitionId) => { + return request({ + url: '/api/blade-martial/judge-project/projects-by-judge', + method: 'get', + params: { judgeId, competitionId } + }) +} + +/** + * 获取裁判工作量统计 + * @param {Number} competitionId - 赛事ID + */ +export const getJudgeWorkload = (competitionId) => { + return request({ + url: '/api/blade-martial/judge-project/workload', + method: 'get', + params: { competitionId } + }) +} + +/** + * 检查裁判冲突 + * @param {Object} data - 检查参数 + * @param {Number} data.judgeId - 裁判ID + * @param {Number} data.projectId - 项目ID + * @param {Number} data.competitionId - 赛事ID + */ +export const checkJudgeConflict = (data) => { + return request({ + url: '/api/blade-martial/judge-project/check-conflict', + method: 'post', + data + }) +} + +/** + * 交换两个裁判的项目分配 + * @param {Object} data - 交换参数 + * @param {Number} data.assignmentId1 - 分配1的ID + * @param {Number} data.assignmentId2 - 分配2的ID + */ +export const swapJudgeAssignment = (data) => { + return request({ + url: '/api/blade-martial/judge-project/swap', + method: 'post', + data + }) +} + +/** + * 复制分配到其他项目 + * @param {Object} data - 复制参数 + * @param {Number} data.sourceProjectId - 源项目ID + * @param {Number} data.targetProjectId - 目标项目ID + */ +export const copyAssignment = (data) => { + return request({ + url: '/api/blade-martial/judge-project/copy', + method: 'post', + data + }) +} + +/** + * 获取可分配的裁判列表 + * @param {Number} competitionId - 赛事ID + * @param {Number} projectId - 项目ID(可选) + */ +export const getAvailableJudges = (competitionId, projectId) => { + return request({ + url: '/api/blade-martial/judge-project/available-judges', + method: 'get', + params: { competitionId, projectId } + }) +} + +/** + * 获取未分配裁判的项目列表 + * @param {Number} competitionId - 赛事ID + */ +export const getUnassignedProjects = (competitionId) => { + return request({ + url: '/api/blade-martial/judge-project/unassigned-projects', + method: 'get', + params: { competitionId } + }) +} + +/** + * 导出裁判分配表 + * @param {Object} params - 导出参数 + */ +export const exportAssignments = (params) => { + return request({ + url: '/api/blade-martial/judge-project/export', + method: 'get', + params, + responseType: 'blob' + }) +} + +/** + * 导入裁判分配 + * @param {Number} competitionId - 赛事ID + * @param {File} file - Excel文件 + */ +export const importAssignments = (competitionId, file) => { + const formData = new FormData() + formData.append('competitionId', competitionId) + formData.append('file', file) + return request({ + url: '/api/blade-martial/judge-project/import', + method: 'post', + data: formData, + headers: { + 'Content-Type': 'multipart/form-data' + } + }) +} diff --git a/src/api/martial/live.js b/src/api/martial/live.js new file mode 100644 index 0000000..a109414 --- /dev/null +++ b/src/api/martial/live.js @@ -0,0 +1,203 @@ +import request from '@/axios'; + +// ==================== f/[ ==================== + +/** + * u + * @param {Number} current - SMu,ؤ1 + * @param {Number} size - uap,ؤ10 + * @param {Object} params - p + * @param {Number} params.competitionId - [ID + * @param {String} params.updateType - {match[/result/notice + * @param {Number} params.projectId - yID + * @param {Number} params.venueId - :0ID + */ +export const getLiveUpdateList = (current, size, params) => { + return request({ + url: '/api/blade-martial/live-update/list', + method: 'get', + params: { + current, + size, + ...params + } + }) +} + +/** + * + * @param {Number} id - ID + */ +export const getLiveUpdateDetail = (id) => { + return request({ + url: '/api/blade-martial/live-update/detail', + method: 'get', + params: { id } + }) +} + +/** + *  + * @param {Object} data - pn + * @param {Number} data.competitionId - [ID + * @param {String} data.title -  + * @param {String} data.content - ̇, + * @param {String} data.updateType - { + * @param {Number} data.projectId - yID + * @param {Number} data.venueId - :0ID + * @param {Array} data.images - GURLp + * @param {Array} data.videos - ƑURLp + * @param {Boolean} data.isTop - /&nv + */ +export const publishLiveUpdate = (data) => { + return request({ + url: '/api/blade-martial/live-update/publish', + method: 'post', + data + }) +} + +/** + * 9 + * @param {Object} data - pn + */ +export const updateLiveUpdate = (data) => { + return request({ + url: '/api/blade-martial/live-update/update', + method: 'post', + data + }) +} + +/** + * d + * @param {String} ids - ID,*( + */ +export const removeLiveUpdate = (ids) => { + return request({ + url: '/api/blade-martial/live-update/remove', + method: 'post', + params: { ids } + }) +} + +/** + * bnv + * @param {Number} id - ID + * @param {Boolean} isTop - /&nv + */ +export const toggleTop = (id, isTop) => { + return request({ + url: '/api/blade-martial/live-update/toggle-top', + method: 'post', + data: { id, isTop } + }) +} + +/** + * + G + * @param {File} file - G + */ +export const uploadLiveImage = (file) => { + const formData = new FormData() + formData.append('file', file) + return request({ + url: '/api/blade-martial/live-update/upload-image', + method: 'post', + data: formData, + headers: { + 'Content-Type': 'multipart/form-data' + } + }) +} + +/** + * + Ƒ + * @param {File} file - Ƒ + * @param {Function} onProgress - + ۦ + */ +export const uploadLiveVideo = (file, onProgress) => { + const formData = new FormData() + formData.append('file', file) + return request({ + url: '/api/blade-martial/live-update/upload-video', + method: 'post', + data: formData, + headers: { + 'Content-Type': 'multipart/form-data' + }, + onUploadProgress: onProgress + }) +} + +/** + * y + G + * @param {Array} files - Gp + */ +export const batchUploadImages = (files) => { + const formData = new FormData() + files.forEach(file => { + formData.append('files', file) + }) + return request({ + url: '/api/blade-martial/live-update/batch-upload-images', + method: 'post', + data: formData, + headers: { + 'Content-Type': 'multipart/form-data' + } + }) +} + +/** + * ߡpn + * @param {Number} competitionId - [ID + */ +export const getLiveStatistics = (competitionId) => { + return request({ + url: '/api/blade-martial/live-update/statistics', + method: 'get', + params: { competitionId } + }) +} + +/** + * ^ + * @param {Number} id - ID + */ +export const likeLiveUpdate = (id) => { + return request({ + url: '/api/blade-martial/live-update/like', + method: 'post', + data: { id } + }) +} + +/** + * ֈ^ + * @param {Number} id - ID + */ +export const unlikeLiveUpdate = (id) => { + return request({ + url: '/api/blade-martial/live-update/unlike', + method: 'post', + data: { id } + }) +} + +/** + * + * @param {Number} competitionId - [ID + * @param {Number} limit - pP6 + */ +export const getHotLiveUpdates = (competitionId, limit = 10) => { + return request({ + url: '/api/blade-martial/live-update/hot', + method: 'get', + params: { competitionId, limit } + }) +} diff --git a/src/api/martial/liveUpdate.js b/src/api/martial/liveUpdate.js new file mode 100644 index 0000000..acc7d09 --- /dev/null +++ b/src/api/martial/liveUpdate.js @@ -0,0 +1,221 @@ +import request from '@/axios'; + +// ==================== 武术赛事直播更新管理接口 ==================== + +/** + * 直播更新分页查询 + * @param {Number} current - 当前页,默认1 + * @param {Number} size - 每页条数,默认10 + * @param {Object} params - 查询参数 + * @param {Number} params.competitionId - 赛事ID + * @param {Number} params.projectId - 项目ID(可选) + * @param {Number} params.venueId - 场地ID(可选) + * @param {Number} params.updateType - 更新类型(可选) + */ +export const getLiveUpdateList = (current, size, params) => { + return request({ + url: '/api/blade-martial/liveUpdate/list', + method: 'get', + params: { + current, + size, + ...params + } + }) +} + +/** + * 获取直播更新详情 + * @param {Number} id - 更新ID + */ +export const getLiveUpdateDetail = (id) => { + return request({ + url: '/api/blade-martial/liveUpdate/detail', + method: 'get', + params: { id } + }) +} + +/** + * 发布直播更新 + * @param {Object} data - 更新数据 + * @param {Number} data.competitionId - 赛事ID + * @param {Number} data.projectId - 项目ID(可选) + * @param {Number} data.venueId - 场地ID(可选) + * @param {Number} data.updateType - 更新类型(1赛况2成绩3通知4其他) + * @param {String} data.title - 标题 + * @param {String} data.content - 内容 + * @param {Array} data.images - 图片URL数组(可选) + * @param {String} data.videoUrl - 视频URL(可选) + * @param {Number} data.isTop - 是否置顶(0否1是) + */ +export const publishLiveUpdate = (data) => { + return request({ + url: '/api/blade-martial/liveUpdate/publish', + method: 'post', + data + }) +} + +/** + * 修改直播更新 + * @param {Object} data - 更新数据 + */ +export const updateLiveUpdate = (data) => { + return request({ + url: '/api/blade-martial/liveUpdate/update', + method: 'post', + data + }) +} + +/** + * 删除直播更新 + * @param {String} ids - 更新ID,多个用逗号分隔 + */ +export const removeLiveUpdate = (ids) => { + return request({ + url: '/api/blade-martial/liveUpdate/remove', + method: 'post', + params: { ids } + }) +} + +/** + * 批量发布直播更新 + * @param {Array} data - 更新数据数组 + */ +export const batchPublishLiveUpdates = (data) => { + return request({ + url: '/api/blade-martial/liveUpdate/batch-publish', + method: 'post', + data + }) +} + +/** + * 置顶/取消置顶直播更新 + * @param {Number} id - 更新ID + * @param {Number} isTop - 是否置顶(0否1是) + */ +export const toggleTop = (id, isTop) => { + return request({ + url: '/api/blade-martial/liveUpdate/toggle-top', + method: 'post', + params: { id, isTop } + }) +} + +/** + * 获取最新直播更新列表(不分页) + * @param {Number} competitionId - 赛事ID + * @param {Number} limit - 获取数量(默认10) + */ +export const getLatestUpdates = (competitionId, limit = 10) => { + return request({ + url: '/api/blade-martial/liveUpdate/latest', + method: 'get', + params: { competitionId, limit } + }) +} + +/** + * 获取置顶直播更新列表 + * @param {Number} competitionId - 赛事ID + */ +export const getTopUpdates = (competitionId) => { + return request({ + url: '/api/blade-martial/liveUpdate/top-updates', + method: 'get', + params: { competitionId } + }) +} + +/** + * 获取项目的直播更新 + * @param {Number} projectId - 项目ID + * @param {Number} limit - 获取数量(默认20) + */ +export const getProjectUpdates = (projectId, limit = 20) => { + return request({ + url: '/api/blade-martial/liveUpdate/project-updates', + method: 'get', + params: { projectId, limit } + }) +} + +/** + * 获取场地的直播更新 + * @param {Number} venueId - 场地ID + * @param {Number} limit - 获取数量(默认20) + */ +export const getVenueUpdates = (venueId, limit = 20) => { + return request({ + url: '/api/blade-martial/liveUpdate/venue-updates', + method: 'get', + params: { venueId, limit } + }) +} + +/** + * 搜索直播更新 + * @param {Object} params - 搜索参数 + * @param {Number} params.competitionId - 赛事ID + * @param {String} params.keyword - 关键词 + * @param {Number} params.updateType - 更新类型(可选) + * @param {String} params.startTime - 开始时间(可选) + * @param {String} params.endTime - 结束时间(可选) + */ +export const searchLiveUpdates = (params) => { + return request({ + url: '/api/blade-martial/liveUpdate/search', + method: 'get', + params + }) +} + +/** + * 上传直播图片 + * @param {File} file - 图片文件 + */ +export const uploadLiveImage = (file) => { + const formData = new FormData() + formData.append('file', file) + return request({ + url: '/api/blade-martial/liveUpdate/upload-image', + method: 'post', + data: formData, + headers: { + 'Content-Type': 'multipart/form-data' + } + }) +} + +/** + * 上传直播视频 + * @param {File} file - 视频文件 + */ +export const uploadLiveVideo = (file) => { + const formData = new FormData() + formData.append('file', file) + return request({ + url: '/api/blade-martial/liveUpdate/upload-video', + method: 'post', + data: formData, + headers: { + 'Content-Type': 'multipart/form-data' + } + }) +} + +/** + * 获取直播统计 + * @param {Number} competitionId - 赛事ID + */ +export const getLiveStatistics = (competitionId) => { + return request({ + url: '/api/blade-martial/liveUpdate/statistics', + method: 'get', + params: { competitionId } + }) +} diff --git a/src/api/martial/project.js b/src/api/martial/project.js new file mode 100644 index 0000000..b3d6c11 --- /dev/null +++ b/src/api/martial/project.js @@ -0,0 +1,138 @@ +import request from '@/axios'; + +// ==================== 武术赛事项目管理接口 ==================== + +/** + * 项目分页查询 + * @param {Number} current - 当前页,默认1 + * @param {Number} size - 每页条数,默认10 + * @param {Object} params - 查询参数 + * @param {Number} params.competitionId - 赛事ID + * @param {String} params.projectName - 项目名称(可选) + * @param {String} params.category - 分组类别(可选) + * @param {String} params.eventType - 项目类型(可选) + */ +export const getProjectList = (current, size, params) => { + return request({ + url: '/api/blade-martial/project/list', + method: 'get', + params: { + current, + size, + ...params + } + }) +} + +/** + * 获取项目详情 + * @param {Number} id - 项目ID + */ +export const getProjectDetail = (id) => { + return request({ + url: '/api/blade-martial/project/detail', + method: 'get', + params: { id } + }) +} + +/** + * 新增项目 + * @param {Object} data - 项目数据 + * @param {Number} data.competitionId - 赛事ID + * @param {String} data.projectName - 项目名称 + * @param {String} data.projectCode - 项目编码 + * @param {String} data.category - 分组类别(男子、女子、团体) + * @param {String} data.eventType - 项目类型(套路、散打等) + * @param {Number} data.registrationFee - 报名费 + * @param {String} data.registrationStartTime - 报名开始时间 + * @param {String} data.registrationEndTime - 报名结束时间 + * @param {Number} data.maxParticipants - 最大参赛人数 + * @param {String} data.rules - 比赛规则 + */ +export const addProject = (data) => { + return request({ + url: '/api/blade-martial/project/save', + method: 'post', + data + }) +} + +/** + * 修改项目 + * @param {Object} data - 项目数据 + */ +export const updateProject = (data) => { + return request({ + url: '/api/blade-martial/project/update', + method: 'post', + data + }) +} + +/** + * 删除项目 + * @param {String} ids - 项目ID,多个用逗号分隔 + */ +export const removeProject = (ids) => { + return request({ + url: '/api/blade-martial/project/remove', + method: 'post', + params: { ids } + }) +} + +/** + * 获取赛事的项目列表(不分页) + * @param {Number} competitionId - 赛事ID + */ +export const getProjectsByCompetition = (competitionId) => { + return request({ + url: '/api/blade-martial/project/list-by-competition', + method: 'get', + params: { competitionId } + }) +} + +/** + * 批量导入项目 + * @param {Number} competitionId - 赛事ID + * @param {File} file - Excel文件 + */ +export const importProjects = (competitionId, file) => { + const formData = new FormData() + formData.append('competitionId', competitionId) + formData.append('file', file) + return request({ + url: '/api/blade-martial/project/import', + method: 'post', + data: formData, + headers: { + 'Content-Type': 'multipart/form-data' + } + }) +} + +/** + * 导出项目模板 + */ +export const exportProjectTemplate = () => { + return request({ + url: '/api/blade-martial/project/export-template', + method: 'get', + responseType: 'blob' + }) +} + +/** + * 导出项目列表 + * @param {Object} params - 查询参数 + */ +export const exportProjects = (params) => { + return request({ + url: '/api/blade-martial/project/export', + method: 'get', + params, + responseType: 'blob' + }) +} diff --git a/src/api/martial/result.js b/src/api/martial/result.js new file mode 100644 index 0000000..5d98fa4 --- /dev/null +++ b/src/api/martial/result.js @@ -0,0 +1,234 @@ +import request from '@/axios'; + +// ==================== 武术赛事成绩管理接口 ==================== + +/** + * 成绩分页查询 + * @param {Number} current - 当前页,默认1 + * @param {Number} size - 每页条数,默认10 + * @param {Object} params - 查询参数 + * @param {Number} params.competitionId - 赛事ID + * @param {Number} params.projectId - 项目ID(可选) + * @param {Number} params.athleteId - 运动员ID(可选) + * @param {String} params.playerName - 运动员姓名(可选) + * @param {String} params.teamName - 团队名称(可选) + * @param {Number} params.isFinal - 是否最终成绩(可选) + */ +export const getResultList = (current, size, params) => { + return request({ + url: '/api/blade-martial/result/list', + method: 'get', + params: { + current, + size, + ...params + } + }) +} + +/** + * 获取成绩详情 + * @param {Number} id - 成绩ID + */ +export const getResultDetail = (id) => { + return request({ + url: '/api/blade-martial/result/detail', + method: 'get', + params: { id } + }) +} + +/** + * 新增成绩 + * @param {Object} data - 成绩数据 + * @param {Number} data.competitionId - 赛事ID + * @param {Number} data.athleteId - 运动员ID + * @param {Number} data.projectId - 项目ID + * @param {Number} data.venueId - 场地ID + * @param {String} data.playerName - 运动员姓名 + * @param {String} data.teamName - 团队名称 + * @param {Number} data.totalScore - 总分 + * @param {Number} data.difficultyCoefficient - 难度系数 + * @param {Number} data.finalScore - 最终成绩 + */ +export const addResult = (data) => { + return request({ + url: '/api/blade-martial/result/save', + method: 'post', + data + }) +} + +/** + * 修改成绩 + * @param {Object} data - 成绩数据 + */ +export const updateResult = (data) => { + return request({ + url: '/api/blade-martial/result/update', + method: 'post', + data + }) +} + +/** + * 删除成绩 + * @param {String} ids - 成绩ID,多个用逗号分隔 + */ +export const removeResult = (ids) => { + return request({ + url: '/api/blade-martial/result/remove', + method: 'post', + params: { ids } + }) +} + +// ==================== 成绩高级功能接口 ==================== + +/** + * 计算成绩 + * @param {Object} data - 计算参数 + * @param {Number} data.athleteId - 运动员ID + * @param {Number} data.projectId - 项目ID + * @param {Number} data.competitionId - 赛事ID + * @param {Boolean} data.autoRanking - 是否自动排名(可选) + */ +export const calculateResult = (data) => { + return request({ + url: '/api/blade-martial/result/calculate', + method: 'post', + data + }) +} + +/** + * 批量计算成绩 + * @param {Object} data - 计算参数 + * @param {Number} data.projectId - 项目ID + * @param {Number} data.competitionId - 赛事ID + * @param {Array} data.athleteIds - 运动员ID数组(可选,为空时计算所有) + */ +export const batchCalculateResults = (data) => { + return request({ + url: '/api/blade-martial/result/batch-calculate', + method: 'post', + data + }) +} + +/** + * 自动排名 + * @param {Object} data - 排名参数 + * @param {Number} data.projectId - 项目ID + * @param {Number} data.competitionId - 赛事ID + * @param {String} data.category - 分组类别(可选) + */ +export const autoRanking = (data) => { + return request({ + url: '/api/blade-martial/result/ranking', + method: 'post', + data + }) +} + +/** + * 分配奖牌 + * @param {Object} data - 奖牌分配参数 + * @param {Number} data.projectId - 项目ID + * @param {Number} data.competitionId - 赛事ID + * @param {Number} data.goldCount - 金牌数量 + * @param {Number} data.silverCount - 银牌数量 + * @param {Number} data.bronzeCount - 铜牌数量 + */ +export const allocateMedals = (data) => { + return request({ + url: '/api/blade-martial/result/medals', + method: 'post', + data + }) +} + +/** + * 成绩复核 + * @param {Object} data - 复核参数 + * @param {Number} data.resultId - 成绩ID + * @param {String} data.reviewNote - 复核说明 + * @param {Number} data.reviewStatus - 复核状态(1通过2驳回) + */ +export const reviewResult = (data) => { + return request({ + url: '/api/blade-martial/result/review', + method: 'post', + data + }) +} + +/** + * 发布成绩 + * @param {Object} data - 发布参数 + * @param {Number} data.projectId - 项目ID(可选) + * @param {Number} data.competitionId - 赛事ID + * @param {Array} data.resultIds - 成绩ID数组(可选) + * @param {Boolean} data.publishAll - 是否发布全部(可选) + */ +export const publishResult = (data) => { + return request({ + url: '/api/blade-martial/result/publish', + method: 'post', + data + }) +} + +/** + * 撤销发布成绩 + * @param {Object} data - 撤销参数 + * @param {Number} data.projectId - 项目ID(可选) + * @param {Number} data.competitionId - 赛事ID + * @param {Array} data.resultIds - 成绩ID数组(可选) + */ +export const unpublishResult = (data) => { + return request({ + url: '/api/blade-martial/result/unpublish', + method: 'post', + data + }) +} + +/** + * 获取项目成绩统计 + * @param {Number} projectId - 项目ID + * @param {Number} competitionId - 赛事ID + */ +export const getResultStatistics = (projectId, competitionId) => { + return request({ + url: '/api/blade-martial/result/statistics', + method: 'get', + params: { projectId, competitionId } + }) +} + +/** + * 获取奖牌榜 + * @param {Number} competitionId - 赛事ID + * @param {String} groupBy - 分组方式(team团队/region地区) + */ +export const getMedalRanking = (competitionId, groupBy = 'team') => { + return request({ + url: '/api/blade-martial/result/medal-ranking', + method: 'get', + params: { competitionId, groupBy } + }) +} + +/** + * 导出成绩单 + * @param {Object} params - 查询参数 + */ +export const exportResults = (params) => { + return request({ + url: '/api/blade-martial/result/export', + method: 'get', + params, + responseType: 'blob' + }) +} diff --git a/src/api/martial/scheduleAthlete.js b/src/api/martial/scheduleAthlete.js new file mode 100644 index 0000000..a26bde2 --- /dev/null +++ b/src/api/martial/scheduleAthlete.js @@ -0,0 +1,239 @@ +import request from '@/axios'; + +// ==================== 武术赛事赛程选手关联管理接口 ==================== + +/** + * 赛程选手关联分页查询 + * @param {Number} current - 当前页,默认1 + * @param {Number} size - 每页条数,默认10 + * @param {Object} params - 查询参数 + * @param {Number} params.scheduleId - 赛程ID + * @param {Number} params.schedulePlanId - 赛程计划ID(可选) + * @param {Number} params.athleteId - 运动员ID(可选) + * @param {Number} params.status - 状态(可选) + */ +export const getScheduleAthleteList = (current, size, params) => { + return request({ + url: '/api/blade-martial/scheduleAthlete/list', + method: 'get', + params: { + current, + size, + ...params + } + }) +} + +/** + * 获取赛程选手关联详情 + * @param {Number} id - 关联ID + */ +export const getScheduleAthleteDetail = (id) => { + return request({ + url: '/api/blade-martial/scheduleAthlete/detail', + method: 'get', + params: { id } + }) +} + +/** + * 新增赛程选手关联 + * @param {Object} data - 关联数据 + * @param {Number} data.scheduleId - 赛程ID + * @param {Number} data.schedulePlanId - 赛程计划ID + * @param {Number} data.athleteId - 运动员ID + * @param {String} data.athleteName - 运动员姓名 + * @param {Number} data.competitionOrder - 出场顺序 + * @param {Number} data.status - 状态(0待出场1进行中2已完成) + */ +export const addScheduleAthlete = (data) => { + return request({ + url: '/api/blade-martial/scheduleAthlete/save', + method: 'post', + data + }) +} + +/** + * 修改赛程选手关联 + * @param {Object} data - 关联数据 + */ +export const updateScheduleAthlete = (data) => { + return request({ + url: '/api/blade-martial/scheduleAthlete/update', + method: 'post', + data + }) +} + +/** + * 删除赛程选手关联 + * @param {String} ids - 关联ID,多个用逗号分隔 + */ +export const removeScheduleAthlete = (ids) => { + return request({ + url: '/api/blade-martial/scheduleAthlete/remove', + method: 'post', + params: { ids } + }) +} + +/** + * 批量添加赛程选手 + * @param {Object} data - 批量添加参数 + * @param {Number} data.schedulePlanId - 赛程计划ID + * @param {Array} data.athleteIds - 运动员ID数组 + * @param {Boolean} data.autoOrder - 是否自动排序(默认true) + */ +export const batchAddScheduleAthletes = (data) => { + return request({ + url: '/api/blade-martial/scheduleAthlete/batch-save', + method: 'post', + data + }) +} + +/** + * 自动分配选手到赛程 + * @param {Object} data - 分配参数 + * @param {Number} data.scheduleId - 赛程ID + * @param {Number} data.projectId - 项目ID + * @param {String} data.allocateStrategy - 分配策略(random随机/order顺序) + */ +export const autoAllocateAthletes = (data) => { + return request({ + url: '/api/blade-martial/scheduleAthlete/auto-allocate', + method: 'post', + data + }) +} + +/** + * 调整选手出场顺序 + * @param {Object} data - 调整参数 + * @param {Number} data.id - 关联ID + * @param {Number} data.targetOrder - 目标顺序 + */ +export const adjustAthleteOrder = (data) => { + return request({ + url: '/api/blade-martial/scheduleAthlete/adjust-order', + method: 'post', + data + }) +} + +/** + * 交换两个选手的出场顺序 + * @param {Object} data - 交换参数 + * @param {Number} data.athleteId1 - 选手1的关联ID + * @param {Number} data.athleteId2 - 选手2的关联ID + */ +export const swapAthleteOrder = (data) => { + return request({ + url: '/api/blade-martial/scheduleAthlete/swap-order', + method: 'post', + data + }) +} + +/** + * 随机排序选手出场顺序 + * @param {Number} schedulePlanId - 赛程计划ID + */ +export const randomizeAthleteOrder = (schedulePlanId) => { + return request({ + url: '/api/blade-martial/scheduleAthlete/randomize', + method: 'post', + params: { schedulePlanId } + }) +} + +/** + * 更新选手状态 + * @param {Object} data - 状态更新参数 + * @param {Number} data.id - 关联ID + * @param {Number} data.status - 状态(0待出场1进行中2已完成) + */ +export const updateAthleteStatus = (data) => { + return request({ + url: '/api/blade-martial/scheduleAthlete/update-status', + method: 'post', + data + }) +} + +/** + * 获取赛程计划的选手列表(不分页) + * @param {Number} schedulePlanId - 赛程计划ID + */ +export const getAthletesBySchedulePlan = (schedulePlanId) => { + return request({ + url: '/api/blade-martial/scheduleAthlete/list-by-plan', + method: 'get', + params: { schedulePlanId } + }) +} + +/** + * 获取运动员的赛程安排 + * @param {Number} athleteId - 运动员ID + * @param {Number} competitionId - 赛事ID + */ +export const getAthleteSchedules = (athleteId, competitionId) => { + return request({ + url: '/api/blade-martial/scheduleAthlete/athlete-schedules', + method: 'get', + params: { athleteId, competitionId } + }) +} + +/** + * 检查选手时间冲突 + * @param {Object} data - 检查参数 + * @param {Number} data.athleteId - 运动员ID + * @param {Number} data.schedulePlanId - 赛程计划ID + */ +export const checkAthleteConflict = (data) => { + return request({ + url: '/api/blade-martial/scheduleAthlete/check-conflict', + method: 'post', + data + }) +} + +/** + * 签到选手 + * @param {Number} id - 关联ID + */ +export const checkInAthlete = (id) => { + return request({ + url: '/api/blade-martial/scheduleAthlete/check-in', + method: 'post', + params: { id } + }) +} + +/** + * 批量签到选手 + * @param {Array} ids - 关联ID数组 + */ +export const batchCheckInAthletes = (ids) => { + return request({ + url: '/api/blade-martial/scheduleAthlete/batch-check-in', + method: 'post', + data: ids + }) +} + +/** + * 导出赛程选手名单 + * @param {Object} params - 导出参数 + */ +export const exportScheduleAthletes = (params) => { + return request({ + url: '/api/blade-martial/scheduleAthlete/export', + method: 'get', + params, + responseType: 'blob' + }) +} diff --git a/src/api/martial/schedulePlan.js b/src/api/martial/schedulePlan.js new file mode 100644 index 0000000..83f3fc2 --- /dev/null +++ b/src/api/martial/schedulePlan.js @@ -0,0 +1,196 @@ +import request from '@/axios'; + +// ==================== 武术赛事赛程计划管理接口 ==================== + +/** + * 赛程计划分页查询 + * @param {Number} current - 当前页,默认1 + * @param {Number} size - 每页条数,默认10 + * @param {Object} params - 查询参数 + * @param {Number} params.scheduleId - 赛程ID + * @param {Number} params.venueId - 场地ID(可选) + * @param {Number} params.projectId - 项目ID(可选) + * @param {String} params.planDate - 计划日期(可选) + */ +export const getSchedulePlanList = (current, size, params) => { + return request({ + url: '/api/blade-martial/schedule-plan/list', + method: 'get', + params: { + current, + size, + ...params + } + }) +} + +/** + * 获取赛程计划详情 + * @param {Number} id - 赛程计划ID + */ +export const getSchedulePlanDetail = (id) => { + return request({ + url: '/api/blade-martial/schedule-plan/detail', + method: 'get', + params: { id } + }) +} + +/** + * 新增赛程计划 + * @param {Object} data - 赛程计划数据 + * @param {Number} data.scheduleId - 赛程ID + * @param {String} data.planDate - 计划日期 + * @param {String} data.startTime - 开始时间 + * @param {String} data.endTime - 结束时间 + * @param {Number} data.venueId - 场地ID + * @param {String} data.venueName - 场地名称 + * @param {Number} data.projectId - 项目ID + * @param {String} data.projectName - 项目名称 + * @param {Number} data.planOrder - 计划顺序 + */ +export const addSchedulePlan = (data) => { + return request({ + url: '/api/blade-martial/schedule-plan/save', + method: 'post', + data + }) +} + +/** + * 修改赛程计划 + * @param {Object} data - 赛程计划数据 + */ +export const updateSchedulePlan = (data) => { + return request({ + url: '/api/blade-martial/schedule-plan/update', + method: 'post', + data + }) +} + +/** + * 删除赛程计划 + * @param {String} ids - 赛程计划ID,多个用逗号分隔 + */ +export const removeSchedulePlan = (ids) => { + return request({ + url: '/api/blade-martial/schedule-plan/remove', + method: 'post', + params: { ids } + }) +} + +/** + * 批量添加赛程计划 + * @param {Array} data - 赛程计划数据数组 + */ +export const batchAddSchedulePlans = (data) => { + return request({ + url: '/api/blade-martial/schedule-plan/batch-save', + method: 'post', + data + }) +} + +/** + * 自动编排赛程 + * @param {Object} data - 编排参数 + * @param {Number} data.scheduleId - 赛程ID + * @param {Number} data.competitionId - 赛事ID + * @param {String} data.startDate - 开始日期 + * @param {String} data.endDate - 结束日期 + * @param {Array} data.venueIds - 场地ID数组 + * @param {Array} data.projectIds - 项目ID数组 + */ +export const autoArrangeSchedule = (data) => { + return request({ + url: '/api/blade-martial/schedule-plan/auto-arrange', + method: 'post', + data + }) +} + +/** + * 调整赛程计划顺序 + * @param {Object} data - 调整参数 + * @param {Number} data.id - 赛程计划ID + * @param {Number} data.targetOrder - 目标顺序 + */ +export const adjustScheduleOrder = (data) => { + return request({ + url: '/api/blade-martial/schedule-plan/adjust-order', + method: 'post', + data + }) +} + +/** + * 获取某日期的赛程计划 + * @param {Number} scheduleId - 赛程ID + * @param {String} planDate - 计划日期 + */ +export const getSchedulePlansByDate = (scheduleId, planDate) => { + return request({ + url: '/api/blade-martial/schedule-plan/list-by-date', + method: 'get', + params: { scheduleId, planDate } + }) +} + +/** + * 获取某场地的赛程计划 + * @param {Number} venueId - 场地ID + * @param {String} planDate - 计划日期(可选) + */ +export const getSchedulePlansByVenue = (venueId, planDate) => { + return request({ + url: '/api/blade-martial/schedule-plan/list-by-venue', + method: 'get', + params: { venueId, planDate } + }) +} + +/** + * 检查时间冲突 + * @param {Object} data - 检查参数 + * @param {Number} data.venueId - 场地ID + * @param {String} data.planDate - 计划日期 + * @param {String} data.startTime - 开始时间 + * @param {String} data.endTime - 结束时间 + * @param {Number} data.excludeId - 排除的赛程计划ID(编辑时使用) + */ +export const checkTimeConflict = (data) => { + return request({ + url: '/api/blade-martial/schedule-plan/check-conflict', + method: 'post', + data + }) +} + +/** + * 复制赛程计划到其他日期 + * @param {Object} data - 复制参数 + * @param {Number} data.sourcePlanId - 源赛程计划ID + * @param {String} data.targetDate - 目标日期 + */ +export const copySchedulePlan = (data) => { + return request({ + url: '/api/blade-martial/schedule-plan/copy', + method: 'post', + data + }) +} + +/** + * 导出赛程计划 + * @param {Object} params - 导出参数 + */ +export const exportSchedulePlans = (params) => { + return request({ + url: '/api/blade-martial/schedule-plan/export', + method: 'get', + params, + responseType: 'blob' + }) +} diff --git a/src/api/martial/score.js b/src/api/martial/score.js index 5d3993e..d980d5e 100644 --- a/src/api/martial/score.js +++ b/src/api/martial/score.js @@ -82,3 +82,94 @@ export const getProjectList = (competitionId, venueId) => { params: { competitionId, venueId } }) } + +// ==================== 评分提交接口 ==================== + +/** + * 提交评分 + * @param {Object} data - 评分数据 + * @param {Number} data.competitionId - 赛事ID + * @param {Number} data.athleteId - 运动员ID + * @param {Number} data.projectId - 项目ID + * @param {Number} data.scheduleId - 赛程ID + * @param {Number} data.venueId - 场地ID + * @param {Number} data.judgeId - 裁判ID + * @param {String} data.judgeName - 裁判姓名 + * @param {Number} data.score - 评分 + * @param {Number} data.originalScore - 原始分 + * @param {Array} data.deductionItems - 扣分项ID数组 + * @param {String} data.note - 备注 + */ +export const submitScore = (data) => { + return request({ + url: '/api/blade-martial/score/submit', + method: 'post', + data + }) +} + +/** + * 删除评分 + * @param {String} ids - 评分ID,多个用逗号分隔 + */ +export const removeScore = (ids) => { + return request({ + url: '/api/blade-martial/score/remove', + method: 'post', + params: { ids } + }) +} + +/** + * 获取异常评分列表 + * @param {Object} params - 查询参数 + * @param {Number} params.competitionId - 赛事ID + * @param {Number} params.projectId - 项目ID(可选) + */ +export const getAnomalies = (params) => { + return request({ + url: '/api/blade-martial/score/anomalies', + method: 'get', + params + }) +} + +/** + * 验证评分 + * @param {Object} data - 验证数据 + * @param {Number} data.athleteId - 运动员ID + * @param {Number} data.projectId - 项目ID + * @param {Number} data.score - 评分 + */ +export const validateScores = (data) => { + return request({ + url: '/api/blade-martial/score/validate', + method: 'post', + data + }) +} + +/** + * 批量提交评分 + * @param {Array} data - 评分数据数组 + */ +export const batchSubmitScores = (data) => { + return request({ + url: '/api/blade-martial/score/batch-submit', + method: 'post', + data + }) +} + +/** + * 获取裁判待评分列表 + * @param {Number} judgeId - 裁判ID + * @param {Number} competitionId - 赛事ID + */ +export const getPendingScores = (judgeId, competitionId) => { + return request({ + url: '/api/blade-martial/score/pending', + method: 'get', + params: { judgeId, competitionId } + }) +} diff --git a/src/components/martial/CompetitionSelector.vue b/src/components/martial/CompetitionSelector.vue new file mode 100644 index 0000000..9338cb2 --- /dev/null +++ b/src/components/martial/CompetitionSelector.vue @@ -0,0 +1,186 @@ + + + + + diff --git a/src/components/martial/MedalDialog.vue b/src/components/martial/MedalDialog.vue new file mode 100644 index 0000000..b4b86e4 --- /dev/null +++ b/src/components/martial/MedalDialog.vue @@ -0,0 +1,330 @@ + + + + + diff --git a/src/components/martial/ProjectSelector.vue b/src/components/martial/ProjectSelector.vue new file mode 100644 index 0000000..0b2a0c4 --- /dev/null +++ b/src/components/martial/ProjectSelector.vue @@ -0,0 +1,186 @@ + + + + + diff --git a/src/components/martial/ScoreInput.vue b/src/components/martial/ScoreInput.vue new file mode 100644 index 0000000..09c0b92 --- /dev/null +++ b/src/components/martial/ScoreInput.vue @@ -0,0 +1,268 @@ + + + + + diff --git a/src/router/views/index.js b/src/router/views/index.js index 13eb567..121e600 100644 --- a/src/router/views/index.js +++ b/src/router/views/index.js @@ -53,23 +53,13 @@ export default [ meta: { keepAlive: false, }, - component: () => import(/* webpackChunkName: "martial" */ '@/views/martial/competition/list.vue'), - }, - { - path: 'competition/create', - name: '赛事详情', - meta: { - keepAlive: false, - menu: false, - }, - component: () => import(/* webpackChunkName: "martial" */ '@/views/martial/competition/create.vue'), + component: () => import(/* webpackChunkName: "martial" */ '@/views/martial/competition/index.vue'), }, { path: 'registration/detail', name: '报名详情', meta: { keepAlive: false, - menu: false, }, component: () => import(/* webpackChunkName: "martial" */ '@/views/martial/registration/index.vue'), }, @@ -127,16 +117,106 @@ export default [ meta: { keepAlive: false, }, - component: () => import(/* webpackChunkName: "martial" */ '@/views/martial/participant/list.vue'), + component: () => import(/* webpackChunkName: "martial" */ '@/views/martial/participant/index.vue'), + }, + // 新增页面 - P0核心页面 + { + path: 'project/list', + name: '项目管理', + meta: { + keepAlive: true, + }, + component: () => import(/* webpackChunkName: "martial" */ '@/views/martial/project/index.vue'), }, { - path: 'participant/manage', - name: '选手详情', + path: 'deduction/list', + name: '扣分项管理', meta: { - keepAlive: false, - menu: false, + keepAlive: true, }, - component: () => import(/* webpackChunkName: "martial" */ '@/views/martial/participant/manage.vue'), + component: () => import(/* webpackChunkName: "martial" */ '@/views/martial/deduction/index.vue'), + }, + { + path: 'result/list', + name: '成绩管理', + meta: { + keepAlive: true, + }, + component: () => import(/* webpackChunkName: "martial" */ '@/views/martial/result/index.vue'), + }, + { + path: 'export/index', + name: '导出中心', + meta: { + keepAlive: true, + }, + component: () => import(/* webpackChunkName: "martial" */ '@/views/martial/export/index.vue'), + }, + // P1重要页面 + { + path: 'schedulePlan/list', + name: '赛程计划', + meta: { + keepAlive: true, + }, + component: () => import(/* webpackChunkName: "martial" */ '@/views/martial/schedulePlan/index.vue'), + }, + { + path: 'scheduleAthlete/list', + name: '选手关联', + meta: { + keepAlive: true, + }, + component: () => import(/* webpackChunkName: "martial" */ '@/views/martial/scheduleAthlete/index.vue'), + }, + { + path: 'judgeInvite/list', + name: '裁判邀请', + meta: { + keepAlive: true, + }, + component: () => import(/* webpackChunkName: "martial" */ '@/views/martial/judgeInvite/index.vue'), + }, + { + path: 'judgeProject/list', + name: '裁判分配', + meta: { + keepAlive: true, + }, + component: () => import(/* webpackChunkName: "martial" */ '@/views/martial/judgeProject/index.vue'), + }, + // P2增强页面 + { + path: 'live/list', + name: '直播管理', + meta: { + keepAlive: true, + }, + component: () => import(/* webpackChunkName: "martial" */ '@/views/martial/live/index.vue'), + }, + { + path: 'info/list', + name: '信息发布', + meta: { + keepAlive: true, + }, + component: () => import(/* webpackChunkName: "martial" */ '@/views/martial/info/index.vue'), + }, + { + path: 'exception/list', + name: '异常事件', + meta: { + keepAlive: true, + }, + component: () => import(/* webpackChunkName: "martial" */ '@/views/martial/exception/index.vue'), + }, + { + path: 'activity/list', + name: '活动日程', + meta: { + keepAlive: true, + }, + component: () => import(/* webpackChunkName: "martial" */ '@/views/martial/activity/index.vue'), }, ], }, diff --git a/src/views/martial/activity/index.vue b/src/views/martial/activity/index.vue new file mode 100644 index 0000000..42c487d --- /dev/null +++ b/src/views/martial/activity/index.vue @@ -0,0 +1,1249 @@ + + + + + diff --git a/src/views/martial/banner/index.vue b/src/views/martial/banner/index.vue index ef6105e..60fd3f8 100644 --- a/src/views/martial/banner/index.vue +++ b/src/views/martial/banner/index.vue @@ -59,7 +59,7 @@ - + diff --git a/src/views/martial/competition/list.vue b/src/views/martial/competition/list.vue index 5526df3..c669ee4 100644 --- a/src/views/martial/competition/list.vue +++ b/src/views/martial/competition/list.vue @@ -105,6 +105,309 @@ + + + + + +
+
+ + 基本信息 +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+
+ + 信息发布 +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + +
+
+ + 赛事规程 +
+ + + + + + + + + + + + +
+ + +
+
+ + 活动日程 +
+ + + + 添加日程 + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
@@ -184,9 +487,51 @@ export default { { date: '2025-05-21', time: '09:00-18:00', event: '初赛', venue: '比赛馆' }, ] } - ] + ], + dialogVisible: false, + dialogMode: 'create', // create, edit, view + submitLoading: false, + currentCompetitionId: null, + formData: { + competitionName: '', + organizer: '', + location: '', + venue: '', + registrationTime: '', + competitionTime: '', + status: 1, + introduction: '', + contactPerson: '', + contactPhone: '', + contactEmail: '', + rules: '', + requirements: '', + awards: '', + schedule: [] + }, + formRules: { + competitionName: [ + { required: true, message: '请输入赛事名称', trigger: 'blur' } + ], + organizer: [ + { required: true, message: '请输入主办单位', trigger: 'blur' } + ], + location: [ + { required: true, message: '请输入举办地点', trigger: 'blur' } + ] + } }; }, + computed: { + dialogTitle() { + const titleMap = { + create: '新建赛事', + edit: '编辑赛事', + view: '查看赛事' + }; + return titleMap[this.dialogMode] || '赛事信息'; + } + }, mounted() { this.loadCompetitionList(); }, @@ -231,24 +576,28 @@ export default { }, handleCreate() { - this.$router.push({ - path: '/martial/competition/create', - query: { mode: 'create' } - }); + this.dialogMode = 'create'; + this.currentCompetitionId = null; + this.resetFormData(); + this.dialogVisible = true; }, handleView(row) { - this.$router.push({ - path: '/martial/competition/create', - query: { mode: 'view', id: row.id } - }); + this.dialogMode = 'view'; + this.currentCompetitionId = row.id; + this.formData = { ...row }; + this.dialogVisible = true; }, handleEdit(row) { - this.$router.push({ - path: '/martial/competition/create', - query: { mode: 'edit', id: row.id } - }); + this.dialogMode = 'edit'; + this.currentCompetitionId = row.id; + this.formData = { ...row }; + this.dialogVisible = true; + }, + + switchToEdit() { + this.dialogMode = 'edit'; }, handleDelete(row) { @@ -264,6 +613,85 @@ export default { this.$message.success('删除成功'); } }).catch(() => {}); + }, + + handleAddSchedule() { + this.formData.schedule.push({ + date: '', + time: '', + event: '', + venue: '' + }); + }, + + handleDeleteSchedule(index) { + this.formData.schedule.splice(index, 1); + }, + + handleSubmit() { + this.$refs.formRef.validate((valid) => { + if (valid) { + this.submitLoading = true; + + setTimeout(() => { + if (this.dialogMode === 'create') { + // 新建 + const newId = this.competitionList.length > 0 + ? Math.max(...this.competitionList.map(item => item.id)) + 1 + : 1; + const newCompetition = { + ...this.formData, + id: newId, + posterImages: [], + regulationFiles: [] + }; + this.competitionList.push(newCompetition); + this.$message.success('创建成功'); + } else if (this.dialogMode === 'edit') { + // 编辑 + const index = this.competitionList.findIndex(item => item.id === this.currentCompetitionId); + if (index !== -1) { + this.competitionList[index] = { + ...this.competitionList[index], + ...this.formData + }; + this.$message.success('保存成功'); + } + } + + this.saveCompetitionList(); + this.dialogVisible = false; + this.submitLoading = false; + }, 500); + } else { + this.$message.error('请完善必填信息'); + } + }); + }, + + handleDialogClose() { + this.$refs.formRef.resetFields(); + this.resetFormData(); + }, + + resetFormData() { + this.formData = { + competitionName: '', + organizer: '', + location: '', + venue: '', + registrationTime: '', + competitionTime: '', + status: 1, + introduction: '', + contactPerson: '', + contactPhone: '', + contactEmail: '', + rules: '', + requirements: '', + awards: '', + schedule: [] + }; } } }; @@ -306,4 +734,49 @@ export default { padding: 0 8px; } } + +.competition-form { + max-height: 60vh; + overflow-y: auto; +} + +.form-section { + margin-bottom: 30px; + padding: 20px; + background: #fafafa; + border-radius: 8px; + + &:last-child { + margin-bottom: 0; + } +} + +.section-title { + display: flex; + align-items: center; + gap: 8px; + margin-bottom: 20px; + font-size: 16px; + font-weight: 600; + color: #333; + + i { + color: #dc2626; + font-size: 18px; + } +} + +:deep(.el-form-item) { + margin-bottom: 18px; +} + +:deep(.el-table) { + .el-input { + width: 100%; + } +} + +.dialog-footer { + text-align: right; +} diff --git a/src/views/martial/deduction/index.vue b/src/views/martial/deduction/index.vue new file mode 100644 index 0000000..f754b35 --- /dev/null +++ b/src/views/martial/deduction/index.vue @@ -0,0 +1,698 @@ + + + + + diff --git a/src/views/martial/dispatch/index.vue b/src/views/martial/dispatch/index.vue index 2e870e4..e6d6f8e 100644 --- a/src/views/martial/dispatch/index.vue +++ b/src/views/martial/dispatch/index.vue @@ -154,7 +154,7 @@ export default { }, methods: { goBack() { - this.$router.push('/martial/order/list') + this.$router.go(-1) }, setViewMode(index, mode) { this.dispatchGroups[index].viewMode = mode diff --git a/src/views/martial/exception/index.vue b/src/views/martial/exception/index.vue new file mode 100644 index 0000000000000000000000000000000000000000..4fb8c881b41a24899fea027ac5eb6e4846971262 GIT binary patch literal 34562 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 R*RXdr& +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + 排名 + 选手姓名 + 团队名称 + 项目 + 总分 + 最终成绩 + 奖牌 + 裁判评分明细 + + + + + Excel (xlsx) + PDF + CSV + + + + + 导出成绩单 + + + +
+
+ + + +
+ + + + + + + + + 运动员名单 + 裁判名单 + 工作人员名单 + + + + + Excel (xlsx) + PDF + + + + + 导出名单 + + + +
+
+ + + +
+ + + + + + + + + + + + + + 获奖证书(金银铜牌) + 参赛证书 + 优秀运动员证书 + + + + + + {{ item.templateName }} + + {{ item.description }} + + + + + + + PDF + JPG图片 + + + + + + 开启后将根据筛选条件批量生成 + + + + + 生成证书 + + + 预览模板 + + + + + + +

已生成证书

+ + + + + + + + + + + + + + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + Excel (xlsx) + PDF + + + + + + 导出PDF时包含统计图表 + + + + + 导出报表 + + + + + + + + +
+

赛事统计报表:包含赛事基本信息、时间、地点、参赛人数、项目数量、裁判数量等综合统计信息

+

项目统计报表:各项目报名人数、实际参赛人数、获奖分布、平均分、最高分、最低分等详细数据

+

裁判工作量报表:每位裁判的评分数量、负责项目、工作时长、评分准确性等统计

+

报名统计报表:报名趋势分析、地域分布、团队排名、报名费收入统计等

+

奖牌榜报表:按团队或地区统计金银铜牌数量,包含总积分排名

+
+
+
+
+
+
+ + + +
+ + +
+
+
+ + + + + diff --git a/src/views/martial/info/index.vue b/src/views/martial/info/index.vue new file mode 100644 index 0000000..5f7934f --- /dev/null +++ b/src/views/martial/info/index.vue @@ -0,0 +1,1194 @@ + + + + + diff --git a/src/views/martial/judgeInvite/index.vue b/src/views/martial/judgeInvite/index.vue new file mode 100644 index 0000000000000000000000000000000000000000..ccbf4887542e9411516195c990a04a7a0631b47c GIT binary patch literal 31762 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 Zdx)UOeNCrUqD>(d5 literal 0 HcmV?d00001 diff --git a/src/views/martial/judgeProject/index.vue b/src/views/martial/judgeProject/index.vue new file mode 100644 index 0000000..7e5a4cb --- /dev/null +++ b/src/views/martial/judgeProject/index.vue @@ -0,0 +1,1722 @@ + + + + + diff --git a/src/views/martial/live/index.vue b/src/views/martial/live/index.vue new file mode 100644 index 0000000000000000000000000000000000000000..71b366f13cdcee0e5b5cdcf72aa6d6707bda49c3 GIT binary patch literal 27988 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 literal 0 HcmV?d00001 diff --git a/src/views/martial/participant/index.vue b/src/views/martial/participant/index.vue index 29a2c9c..9c8312a 100644 --- a/src/views/martial/participant/index.vue +++ b/src/views/martial/participant/index.vue @@ -1,260 +1,449 @@ diff --git a/src/views/martial/participant/list.vue b/src/views/martial/participant/list.vue index 6c3e3c4..5f46cf0 100644 --- a/src/views/martial/participant/list.vue +++ b/src/views/martial/participant/list.vue @@ -32,11 +32,12 @@ 查询 + 重置
+ + + + + +
+
+ + 基本信息 +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+
+ + 赛事信息 +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+
+ + 其他信息 +
+ + + + + + + + +
+
+ + +
@@ -182,6 +367,7 @@ export default { category: '成年男子组', orderNum: 1, introduction: '国家一级运动员', + remark: '', attachments: [] }, { @@ -198,6 +384,7 @@ export default { category: '成年女子组', orderNum: 2, introduction: '国家二级运动员', + remark: '', attachments: [] }, { @@ -214,6 +401,7 @@ export default { category: '少年男子组', orderNum: 1, introduction: '市级青少年冠军', + remark: '', attachments: [] }, { @@ -230,6 +418,7 @@ export default { category: '少年女子组', orderNum: 2, introduction: '省级青少年亚军', + remark: '', attachments: [] }, { @@ -246,11 +435,80 @@ export default { category: '中年组', orderNum: 1, introduction: '武当第十五代传人', + remark: '', attachments: [] } - ] + ], + dialogVisible: false, + dialogMode: 'create', // create, edit, view + submitLoading: false, + currentParticipantId: null, + formData: { + competitionId: null, + competitionName: '', + playerName: '', + gender: 1, + age: null, + contactPhone: '', + organization: '', + idCard: '', + projectName: '', + category: '', + orderNum: 1, + introduction: '', + remark: '', + attachments: [] + }, + formRules: { + playerName: [ + { required: true, message: '请输入选手姓名', trigger: 'blur' } + ], + gender: [ + { required: true, message: '请选择性别', trigger: 'change' } + ], + age: [ + { required: true, message: '请输入年龄', trigger: 'blur' } + ], + contactPhone: [ + { required: true, message: '请输入联系电话', trigger: 'blur' }, + { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号码', trigger: 'blur' } + ], + competitionId: [ + { required: true, message: '请选择赛事', trigger: 'change' } + ], + projectName: [ + { required: true, message: '请输入参赛项目', trigger: 'blur' } + ] + } }; }, + computed: { + dialogTitle() { + const titleMap = { + create: '添加参赛选手', + edit: '编辑参赛选手', + view: '查看参赛选手' + }; + return titleMap[this.dialogMode] || '参赛选手信息'; + }, + displayList() { + let list = [...this.participantList]; + + // 关键词搜索 + if (this.searchForm.keyword) { + list = list.filter(item => + item.playerName.includes(this.searchForm.keyword) + ); + } + + // 赛事筛选 + if (this.searchForm.competitionId) { + list = list.filter(item => item.competitionId === this.searchForm.competitionId); + } + + return list; + } + }, mounted() { this.loadParticipantList(); }, @@ -285,29 +543,39 @@ export default { }, handleSearch() { - // 实现搜索逻辑 - this.loadParticipantList(); + // 搜索逻辑已在 computed 中实现 + }, + + handleReset() { + this.searchForm = { + keyword: '', + competitionId: null + }; }, handleCreate() { - this.$router.push({ - path: '/martial/participant/manage', - query: { mode: 'create' } - }); + this.dialogMode = 'create'; + this.currentParticipantId = null; + this.resetFormData(); + this.dialogVisible = true; }, handleView(row) { - this.$router.push({ - path: '/martial/participant/manage', - query: { mode: 'view', id: row.id } - }); + this.dialogMode = 'view'; + this.currentParticipantId = row.id; + this.formData = { ...row }; + this.dialogVisible = true; }, handleEdit(row) { - this.$router.push({ - path: '/martial/participant/manage', - query: { mode: 'edit', id: row.id } - }); + this.dialogMode = 'edit'; + this.currentParticipantId = row.id; + this.formData = { ...row }; + this.dialogVisible = true; + }, + + switchToEdit() { + this.dialogMode = 'edit'; }, handleDelete(row) { @@ -323,6 +591,84 @@ export default { this.$message.success('删除成功'); } }).catch(() => {}); + }, + + handleCompetitionChange(competitionId) { + const competition = this.competitionOptions.find(item => item.id === competitionId); + if (competition) { + this.formData.competitionName = competition.competitionName; + } + }, + + handleSubmit() { + this.$refs.formRef.validate((valid) => { + if (valid) { + this.submitLoading = true; + + // 确保有赛事名称 + if (!this.formData.competitionName) { + const competition = this.competitionOptions.find(item => item.id === this.formData.competitionId); + if (competition) { + this.formData.competitionName = competition.competitionName; + } + } + + setTimeout(() => { + if (this.dialogMode === 'create') { + // 新建 + const newId = this.participantList.length > 0 + ? Math.max(...this.participantList.map(item => item.id)) + 1 + : 1; + const newParticipant = { + ...this.formData, + id: newId + }; + this.participantList.push(newParticipant); + this.$message.success('添加成功'); + } else if (this.dialogMode === 'edit') { + // 编辑 + const index = this.participantList.findIndex(item => item.id === this.currentParticipantId); + if (index !== -1) { + this.participantList[index] = { + ...this.participantList[index], + ...this.formData + }; + this.$message.success('保存成功'); + } + } + + this.saveParticipantList(); + this.dialogVisible = false; + this.submitLoading = false; + }, 500); + } else { + this.$message.error('请完善必填信息'); + } + }); + }, + + handleDialogClose() { + this.$refs.formRef.resetFields(); + this.resetFormData(); + }, + + resetFormData() { + this.formData = { + competitionId: null, + competitionName: '', + playerName: '', + gender: 1, + age: null, + contactPhone: '', + organization: '', + idCard: '', + projectName: '', + category: '', + orderNum: 1, + introduction: '', + remark: '', + attachments: [] + }; } } }; @@ -369,4 +715,43 @@ export default { padding: 0 8px; } } + +.participant-form { + max-height: 60vh; + overflow-y: auto; +} + +.form-section { + margin-bottom: 30px; + padding: 20px; + background: #fafafa; + border-radius: 8px; + + &:last-child { + margin-bottom: 0; + } +} + +.section-title { + display: flex; + align-items: center; + gap: 8px; + margin-bottom: 20px; + font-size: 16px; + font-weight: 600; + color: #333; + + i { + color: #dc2626; + font-size: 18px; + } +} + +:deep(.el-form-item) { + margin-bottom: 18px; +} + +.dialog-footer { + text-align: right; +} diff --git a/src/views/martial/project/index.vue b/src/views/martial/project/index.vue new file mode 100644 index 0000000..1c0d371 --- /dev/null +++ b/src/views/martial/project/index.vue @@ -0,0 +1,837 @@ + + + + + diff --git a/src/views/martial/registration/index.vue b/src/views/martial/registration/index.vue index 29f655e..916e9ee 100644 --- a/src/views/martial/registration/index.vue +++ b/src/views/martial/registration/index.vue @@ -1,5 +1,5 @@