Sfoglia il codice sorgente

feat(game-event): 增加赛事项目库功能

zhou 1 mese fa
parent
commit
1810349f9f

+ 25 - 0
src/api/system/gameEventProject/index.ts

@@ -16,6 +16,19 @@ export const listGameEventProject = (query?: GameEventProjectQuery): AxiosPromis
   });
 };
 
+/**
+ * 查询所有赛事的项目列表(用于项目库)
+ * @param query
+ * @returns {*}
+ */
+export const listAllGameEventProject = (query?: GameEventProjectQuery): AxiosPromise<GameEventProjectVO[]> => {
+  return request({
+    url: '/system/gameEventProject/listAll',
+    method: 'get',
+    params: query
+  });
+};
+
 /**
  * 查询赛事项目详细
  * @param projectId
@@ -39,6 +52,18 @@ export const addGameEventProject = (data: GameEventProjectForm) => {
   });
 };
 
+/**
+ * 批量新增赛事项目
+ * @param data
+ */
+export const BatchAddProject = (data: GameEventProjectVO[]) => {
+  return request({
+    url: '/system/gameEventProject/BatchAdd',
+    method: 'post',
+    data: data
+  });
+};
+
 /**
  * 修改赛事项目
  * @param data

+ 16 - 10
src/api/system/gameEventProject/types.ts

@@ -4,6 +4,12 @@ export interface GameEventProjectVO {
    * 赛事ID
    */
   eventId: string | number;
+
+  /**
+   * 赛事名称
+   */
+  eventName: string;
+
   /**
    * 项目ID
    */
