| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928 |
- <template>
- <div class="game-event-edit">
- <el-card shadow="never">
- <template #header>
- <div class="page-header">
- <el-button @click="goBack" icon="ArrowLeft">返回</el-button>
- <span class="page-title">{{ isEdit ? '编辑赛事' : '新增赛事' }}</span>
- </div>
- </template>
- <el-tabs v-model="activeTab" type="card" @tab-click="handleTabClick">
- <!-- 基本信息标签页 -->
- <el-tab-pane label="基本信息" name="basic">
- <el-form ref="basicFormRef" :model="basicForm" :rules="basicRules" label-width="120px">
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="赛事编号" prop="eventCode">
- <el-input v-model="basicForm.eventCode" placeholder="请输入赛事编号" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="赛事名称" prop="eventName">
- <el-input v-model="basicForm.eventName" placeholder="请输入赛事名称" />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="赛事类型" prop="eventType">
- <el-select v-model="basicForm.eventType" placeholder="请选择赛事类型" style="width: 100%">
- <el-option v-for="dict in game_event_type" :key="dict.value" :label="dict.label" :value="dict.value" />
- </el-select>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="用途" prop="purpose">
- <el-select v-model="basicForm.purpose" placeholder="请选择用途" style="width: 100%">
- <el-option v-for="dict in game_event_purpose" :key="dict.value" :label="dict.label" :value="dict.value" />
- </el-select>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="开始时间" prop="startTime">
- <el-date-picker
- v-model="basicForm.startTime"
- type="datetime"
- value-format="YYYY-MM-DD HH:mm:ss"
- placeholder="请选择开始时间"
- style="width: 100%"
- />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="结束时间" prop="endTime">
- <el-date-picker
- v-model="basicForm.endTime"
- type="datetime"
- value-format="YYYY-MM-DD HH:mm:ss"
- placeholder="请选择结束时间"
- style="width: 100%"
- />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="举办地点" prop="location">
- <el-input v-model="basicForm.location" placeholder="请输入举办地点" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="举办单位" prop="unit">
- <el-input v-model="basicForm.unit" placeholder="请输入举办单位" />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="状态" prop="status">
- <el-radio-group v-model="basicForm.status">
- <el-radio v-for="dict in game_event_status" :key="dict.value" :value="dict.value">{{ dict.label }} </el-radio>
- </el-radio-group>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="赛事链接" prop="eventUrl">
- <image-upload-cropper v-model="basicForm.eventUrl" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="裁判码" prop="refereeUrl">
- <image-upload-cropper v-model="basicForm.refereeUrl" />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="20">
- <el-col :span="12" v-for="item in imageConfigItems" :key="item.configKey">
- <el-form-item :label="item.configDesc">
- <image-upload-cropper v-model="item.configValue" />
- </el-form-item>
- </el-col>
- </el-row>
- <el-form-item label="备注" prop="remark">
- <el-input v-model="basicForm.remark" type="textarea" placeholder="请输入备注" :rows="3" />
- </el-form-item>
- </el-form>
- </el-tab-pane>
- <!-- 赛事菜单标签页 -->
- <el-tab-pane label="赛事菜单" name="menu">
- <div class="menu-config">
- <div class="menu-header">
- <h3>赛事菜单</h3>
- <el-button type="primary" @click="showMenuSelectDialog" icon="Plus">添加菜单项</el-button>
- </div>
- <el-table :data="menuItems" border style="width: 100%">
- <el-table-column label="菜单名称" prop="name" width="200">
- <template #default="scope">
- <span>{{ scope.row.name }}</span>
- </template>
- </el-table-column>
- <el-table-column label="图标" prop="pic" width="80">
- <template #default="scope">
- <el-image v-if="scope.row.pic" :src="scope.row.pic" style="width: 40px; height: 40px" fit="cover" />
- <span v-else>-</span>
- </template>
- </el-table-column>
- <el-table-column label="跳转类型" prop="jumpType" width="100">
- <template #default="scope">
- <span>{{ getJumpTypeLabel(scope.row.jumpType) }}</span>
- </template>
- </el-table-column>
- <el-table-column label="颜色" prop="color" width="100">
- <template #default="scope">
- <div v-if="scope.row.color" :style="{ backgroundColor: scope.row.color, width: '30px', height: '20px', borderRadius: '4px' }"></div>
- </template>
- </el-table-column>
- <el-table-column label="跳转路径" prop="jumpPath">
- <template #default="scope">
- <span>{{ scope.row.jumpPath }}</span>
- </template>
- </el-table-column>
- <el-table-column label="排序" prop="sortNum" width="80">
- <template #default="scope">
- <span>{{ scope.row.sortNum }}</span>
- </template>
- </el-table-column>
- <el-table-column label="活动类型" prop="activityType" width="100">
- <template #default="scope">
- <span>{{ scope.row.activityType === 0 ? '赛前' : scope.row.activityType === 1 ? '赛中' : '赛后' }}</span>
- </template>
- </el-table-column>
- <el-table-column label="操作" width="100">
- <template #default="scope">
- <el-button type="danger" size="small" @click="removeMenuItem(scope.$index)" icon="Delete">删除 </el-button>
- </template>
- </el-table-column>
- </el-table>
- </div>
- <!-- 菜单选择弹框 -->
- <el-dialog v-model="menuSelectDialogVisible" title="选择菜单" width="60%" :close-on-click-modal="false">
- <div class="menu-select-content">
- <div class="search-bar" style="margin-bottom: 16px">
- <el-input v-model="menuSearchKeyword" placeholder="搜索菜单名称" clearable style="width: 300px" />
- </div>
- <el-table :data="filteredAvailableMenus" border style="width: 100%" @selection-change="handleMenuSelectionChange" max-height="400">
- <el-table-column type="selection" width="55" />
- <el-table-column label="菜单名称" prop="name" width="200" />
- <el-table-column label="图标" prop="pic" width="80">
- <template #default="scope">
- <el-image v-if="scope.row.pic" :src="scope.row.pic" style="width: 40px; height: 40px" fit="cover" />
- </template>
- </el-table-column>
- <el-table-column label="颜色" prop="color" width="100">
- <template #default="scope">
- <div
- v-if="scope.row.color"
- :style="{ backgroundColor: scope.row.color, width: '30px', height: '20px', borderRadius: '4px' }"
- ></div>
- </template>
- </el-table-column>
- <el-table-column label="跳转类型" prop="jumpType" width="120">
- <template #default="scope">
- <span>{{ getJumpTypeLabel(scope.row.jumpType) }}</span>
- </template>
- </el-table-column>
- <el-table-column label="跳转路径" prop="jumpPath" />
- <el-table-column label="排序" prop="sortNum" width="80" />
- </el-table>
- </div>
- <template #footer>
- <span class="dialog-footer">
- <el-button @click="menuSelectDialogVisible = false">取消</el-button>
- <el-button type="primary" @click="confirmAddMenuItems">确认添加</el-button>
- </span>
- </template>
- </el-dialog>
- </el-tab-pane>
- <!-- 配置信息标签页 -->
- <el-tab-pane label="配置信息" name="config">
- <div class="config-info">
- <div class="config-header">
- <h3>赛事配置信息</h3>
- <el-button type="primary" @click="addConfigItem" icon="Plus">添加配置</el-button>
- </div>
- <el-table :data="configItems" border style="width: 100%">
- <el-table-column label="配置类型" prop="configType" width="150">
- <template #default="scope">
- <el-select v-model="scope.row.configType" placeholder="请选择配置类型" style="width: 100%">
- <el-option v-for="type in configTypes" :key="type.typeCode" :label="type.typeName" :value="type.typeCode" />
- </el-select>
- </template>
- </el-table-column>
- <el-table-column label="配置描述" prop="configDesc">
- <template #default="scope">
- <el-input v-model="scope.row.configDesc" placeholder="请输入配置描述" />
- </template>
- </el-table-column>
- <el-table-column label="配置键" prop="configKey" width="200">
- <template #default="scope">
- <el-input v-model="scope.row.configKey" placeholder="请输入配置键" />
- </template>
- </el-table-column>
- <el-table-column label="配置值" prop="configValue">
- <template #default="scope">
- <image-or-url-input v-model="scope.row.configValue" />
- </template>
- </el-table-column>
- <!-- <el-table-column label="是否启用" prop="isEnabled">
- <template #default="scope">
- <el-switch v-model="scope.row.isEnabled" />
- </template>
- </el-table-column> -->
- <el-table-column label="操作">
- <template #default="scope">
- <el-button type="danger" size="small" @click="removeConfigItem(scope.$index)" icon="Delete">删除 </el-button>
- </template>
- </el-table-column>
- </el-table>
- </div>
- </el-tab-pane>
- </el-tabs>
- <!-- 底部操作按钮 -->
- <div class="form-actions">
- <el-button @click="goBack">取消</el-button>
- <el-button type="primary" @click="saveEvent" :loading="saveLoading">保存</el-button>
- </div>
- </el-card>
- </div>
- </template>
- <script setup name="GameEventEdit" lang="ts">
- import { getGameEvent, addGameEvent, updateGameEvent, changeEventDefault } from '@/api/system/gameEvent';
- import { GameEventVO, GameEventForm } from '@/api/system/gameEvent/types';
- import { listGameEventConfig, addGameEventConfig, updateGameEventConfig, delGameEventConfig } from '@/api/system/gameEventConfig';
- import { GameEventConfigForm } from '@/api/system/gameEventConfig/types';
- import { listGameEventConfigType } from '@/api/system/gameEventConfigType'; // 添加导入
- import { GameEventConfigTypeVO } from '@/api/system/gameEventConfigType/types'; // 添加导入
- import { useRoute, useRouter } from 'vue-router';
- import { listRelateMenu, getEnabledNavigator, editRelate, type EditRelateMenuParams, GameNavigatorVo } from '@/api/system/common/nav/gameNavigator';
- const route = useRoute();
- const router = useRouter();
- const { proxy } = getCurrentInstance() as ComponentInternalInstance;
- const { game_event_type, game_event_purpose, game_event_status, sys_yes_no, game_project_type } = toRefs<any>(
- proxy?.useDict('game_event_type', 'game_event_purpose', 'game_event_status', 'sys_yes_no', 'game_project_type')
- );
- // 页面状态
- const isEdit = ref(false);
- const activeTab = ref('basic');
- const saveLoading = ref(false);
- // 判断是否为默认赛事操作
- const isDefaultEventOperation = () => {
- return basicForm.value.isDefault === '0';
- };
- // 获取有效的赛事ID(默认赛事返回空字符串,否则返回实际ID)
- const getEffectiveEventId = (eventId?: string | number): string => {
- if (isDefaultEventOperation()) {
- return '';
- }
- return String(eventId || (route.params.id as string) || '');
- };
- // 表单引用
- const basicFormRef = ref<ElFormInstance>();
- // 基本信息表单
- const basicForm = ref<GameEventForm>({
- eventCode: '',
- eventName: '',
- eventType: '11',
- location: '',
- purpose: '',
- startTime: '',
- endTime: '',
- eventUrl: '',
- refereeUrl: '',
- registerUrl: '',
- unit: '',
- isDefault: '1',
- status: '0',
- remark: ''
- });
- // 表单验证规则
- const basicRules = {
- eventCode: [{ required: true, message: '请输入赛事编号', trigger: 'blur' }],
- eventName: [{ required: true, message: '请输入赛事名称', trigger: 'blur' }],
- eventType: [{ required: true, message: '请选择赛事类型', trigger: 'change' }],
- startTime: [{ required: true, message: '请选择开始时间', trigger: 'change' }],
- endTime: [{ required: true, message: '请选择结束时间', trigger: 'change' }]
- };
- const currentEventId = ref<number>();
- // 初始化页面
- onMounted(async () => {
- const eventId = route.params.id as string;
- if (eventId) {
- isEdit.value = true;
- currentEventId.value = Number(eventId);
- await loadEventData(eventId);
- } else {
- // 新增模式,确保清除所有可能残留的数据
- isEdit.value = false;
- currentEventId.value = undefined;
- // 重置表单数据,确保不包含eventId
- basicForm.value = {
- eventCode: '',
- eventName: '',
- eventType: '11',
- location: '',
- purpose: '',
- startTime: '',
- endTime: '',
- eventUrl: '',
- refereeUrl: '',
- registerUrl: '',
- unit: '',
- isDefault: '1',
- status: '0',
- remark: ''
- };
- // 新增模式,加载图片配置模板
- // await loadImageConfigTemplates();
- }
- // 加载配置类型选项
- await loadConfigTypes();
- });
- // 加载赛事数据
- const loadEventData = async (eventId: string | number) => {
- try {
- const res = await getGameEvent(eventId);
- const data = res.data;
- // 填充基本信息
- Object.assign(basicForm.value, data);
- // 加载图片配置数据
- try {
- await loadImageConfigData(eventId);
- } catch (error) {
- console.warn('加载图片配置数据失败,继续加载其他数据:', error);
- // 不中断其他数据的加载
- }
- await loadMenuData(eventId); // 加载菜单数据
- await loadConfigData(eventId); // 加载配置数据
- } catch (error) {
- proxy?.$modal.msgError('加载赛事数据失败');
- }
- };
- /** 状态修改 */
- const handleStatusChange = async (row: GameEventVO) => {
- const text = row.isDefault === '0' ? '启用' : '停用';
- try {
- // 只有在编辑模式下才加载数据
- if (isEdit.value && row.eventId) {
- await loadEventData(row.eventId);
- }
- proxy?.$modal.msgSuccess(text + '成功');
- } catch {
- return;
- } finally {
- row.isDefault = row.isDefault === '0' ? '1' : '0';
- }
- };
- // 菜单列表数据
- const menuItems = ref<GameNavigatorVo[]>([]);
- // 菜单选择弹框相关数据
- const menuSelectDialogVisible = ref(false);
- const availableMenus = ref<any[]>([]);
- const selectedMenus = ref<any[]>([]);
- const menuSearchKeyword = ref('');
- // 过滤可用菜单的计算属性
- const filteredAvailableMenus = computed(() => {
- // 首先过滤掉已添加的菜单
- let filteredMenus = availableMenus.value.filter((menu) => {
- // 检查是否已存在相同的菜单(根据navId比较)
- return !menuItems.value.some((item) => item.navId === Number(menu.navId));
- });
- // 然后根据搜索关键词进一步过滤
- if (menuSearchKeyword.value) {
- filteredMenus = filteredMenus.filter((menu) =>
- menu.name?.toLowerCase().includes(menuSearchKeyword.value.toLowerCase())
- );
- }
- return filteredMenus;
- });
- // 加载菜单数据
- const loadMenuData = async (eventId: string | number) => {
- try {
- const res = await listRelateMenu({
- eventId: eventId,
- pageNum: 1,
- pageSize: 1000,
- orderByColumn: '',
- isAsc: ''
- });
- menuItems.value = Array.isArray(res.rows) ? res.rows : [];
- } catch (error) {
- proxy?.$modal.msgError('加载菜单数据失败');
- }
- };
- // 显示菜单选择弹框
- const showMenuSelectDialog = async () => {
- try {
- // 加载可用的导航菜单
- const res = await getEnabledNavigator();
- availableMenus.value = Array.isArray(res.data) ? res.data : [];
- selectedMenus.value = [];
- menuSearchKeyword.value = '';
- menuSelectDialogVisible.value = true;
- } catch (error) {
- proxy?.$modal.msgError('加载可用菜单失败');
- }
- };
- // 处理菜单选择变化
- const handleMenuSelectionChange = (selection: any[]) => {
- selectedMenus.value = selection;
- };
- // 确认添加菜单项
- const confirmAddMenuItems = async () => {
- console.log('selectedMenus:', selectedMenus.value);
- if (selectedMenus.value.length === 0) {
- proxy?.$modal.msgWarning('请选择要添加的菜单');
- return;
- }
- try {
- // 将选中的菜单添加到菜单列表中(无需重复检查,因为列表已经过滤掉了重复项)
- menuItems.value.push(...selectedMenus.value);
- // 如果是编辑模式,立即保存菜单数据到数据库
- // if (isEdit.value && currentEventId.value) {
- // await saveMenuData(currentEventId.value);
- // proxy?.$modal.msgSuccess(`成功添加 ${selectedMenus.value.length} 个菜单项并保存到数据库`);
- // } else {
- // // 新增模式下,菜单数据会在最终保存赛事时一起保存
- // proxy?.$modal.msgSuccess(`成功添加 ${selectedMenus.value.length} 个菜单项(将在保存赛事时一起保存)`);
- // }
- console.log('menuItems:', menuItems.value);
- menuSelectDialogVisible.value = false;
- } catch (error) {
- console.error('添加菜单项失败:', error);
- // 如果保存失败,回滚本地数组的更改
- menuItems.value.splice(-selectedMenus.value.length, selectedMenus.value.length);
- proxy?.$modal.msgError('添加菜单项失败,请重试');
- }
- };
- // 获取跳转类型标签
- const getJumpTypeLabel = (jumpType: number) => {
- const typeMap = {
- 1: '跳转链接',
- 2: '不跳转',
- 3: '小程序内链',
- 4: '小程序外链',
- 5: 'H5外链',
- 6: '公众号文章',
- 7: '公众号',
- 8: '电话拨号'
- };
- return typeMap[jumpType as keyof typeof typeMap] || '未知类型';
- };
- // 删除菜单项
- const removeMenuItem = async (index: number) => {
- try {
- // 从本地数组中删除元素
- menuItems.value.splice(index, 1);
- // 获取当前赛事ID
- const eventId = (route.params.id as string) || '';
- // 调用saveMenuData方法同步到后端
- await saveMenuData(eventId);
- proxy?.$modal.msgSuccess('删除菜单项成功');
- } catch (error) {
- console.error('删除菜单项失败:', error);
- proxy?.$modal.msgError('删除菜单项失败');
- }
- };
- // 保存菜单数据
- const saveMenuData = async (eventId: string | number) => {
- try {
- // 提取所有菜单的navId
- const menus = menuItems.value.map((item) => Number(item.navId)); // 转换为数字类型
- // 调用editRelate接口保存赛事关联菜单
- const relateData: EditRelateMenuParams = {
- eventId: eventId,
- menus: menus
- };
- await editRelate(relateData);
- } catch (error) {
- console.error('保存菜单数据失败:', error);
- throw new Error('保存菜单失败');
- }
- };
- // 图片配置数据
- const imageConfigItems = ref<GameEventConfigForm[]>([]);
- // 加载图片配置数据(用于编辑模式)
- const loadImageConfigData = async (eventId: string | number) => {
- try {
- // 先查询所有image类型的配置模板(不限制eventId,获取所有可用的图片配置项)
- const templateRes = await listGameEventConfig({
- configType: 'IMAGE',
- pageNum: 1,
- pageSize: 100,
- orderByColumn: '',
- isAsc: ''
- });
- // 获取所有图片配置模板
- const allImageConfigs = Array.isArray(templateRes.rows) ? templateRes.rows : [];
- // 查询当前赛事的图片配置数据(如果是默认赛事,eventId为空字符串)
- const eventRes = await listGameEventConfig({
- eventId: eventId === '' ? '' : eventId,
- configType: 'IMAGE',
- pageNum: 1,
- pageSize: 100,
- orderByColumn: '',
- isAsc: ''
- });
- const eventImageConfigs = Array.isArray(eventRes.rows) ? eventRes.rows : [];
- // 合并配置:以模板为基础,用当前赛事的数据覆盖
- imageConfigItems.value = allImageConfigs.map((template) => {
- const existingConfig = eventImageConfigs.find((item) => item.configKey === template.configKey);
- return {
- ...template,
- eventId: eventId,
- configValue: existingConfig?.configValue || '',
- isEnabled: existingConfig?.isEnabled || template.isEnabled || '0',
- status: existingConfig?.status || template.status || '0',
- configId: existingConfig?.configId
- };
- });
- } catch (error) {
- console.error('加载图片配置数据失败:', error);
- proxy?.$modal.msgError('加载图片配置数据失败: ' + (error as Error).message);
- imageConfigItems.value = [];
- }
- };
- // 刷新图片配置
- const refreshImageConfigs = async () => {
- const eventId = route.params.id as string;
- if (eventId && eventId !== 'add') {
- await loadImageConfigData(getEffectiveEventId(eventId));
- } else {
- // 新增模式,只加载配置模板
- // await loadImageConfigTemplates();
- }
- };
- // 保存图片配置数据
- const saveImageConfigData = async (eventId?: string | number) => {
- try {
- // 如果是默认赛事操作,使用空字符串作为eventId
- const targetEventId = eventId === '' ? '' : eventId || (route.params.id as string);
- const updates: GameEventConfigForm[] = [];
- const adds: GameEventConfigForm[] = [];
- // 收集需要更新和添加的数据
- for (const item of imageConfigItems.value) {
- if (item.configKey) {
- const configData: GameEventConfigForm = {
- ...item,
- eventId: targetEventId,
- configType: 'IMAGE'
- };
- if (item.configId && item.configValue) {
- updates.push(configData);
- } else if (!item.configId && item.configValue) {
- adds.push(configData);
- }
- }
- }
- // 批量更新
- if (updates.length > 0) {
- await Promise.all(updates.map(updateGameEventConfig));
- }
- // 批量添加
- if (adds.length > 0) {
- await Promise.all(adds.map(addGameEventConfig));
- }
- } catch (error) {
- console.error('保存图片配置数据失败:', error);
- throw new Error('保存图片配置失败');
- }
- };
- // 处理标签页切换
- const handleTabClick = () => {
- // 可以在这里添加标签页切换的逻辑
- };
- // 配置信息数据
- const configItems = ref<GameEventConfigForm[]>([]);
- // 配置类型选项
- const configTypes = ref<GameEventConfigTypeVO[]>([]);
- // 加载配置类型数据
- const loadConfigTypes = async () => {
- try {
- const res = await listGameEventConfigType({
- pageNum: 1,
- pageSize: 1000,
- orderByColumn: '',
- isAsc: ''
- });
- configTypes.value = Array.isArray(res.rows) ? res.rows : [];
- } catch (error) {
- proxy?.$modal.msgError('加载配置类型数据失败');
- }
- };
- // 加载赛事配置数据
- const loadConfigData = async (eventId: string | number) => {
- try {
- const res = await listGameEventConfig({
- eventId: eventId === '' ? '' : eventId,
- pageNum: 1,
- pageSize: 1000,
- orderByColumn: '',
- isAsc: ''
- });
- configItems.value = Array.isArray(res.rows) ? res.rows : [];
- } catch (error) {
- console.error('加载赛事配置数据失败:', error);
- proxy?.$modal.msgError('加载赛事配置数据失败: ' + (error as Error).message);
- }
- };
- // 添加配置项
- const addConfigItem = () => {
- configItems.value.push({
- configKey: '',
- configValue: '',
- configDesc: '',
- configType: '' // 添加配置类型字段
- });
- };
- // 删除配置项
- const removeConfigItem = (index: number) => {
- const configItem = configItems.value[index];
- if (configItem.configId) {
- delGameEventConfig(configItem.configId).then(() => {
- configItems.value.splice(index, 1);
- });
- } else {
- configItems.value.splice(index, 1);
- }
- };
- // 保存赛事配置数据
- const saveconfigData = async (eventId: string | number) => {
- try {
- for (const item of configItems.value) {
- // 确保eventId被正确设置
- const configData = { ...item, eventId };
- if (item.configId) {
- // 更新现有队伍
- await updateGameEventConfig(configData);
- } else if (item.configDesc) {
- // 只有有名称的新队伍才保存
- await addGameEventConfig(configData);
- }
- }
- } catch (error) {
- console.error('保存赛事配置信息失败:', error);
- throw new Error('保存赛事配置信息失败');
- }
- };
- // 保存赛事信息
- const saveEvent = async () => {
- let formData: GameEventForm;
- let savedEventId: string;
-
- try {
- // 验证基本信息表单
- await basicFormRef.value?.validate();
- saveLoading.value = true;
- // 合并表单数据
- formData = {
- ...basicForm.value
- };
-
- // 新增模式下,确保不包含eventId字段,避免主键冲突
- if (!isEdit.value) {
- console.log('新增模式,开始保存赛事信息');
- console.log('保存前的formData:', formData);
-
- // 三重保险:确保eventId被完全清除
- delete formData.eventId;
- delete basicForm.value.eventId;
-
- // 再次检查formData中是否还有eventId
- if (formData.eventId !== undefined) {
- console.warn('检测到formData中仍有eventId,强制清除:', formData.eventId);
- delete formData.eventId;
- }
-
- console.log('清除eventId后的formData:', formData);
-
- // 如果设置为默认赛事,则取消其他赛事的默认状态
- if (basicForm.value.isDefault === '0') {
- console.log('设置为默认赛事,调用handleStatusChange');
- handleStatusChange({
- eventId: '', // 新增时没有eventId
- isDefault: basicForm.value.isDefault,
- eventName: basicForm.value.eventName
- } as GameEventVO);
- }
- // 保存基本信息
- console.log('调用addGameEvent API');
- const addRes = await addGameEvent(formData);
- console.log('addGameEvent 响应:', addRes);
- // 获取新创建的赛事ID
- savedEventId = addRes?.data as string;
- console.log('获取到的新赛事ID:', savedEventId);
- } else {
- savedEventId = route.params.id as string;
-
- // 编辑模式下,如果设置为默认赛事,则取消其他赛事的默认状态
- if (basicForm.value.isDefault === '0') {
- handleStatusChange({
- eventId: basicForm.value.eventId,
- isDefault: basicForm.value.isDefault,
- eventName: basicForm.value.eventName
- } as GameEventVO);
- }
-
- // 更新基本信息
- await updateGameEvent(formData);
- }
-
- // 保存图片配置数据
- await saveImageConfigData(savedEventId);
- // 保存赛事配置项数据
- await saveconfigData(savedEventId);
- // 保存菜单数据
- await saveMenuData(savedEventId);
- proxy?.$modal.msgSuccess('保存成功');
- // 保存成功后,设置一个标识,表示需要刷新列表数据
- sessionStorage.setItem('needRefreshGameEventList', 'true');
- goBack();
- } catch (error) {
- console.error('保存失败:', error);
- console.error('错误详情:', {
- message: error instanceof Error ? error.message : String(error),
- stack: error instanceof Error ? error.stack : undefined,
- formData: formData,
- isEdit: isEdit.value,
- currentEventId: currentEventId.value
- });
- proxy?.$modal.msgError(`保存失败: ${error instanceof Error ? error.message : String(error)}`);
- } finally {
- saveLoading.value = false;
- }
- };
- // 返回上一页
- const goBack = () => {
- router.go(-1);
- };
- </script>
- <style lang="scss" scoped>
- .game-event-edit {
- .page-header {
- display: flex;
- align-items: center;
- gap: 16px;
- .page-title {
- font-size: 18px;
- font-weight: 600;
- }
- }
- .menu-config,
- .project-config,
- .config-info,
- .image-config {
- .menu-header,
- .project-header,
- .config-header,
- .image-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 16px;
- h3 {
- margin: 0;
- font-size: 16px;
- font-weight: 600;
- }
- }
- }
- .image-config {
- .config-info {
- margin-top: 8px;
- display: flex;
- align-items: center;
- justify-content: space-between;
- }
- }
- .team-config {
- .team-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 16px;
- h3 {
- margin: 0;
- font-size: 16px;
- font-weight: 600;
- }
- }
- }
- .group-config {
- .group-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 16px;
- h3 {
- margin: 0;
- font-size: 16px;
- font-weight: 600;
- }
- }
- }
- .form-actions {
- display: flex;
- justify-content: center;
- gap: 16px;
- margin-top: 32px;
- padding-top: 24px;
- border-top: 1px solid #ebeef5;
- }
- }
- :deep(.el-tabs__content) {
- padding: 20px 0;
- }
- :deep(.el-form-item) {
- margin-bottom: 20px;
- }
- </style>
|