@@ -58,7 +64,7 @@ export interface GameEventProjectVO {
   participateNum: number;
 
   /**
-   * 
+   * 录取名
    */
   roundType: string;
 
@@ -83,14 +89,14 @@ export interface GameEventProjectVO {
   award: string;
 
   /**
-   * 计时点名称
+   * 比赛轮次
    */
-  timePoint: string;
+  gameRound: string;
 
   /**
-   * 控制盒编号
+   * 比赛阶段
    */
-  boxCode: string;
+  gameStage: string;
 
   /**
    * 状态(0正常 1停用)
@@ -165,7 +171,7 @@ export interface GameEventProjectForm extends BaseEntity {
   participateNum?: number;
 
   /**
-   * 
+   * 录取名
    */
   roundType?: string;
 
@@ -190,14 +196,14 @@ export interface GameEventProjectForm extends BaseEntity {
   award?: string;
 
   /**
-   * 计时点名称
+   * 比赛轮次
    */
-  timePoint?: string;
+  gameRound?: string;
 
   /**
-   * 控制盒编号
+   * 比赛阶段
    */
-  boxCode?: string;
+  gameStage?: string;
 
   /**
    * 状态(0正常 1停用)

+ 271 - 0
src/views/system/gameEventProject/ProjectLibraryDialog.vue

@@ -0,0 +1,271 @@
+<template>
+  <el-dialog
+    v-model="visible"
+    title="项目库"
+    width="80%"
+    :before-close="handleClose"
+    append-to-body
+  >
+    <div class="project-library">
+      <!-- 搜索区域 -->
+      <div class="search-area mb-4">
+        <el-form :model="searchForm" :inline="true">
+          <el-form-item label="来源赛事">
+            <el-select
+              v-model="searchForm.eventId"
+              placeholder="请选择来源赛事"
+              clearable
+              @change="handleSearch"
+            >
+              <el-option
+                v-for="event in eventList"
+                :key="event.eventId"
+                :label="event.eventName"
+                :value="event.eventId"
+              />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="项目名称">
+            <el-input
+              v-model="searchForm.projectName"
+              placeholder="请输入项目名称"
+              clearable
+              @keyup.enter="handleSearch"
+            />
+          </el-form-item>
+          <el-form-item label="项目类型">
+            <el-select
+              v-model="searchForm.projectType"
+              placeholder="请选择项目类型"
+              clearable
+              @change="handleSearch"
+            >
+              <el-option
+                v-for="dict in game_project_type"
+                :key="dict.value"
+                :label="dict.label"
+                :value="dict.value"
+              />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="归类">
+            <el-select
+              v-model="searchForm.classification"
+              placeholder="请选择归类"
+              clearable
+              @change="handleSearch"
+            >
+              <el-option
+                v-for="dict in game_project_classification"
+                :key="dict.value"
+                :label="dict.label"
+                :value="dict.value"
+              />
+            </el-select>
+          </el-form-item>
+          <el-form-item>
+            <el-button type="primary" icon="Search" @click="handleSearch">搜索</el-button>
+            <el-button icon="Refresh" @click="resetSearch">重置</el-button>
+          </el-form-item>
+        </el-form>
+      </div>
+
+      <!-- 项目列表 -->
+      <el-table
+        v-loading="loading"
+        :data="projectList"
+        @selection-change="handleSelectionChange"
+        height="400"
+        border
+      >
+        <el-table-column type="selection" width="55" align="center" />
+        <el-table-column label="项目名称" prop="projectName" min-width="120" />
+        <el-table-column label="项目类型" prop="projectType" width="100">
+          <template #default="scope">
+            <dict-tag :options="game_project_type" :value="scope.row.projectType || ''" />
+          </template>
+        </el-table-column>
+        <el-table-column label="归类" prop="classification" width="100">
+          <template #default="scope">
+            <dict-tag :options="game_project_classification" :value="scope.row.classification || '未知'" />
+          </template>
+        </el-table-column>
+        <el-table-column label="比赛场地" prop="location" min-width="120" />
+        <el-table-column label="计算规则" prop="scoreRule" width="100">
+          <template #default="scope">
+            <dict-tag :options="game_score_type" :value="scope.row.scoreRule || ''" />
+          </template>
+        </el-table-column>
+        <el-table-column label="比赛轮次" prop="gameRound" width="100">
+          <template #default="scope">
+            <dict-tag :options="game_round" :value="scope.row.gameRound || ''" />
+          </template>
+        </el-table-column>
+        <el-table-column label="比赛阶段" prop="gameStage" width="100">
+          <template #default="scope">
+            <dict-tag :options="game_stage" :value="scope.row.gameStage || ''" />
+          </template>
+        </el-table-column>
+        <el-table-column label="排序方式" prop="orderType" width="100">
+          <template #default="scope">
+            {{ scope.row.orderType === '0' ? '升序' : '降序' }}
+          </template>
+        </el-table-column>
+        <el-table-column label="录取名次" prop="roundType" width="100" />
+        <el-table-column label="积分分值" prop="scoreValue" width="120" />
+        <el-table-column label="来源赛事" prop="eventName" min-width="120" />
+      </el-table>
+
+      <!-- 分页 -->
+      <pagination
+        v-show="total > 0"
+        :total="total"
+        v-model:page="searchForm.pageNum"
+        v-model:limit="searchForm.pageSize"
+        @pagination="getProjectList"
+      />
+    </div>
+
+    <template #footer>
+      <div class="dialog-footer">
+        <el-button @click="handleClose">取消</el-button>
+        <el-button
+          type="primary"
+          :disabled="selectedProjects.length === 0"
+          @click="handleConfirm"
+        >
+          确定选择 ({{ selectedProjects.length }})
+        </el-button>
+      </div>
+    </template>
+  </el-dialog>
+</template>
+
+<script setup name="ProjectLibraryDialog" lang="ts">
+import { ref, reactive, defineExpose, onMounted } from 'vue';
+import { listAllGameEventProject } from '@/api/system/gameEventProject';
+import { listGameEvent } from '@/api/system/gameEvent';
+import { GameEventProjectVO, GameEventProjectQuery } from '@/api/system/gameEventProject/types';
+import { GameEventVO } from '@/api/system/gameEvent/types';
+
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const { game_score_type, game_project_type, game_project_classification, game_round, game_stage } = toRefs<any>(
+  proxy?.useDict('game_score_type', 'game_project_type', 'game_project_classification', 'game_round', 'game_stage')
+);
+
+const visible = ref(false);
+const loading = ref(false);
+const projectList = ref<GameEventProjectVO[]>([]);
+const selectedProjects = ref<GameEventProjectVO[]>([]);
+const total = ref(0);
+const eventList = ref<GameEventVO[]>([]);
+
+const searchForm = reactive<GameEventProjectQuery>({
+  pageNum: 1,
+  pageSize: 10,
+  eventId: undefined,
+  projectName: undefined,
+  projectType: undefined,
+  classification: undefined,
+  orderByColumn: undefined,
+  isAsc: undefined,
+});
+
+// 打开对话框
+const openDialog = () => {
+  visible.value = true;
+  resetSearch();
+  getProjectList();
+};
+
+// 关闭对话框
+const handleClose = () => {
+  visible.value = false;
+  selectedProjects.value = [];
+};
+
+// 搜索
+const handleSearch = () => {
+  searchForm.pageNum = 1;
+  getProjectList();
+};
+
+// 重置搜索
+const resetSearch = () => {
+  searchForm.projectName = undefined;
+  searchForm.projectType = undefined;
+  searchForm.classification = undefined;
+  searchForm.pageNum = 1;
+  handleSearch();
+};
+
+// 获取项目列表
+const getProjectList = async () => {
+  loading.value = true;
+  try {
+    const res = await listAllGameEventProject(searchForm);
+    projectList.value = res.rows || [];
+    total.value = res.total || 0;
+  } catch (error) {
+    proxy?.$modal.msgError('获取项目列表失败');
+  } finally {
+    loading.value = false;
+  }
+};
+// 获取赛事列表
+const getEventList = async () => {
+  try {
+    const res = await listGameEvent({
+      pageNum: 1,
+      pageSize: 10,
+      orderByColumn: undefined,
+      isAsc: undefined,
+    });
+    eventList.value = res.rows || [];
+  } catch (error) {
+    proxy?.$modal.msgError('获取赛事列表失败');
+  }
+};
+// 选择变化
+const handleSelectionChange = (selection: GameEventProjectVO[]) => {
+  selectedProjects.value = selection;
+};
+
+// 确认选择
+const handleConfirm = () => {
+  if (selectedProjects.value.length === 0) {
+    proxy?.$modal.msgWarning('请选择至少一个项目');
+    return;
+  }
+  
+  // 触发父组件的确认事件
+  emit('confirm', selectedProjects.value);
+  handleClose();
+};
+
+// 定义事件
+const emit = defineEmits<{
+  confirm: [projects: GameEventProjectVO[]]
+}>();
+
+// 暴露方法给父组件
+defineExpose({
+  openDialog
+});
+
+// 组件挂载时获取赛事列表
+onMounted(() => {
+  getEventList();
+});
+
+</script>
+
+<style scoped lang="scss">
+.project-library {
+  .search-area {
+    background: #f5f5f5;
+    padding: 16px;
+    border-radius: 4px;
+  }
+}
+</style>

+ 79 - 23
src/views/system/gameEventProject/index.vue

@@ -27,6 +27,9 @@
           <el-col :span="1.5">
             <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['system:gameEventProject:add']"> 新增 </el-button>
           </el-col>
+          <el-col :span="1.5">
+            <el-button type="info" plain icon="Collection" @click="handleViewProjectLibrary()"> 项目库 </el-button>
+          </el-col>
           <el-col :span="1.5">
             <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['system:gameEventProject:edit']"
               >修改
@@ -89,18 +92,26 @@
         </el-table-column>
         <!-- <el-table-column label="参赛组数" align="center" prop="groupNum" />
         <el-table-column label="参赛人数" align="center" prop="participateNum" /> -->
-        <el-table-column label="次" align="center" prop="roundType" v-if="columns[9].visible" />
+        <el-table-column label="录取名次" align="center" prop="roundType" v-if="columns[9].visible" />
         <el-table-column label="排序方式" align="center" prop="orderType" v-if="columns[10].visible">
           <template #default="scope">
             {{ scope.row.orderType === '0' ? '升序' : '降序' }}
           </template>
         </el-table-column>
         <el-table-column label="积分分值" align="center" prop="scoreValue" v-if="columns[11].visible" />
-        <!-- <el-table-column label="奖项" align="center" prop="award" />
-        <el-table-column label="计时点名称" align="center" prop="timePoint" />
-        <el-table-column label="控制盒编号" align="center" prop="boxCode" />
-        <el-table-column label="状态" align="center" prop="status" />
-        <el-table-column label="备注" align="center" prop="remark" /> -->
+        <!-- <el-table-column label="奖项" align="center" prop="award" /> -->
+        <el-table-column label="比赛轮次" align="center" prop="gameRound" v-if="columns[12].visible">
+          <template #default="scope">
+            <dict-tag :options="game_round" :value="scope.row.gameRound || ''" />
+          </template>
+        </el-table-column>
+        <el-table-column label="比赛阶段" align="center" prop="gameStage" v-if="columns[13].visible">
+          <template #default="scope">
+            <dict-tag :options="game_stage" :value="scope.row.gameStage || ''" />
+          </template>
+        </el-table-column>
+        <!-- <el-table-column label="状态" align="center" prop="status" /> -->
+        <!-- <el-table-column label="备注" align="center" prop="remark" /> -->
         <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
           <template #default="scope">
             <el-tooltip content="修改" placement="top">
@@ -146,6 +157,16 @@
         <el-form-item label="参赛人数" prop="participateNum">
           <el-input v-model="form.participateNum" placeholder="请输入参赛人数" />
         </el-form-item> -->
+        <el-form-item label="比赛阶段" prop="gameStage">
+          <el-radio-group v-model="form.gameStage" style="width: 100%">
+            <el-radio v-for="dict in game_stage" :key="dict.value" :label="dict.label" :value="dict.value" />
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="比赛轮次" prop="gameRound">
+          <el-radio-group v-model="form.gameRound" style="width: 100%">
+            <el-radio v-for="dict in game_round" :key="dict.value" :label="dict.label" :value="dict.value" />
+          </el-radio-group>
+        </el-form-item>
         <el-form-item label="计算规则" prop="scoreRule">
           <el-select v-model="form.scoreRule" placeholder="请选择计算规则" style="width: 100%">
             <el-option v-for="dict in game_score_type" :key="dict.value" :label="dict.label" :value="dict.value" />
@@ -157,11 +178,20 @@
             <el-radio value="1">降序</el-radio>
           </el-radio-group>
         </el-form-item>
-        <el-form-item label="积分分值" prop="scoreValue">
-          <el-input v-model="form.scoreValue" placeholder="请输入积分分值" />
+        <el-form-item label="录取名次" prop="roundType">
+          <el-input v-model="form.roundType" placeholder="请输入录取名次" />
         </el-form-item>
-        <el-form-item label="轮次" prop="roundType">
-          <el-input v-model="form.roundType" placeholder="请输入轮次" />
+        <el-form-item label="积分分值" prop="scoreValue">
+          <template #label>
+            <span>
+              <el-tooltip content="各值之间以英文逗号分隔" placement="top">
+                <el-icon>
+                  <question-filled />
+                </el-icon>
+              </el-tooltip>
+            积分</span>
+          </template>
+          <el-input v-model="form.scoreValue" placeholder="请输入名次对应的积分" />
         </el-form-item>
         <el-form-item label="开始时间" prop="startTime">
           <el-date-picker clearable v-model="form.startTime" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择开始时间">
@@ -173,14 +203,9 @@
         </el-form-item>
         <!-- <el-form-item label="奖项" prop="award">
           <el-input v-model="form.award" placeholder="请输入奖项" />
-        </el-form-item>
-        <el-form-item label="计时点名称" prop="timePoint">
-          <el-input v-model="form.timePoint" placeholder="请输入计时点名称" />
-        </el-form-item>
-        <el-form-item label="控制盒编号" prop="boxCode">
-          <el-input v-model="form.boxCode" placeholder="请输入控制盒编号" />
-        </el-form-item>
-        <el-form-item label="备注" prop="remark">
+        </el-form-item> -->
+        
+        <!-- <el-form-item label="备注" prop="remark">
             <el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
         </el-form-item> -->
       </el-form>
@@ -194,6 +219,9 @@
 
     <!-- 裁判组查看对话框 -->
     <RefereeGroupDialog ref="refereeGroupDialogRef" />
+
+    <!-- 项目库查看对话框 -->
+    <ProjectLibraryDialog ref="projectLibraryDialog" @confirm="handleLibraryConfirm" />
   </div>
 </template>
 
@@ -203,16 +231,18 @@ import {
   getGameEventProject,
   delGameEventProject,
   addGameEventProject,
-  updateGameEventProject
+  updateGameEventProject,
+  BatchAddProject
 } from '@/api/system/gameEventProject';
 import { listGameEventGroup } from '@/api/system/gameEventGroup';
 import { GameEventProjectVO, GameEventProjectQuery, GameEventProjectForm } from '@/api/system/gameEventProject/types';
 import RefereeGroupDialog from './RefereeGroupDialog.vue';
+import ProjectLibraryDialog from './ProjectLibraryDialog.vue';
 
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { game_score_type, game_project_type, game_project_classification } = toRefs<any>(proxy?.useDict('game_score_type', 'game_project_type','game_project_classification'));
+const { game_score_type, game_project_type, game_project_classification, game_round, game_stage } = toRefs<any>(proxy?.useDict('game_score_type', 'game_project_type', 'game_project_classification', 'game_round', 'game_stage'));
 
-const gameEventGroupList = ref<any[]>([]); // 赛事分组列表
+const gameEventGroupList = ref<any[]>([]); // ���·����б�
 
 const gameEventProjectList = ref<GameEventProjectVO[]>([]);
 const buttonLoading = ref(false);
@@ -230,8 +260,13 @@ const gameEventProjectFormRef = ref<ElFormInstance>();
 interface RefereeGroupDialogInstance {
   openDialog: (refereeGroups: string[], projectName: string) => void;
 }
+// 定义 ProjectLibraryDialog 组件的类型
+interface ProjectLibraryDialogInstance {
+  openDialog: () => void;
+}
 
 const refereeGroupDialogRef = ref<(InstanceType<typeof RefereeGroupDialog> & RefereeGroupDialogInstance) | null>(null);
+const projectLibraryDialog = ref<(InstanceType<typeof ProjectLibraryDialog> & ProjectLibraryDialogInstance) | null>(null);
 
 const dialog = reactive<DialogOption>({
   visible: false,
@@ -252,6 +287,8 @@ const columns = ref<FieldOption[]>([
   { key: 9, label: '录取名次', visible: true },
   { key: 10, label: '积分分值', visible: true },
   { key: 11, label: '排序方式', visible: true },
+  { key: 12, label: '比赛轮次', visible: true },
+  { key: 13, label: '比赛阶段', visible: true },
 ]);
 
 const initFormData: GameEventProjectForm = {
@@ -271,8 +308,8 @@ const initFormData: GameEventProjectForm = {
   scoreRule: undefined,
   scoreValue: undefined,
   award: undefined,
-  timePoint: undefined,
-  boxCode: undefined,
+  gameRound: undefined,
+  gameStage: undefined,
   status: undefined,
   remark: undefined
 };
@@ -417,6 +454,25 @@ const handleViewRefereeGroup = (refereeGroups: string[], projectName: string) =>
   refereeGroupDialogRef.value?.openDialog(refereeGroups, projectName);
 };
 
+/** 查看项目库 */
+const handleViewProjectLibrary = () => {
+  projectLibraryDialog.value?.openDialog();
+};
+
+/** 处理项目库选择确认 */
+const handleLibraryConfirm = async (projects: GameEventProjectVO[]) => {
+  try {
+      // 调用添加接口
+      await BatchAddProject(projects);
+    } catch (error) {
+      console.error('添加项目失败:', error);
+      proxy?.$modal.msgError(`添加项目失败`);
+    }
+  
+  proxy?.$modal.msgSuccess(`成功添加${projects.length}个项目`);
+  getList(); // 刷新列表
+};
+
 onMounted(() => {
   getList();
   // getGameEventGroupList();

+ 1 - 1
src/views/system/gameScore/index.vue

@@ -101,7 +101,7 @@
     <el-dialog 
       title="加分编辑" 
       v-model="bonusDialog.visible" 
-      width="90%" 
+      width="80%" 
       :close-on-click-modal="false"
       append-to-body>
       <div class="mb-4">