| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859 |
- <template>
- <div class="p-2 page-container">
- <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
- <div v-show="showSearch" class="mb-[10px]">
- <el-card shadow="hover">
- <el-form ref="queryFormRef" :model="queryParams" label-width="100px">
- <el-row :gutter="20">
- <el-col :span="6">
- <el-form-item label="活动名称" prop="activityName">
- <el-input v-model="queryParams.activityName" placeholder="请输入活动名称" clearable @keyup.enter="handleQuery" />
- </el-form-item>
- </el-col>
- <el-col :span="6">
- <el-form-item label="活动类型" prop="activityType">
- <el-select v-model="queryParams.activityType" placeholder="请选择活动类型" clearable style="width: 100%">
- <el-option v-for="dict in stgl_activity_type" :key="dict.value" :label="dict.label" :value="dict.value" />
- </el-select>
- </el-form-item>
- </el-col>
- <el-col :span="6">
- <el-form-item label="主办方" prop="organizerName">
- <el-input v-model="queryParams.organizerName" placeholder="请输入主办方名称" clearable @keyup.enter="handleQuery" />
- </el-form-item>
- </el-col>
- <el-col :span="6">
- <el-form-item label="报名方式" prop="registrationType">
- <el-select v-model="queryParams.registrationType" placeholder="请选择报名方式" clearable style="width: 100%">
- <el-option v-for="dict in stgl_registration_type" :key="dict.value" :label="dict.label" :value="dict.value" />
- </el-select>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row>
- <el-col :span="24" class="search-btn-container">
- <el-form-item>
- <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
- <el-button icon="Refresh" @click="resetQuery">重置</el-button>
- </el-form-item>
- </el-col>
- </el-row>
- </el-form>
- </el-card>
- </div>
- </transition>
- <el-card shadow="never" class="button-card table-card">
- <template #header>
- <el-row :gutter="10" class="mb8">
- <el-col :span="1.5">
- <span class="page-title">活动报名大厅</span>
- </el-col>
- <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
- </el-row>
- </template>
- <el-table v-loading="loading" border :data="activityList" @row-dblclick="handleView">
- <el-table-column label="活动名称" align="center" prop="activityName" min-width="150" show-overflow-tooltip />
- <el-table-column label="活动类型" align="center" prop="activityType" width="100">
- <template #default="scope">
- <dict-tag :options="stgl_activity_type" :value="scope.row.activityType" />
- </template>
- </el-table-column>
- <el-table-column label="主办方" align="center" prop="organizerName" min-width="150" show-overflow-tooltip />
- <el-table-column label="关联社团/队伍" align="center" min-width="150" show-overflow-tooltip>
- <template #default="scope">
- <span v-if="scope.row.relatedClubName">{{ scope.row.relatedClubName }}</span>
- <span v-else class="text-gray-400">未关联</span>
- </template>
- </el-table-column>
- <el-table-column label="活动时间" align="center" width="160">
- <template #default="scope">
- <div v-if="scope.row.startTime && scope.row.endTime">
- <div>{{ formatDate(scope.row.startTime) }}</div>
- <div class="text-sm text-gray-500">{{ formatDate(scope.row.endTime) }}</div>
- </div>
- <span v-else class="text-gray-400">未设置</span>
- </template>
- </el-table-column>
- <el-table-column label="报名时间" align="center" width="160">
- <template #default="scope">
- <div v-if="scope.row.registrationStart && scope.row.registrationEnd">
- <div>{{ formatDate(scope.row.registrationStart) }}</div>
- <div class="text-sm text-gray-500">{{ formatDate(scope.row.registrationEnd) }}</div>
- </div>
- <span v-else class="text-gray-400">未设置</span>
- </template>
- </el-table-column>
- <el-table-column label="报名方式" align="center" prop="registrationType" width="100">
- <template #default="scope">
- <dict-tag :options="stgl_registration_type" :value="scope.row.registrationType" />
- </template>
- </el-table-column>
- <el-table-column label="报名状态" align="center" prop="registrationStatus" width="100">
- <template #default="scope">
- <dict-tag :options="stgl_registration_status" :value="scope.row.registrationStatus" />
- </template>
- </el-table-column>
- <el-table-column label="报名人数" align="center" width="100">
- <template #default="scope">
- <el-tag type="info" size="small">{{ scope.row.registrationCount || 0 }}</el-tag>
- </template>
- </el-table-column>
- <el-table-column label="审核设置" align="center" width="100">
- <template #default="scope">
- <el-tag v-if="scope.row.needApproval === 0" type="success" size="small">无需审核</el-tag>
- <el-tag v-else type="warning" size="small">需要审核</el-tag>
- </template>
- </el-table-column>
- <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180" fixed="right">
- <template #default="scope">
- <el-tooltip content="查看详情" placement="top">
- <el-button
- link
- type="primary"
- icon="View"
- size="default"
- style="font-size: 16px; margin-right: 8px; color: blue"
- @click="handleView(scope.row)"
- ></el-button>
- </el-tooltip>
- <el-tooltip content="活动报名" placement="top" v-if="canRegister(scope.row)">
- <el-button
- link
- type="success"
- icon="Plus"
- size="default"
- style="font-size: 16px; margin-right: 8px"
- @click="handleRegister(scope.row)"
- ></el-button>
- </el-tooltip>
- <el-tooltip content="已报名" placement="top" v-else-if="isRegistered(scope.row)">
- <el-button link type="warning" icon="Check" size="default" style="font-size: 16px" disabled></el-button>
- </el-tooltip>
- <el-tooltip content="报名已结束" placement="top" v-else>
- <el-button link type="info" icon="Clock" size="default" style="font-size: 16px" disabled></el-button>
- </el-tooltip>
- </template>
- </el-table-column>
- </el-table>
- <div class="pagination-container">
- <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
- </div>
- </el-card>
- <!-- 查看活动详细信息对话框 -->
- <el-dialog :title="viewDialog.title" v-model="viewDialog.visible" width="1200px" append-to-body>
- <ActivityDetailView :activity="viewForm" />
-
- <template #footer>
- <div class="dialog-footer">
- <el-button type="primary" @click="handleRegister(viewForm)" v-if="canRegister(viewForm)">立即报名</el-button>
- <el-button @click="viewDialog.visible = false">关 闭</el-button>
- </div>
- </template>
- </el-dialog>
- <!-- 活动报名对话框 -->
- <el-dialog title="活动报名" v-model="registerDialog.visible" width="1000px" append-to-body>
- <el-form ref="registerFormRef" :model="registerForm" :rules="registerRules" label-width="120px">
- <el-form-item label="活动名称">
- <el-input v-model="selectedActivity.activityName" disabled />
- </el-form-item>
- <!-- 审核设置提示 -->
- <el-form-item label="审核设置">
- <el-alert
- v-if="selectedActivity.needApproval === 0"
- title="无需审核"
- type="success"
- description="该活动设置为无需审核,报名后将自动通过"
- :closable="false"
- show-icon
- />
- <el-alert
- v-else
- title="需要审核"
- type="info"
- description="该活动设置为需要审核,报名后需要等待管理员审核通过"
- :closable="false"
- show-icon
- />
- </el-form-item>
- <el-form-item label="报名类型" prop="registrationType">
- <el-radio-group v-model="registerForm.registrationType" @change="handleRegistrationTypeChange">
- <el-radio v-if="isRegistrationTypeAllowed(1)" :value="1">个人报名</el-radio>
- <el-radio v-if="isRegistrationTypeAllowed(2)" :value="2">团队报名</el-radio>
- </el-radio-group>
- </el-form-item>
- <!-- 个人报名信息 -->
- <div v-if="registerForm.registrationType === 1">
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="姓名" prop="studentName">
- <el-input v-model="registerForm.studentName" readonly />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="学号" prop="studentNo">
- <el-input v-model="registerForm.studentNo" readonly />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="性别" prop="gender">
- <el-select v-model="registerForm.gender" disabled style="width: 100%">
- <el-option label="男" value="0" />
- <el-option label="女" value="1" />
- </el-select>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="联系电话" prop="phone">
- <el-input v-model="registerForm.phone" />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="院系" prop="department">
- <el-input v-model="registerForm.department" readonly />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="专业" prop="major">
- <el-input v-model="registerForm.major" readonly />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="班级" prop="className">
- <el-input v-model="registerForm.className" readonly />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="邮箱" prop="email">
- <el-input v-model="registerForm.email" />
- </el-form-item>
- </el-col>
- </el-row>
- </div>
- <!-- 团队报名信息 -->
- <div v-if="registerForm.registrationType === 2">
- <el-form-item label="团队名称" prop="teamName">
- <el-input v-model="registerForm.teamName" placeholder="请输入团队名称" />
- </el-form-item>
- <el-form-item label="团队描述" prop="teamDescription">
- <el-input v-model="registerForm.teamDescription" type="textarea" :rows="3" placeholder="请输入团队描述" />
- </el-form-item>
- <!-- 团队负责人信息 -->
- <el-divider content-position="left">团队负责人(当前用户)</el-divider>
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="负责人姓名" prop="studentName">
- <el-input v-model="registerForm.studentName" readonly />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="负责人学号" prop="studentNo">
- <el-input v-model="registerForm.studentNo" readonly />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="性别" prop="gender">
- <el-select v-model="registerForm.gender" disabled style="width: 100%">
- <el-option label="男" value="0" />
- <el-option label="女" value="1" />
- </el-select>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="联系电话" prop="phone">
- <el-input v-model="registerForm.phone" readonly />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="院系" prop="department">
- <el-input v-model="registerForm.department" readonly />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="专业" prop="major">
- <el-input v-model="registerForm.major" readonly />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="班级" prop="className">
- <el-input v-model="registerForm.className" readonly />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="邮箱" prop="email">
- <el-input v-model="registerForm.email" readonly />
- </el-form-item>
- </el-col>
- </el-row>
- <!-- 团队成员管理 -->
- <el-divider content-position="left" style="margin-left: 0px">团队成员</el-divider>
- <VicePresidentManager
- :model-value="registerForm.teamMembersNew"
- title="团队管理"
- addButtonText="添加团队成员"
- emptyTip="暂无团队成员,点击上方按钮添加"
- selectPlaceholder="选择团队成员"
- @change="handleTeamMembersNewChange"
- />
- </div>
- <el-form-item label="申请理由" prop="remark" style="margin-top: 24px">
- <el-input v-model="registerForm.remark" type="textarea" :rows="4" placeholder="请简要说明您的申请理由和个人优势(选填)" />
- </el-form-item>
- </el-form>
- <template #footer>
- <div class="dialog-footer">
- <el-button :loading="registerLoading" type="primary" @click="submitRegister">提交报名</el-button>
- <el-button @click="registerDialog.visible = false">取 消</el-button>
- </div>
- </template>
- </el-dialog>
- </div>
- </template>
- <script setup name="StglActivityRegisterHall" lang="ts">
- import { nextTick } from 'vue';
- import { CircleCheck, Clock } from '@element-plus/icons-vue';
- import {
- listRegistrableActivities,
- getActivityDetail,
- registerActivity,
- checkRegistration,
- getMyRegistrations
- } from '@/api/stgl/activityregisterhall';
- import { StglActivityVO, StglActivityQuery } from '@/api/stgl/activity/types';
- import { StglActivityRegistrationForm, TeamMemberInfo, StglActivityVo } from '@/api/stgl/activityregisterhall/types';
- import ActivityDetailView from '@/views/stgl/activity/components/ActivityDetailView.vue';
- import TeamMemberManager from '@/components/TeamMemberManager/index.vue';
- import VicePresidentManager from '@/components/VicePresidentManager/index.vue';
- import StudentSelector from '@/components/StudentSelector/index.vue';
- import { getPersonalInfo } from '@/api/xg/xsjcxx/studentMsg/studentMsg/index';
- import type { StudentMsgForm } from '@/api/xg/xsjcxx/studentMsg/studentMsg/types';
- import { StudentVO } from '@/api/xg/student/types';
- import { VicePresidentVO } from '@/components/VicePresidentManager/index.vue';
- import { getUser } from '@/api/system/user';
- const { proxy } = getCurrentInstance() as ComponentInternalInstance;
- const { stgl_activity_type, stgl_registration_type, stgl_registration_status } = toRefs<any>(
- proxy?.useDict('stgl_activity_type', 'stgl_registration_type', 'stgl_registration_status')
- );
- // 修改类型定义,使用后端返回的StglActivityVo类型
- const activityList = ref<StglActivityVo[]>([]);
- const loading = ref(true);
- const showSearch = ref(true);
- const total = ref(0);
- const registerLoading = ref(false);
- const queryFormRef = ref<ElFormInstance>();
- const registerFormRef = ref<ElFormInstance>();
- const viewDialog = reactive<DialogOption>({
- visible: false,
- title: ''
- });
- const registerDialog = reactive<DialogOption>({
- visible: false,
- title: ''
- });
- const selectedActivity = ref<StglActivityVo>({} as StglActivityVo);
- const viewForm = ref<StglActivityVo>({} as StglActivityVo);
- // 用户报名状态缓存
- const userRegistrationStatus = ref<Record<number, boolean>>({});
- const data = reactive<PageData<StglActivityRegistrationForm, StglActivityQuery>>({
- form: {
- activityId: undefined,
- registrationType: undefined,
- studentName: undefined,
- studentNo: undefined
- } as StglActivityRegistrationForm,
- queryParams: {
- pageNum: 1,
- pageSize: 10,
- activityName: undefined,
- activityType: undefined,
- organizerName: undefined,
- registrationType: undefined,
- params: {}
- },
- rules: {}
- });
- const { queryParams } = toRefs(data);
- // 报名表单
- const registerForm = reactive<
- StglActivityRegistrationForm & {
- presidentStudent?: StudentVO | null;
- teamMembersNew?: VicePresidentVO[];
- }
- >({
- activityId: undefined,
- registrationType: undefined,
- studentName: undefined,
- studentNo: undefined,
- gender: undefined,
- phone: undefined,
- email: undefined,
- department: undefined,
- major: undefined,
- className: undefined,
- teamName: undefined,
- teamDescription: undefined,
- teamMembers: [], // 保留原有字段,用于兼容
- teamMembersNew: [], // 新增:使用VicePresidentVO结构的团队成员
- remark: undefined,
- presidentStudent: null // 新增:团队负责人学生对象
- });
- const registerRules = reactive({
- registrationType: [{ required: true, message: '请选择报名类型', trigger: 'change' }],
- presidentStudent: [{ required: true, message: '请选择团队负责人', trigger: 'change' }],
- studentNo: [{ required: true, message: '学号不能为空', trigger: 'blur' }],
- phone: [
- { required: true, message: '联系电话不能为空', trigger: 'blur' },
- {
- pattern: /^1[3-9]\d{9}$/,
- message: '请输入正确的手机号码',
- trigger: 'blur'
- } as any
- ],
- teamName: [{ required: true, message: '团队名称不能为空', trigger: 'blur' }]
- } as any);
- /** 查询活动列表 */
- const getList = async () => {
- loading.value = true;
- try {
- const res = await listRegistrableActivities(queryParams.value);
- activityList.value = res.rows || [];
- total.value = res.total || 0;
- // 批量检查用户报名状态
- await checkUserRegistrationStatus();
- } catch (error) {
- console.error('查询活动列表失败:', error);
- proxy?.$modal.msgError('查询活动列表失败');
- // 发生错误时重置数据
- activityList.value = [];
- total.value = 0;
- } finally {
- loading.value = false;
- }
- };
- /** 批量检查用户报名状态 */
- const checkUserRegistrationStatus = async () => {
- // 防御性检查:确保activityList存在且为数组
- if (!activityList.value || !Array.isArray(activityList.value) || activityList.value.length === 0) {
- console.warn('活动列表为空或无效,跳过报名状态检查');
- return;
- }
- const promises = activityList.value.map(async (activity) => {
- try {
- // 确保activity和activity.id存在
- if (!activity || !activity.id) {
- console.warn('活动数据不完整,跳过报名状态检查:', activity);
- return;
- }
-
- const registered = await checkRegistration(activity.id as number);
- userRegistrationStatus.value[activity.id as number] = registered.data;
- } catch (error) {
- console.error(`检查活动${activity?.id}报名状态失败:`, error);
- if (activity?.id) {
- userRegistrationStatus.value[activity.id as number] = false;
- }
- }
- });
- await Promise.all(promises);
- };
- /** 搜索按钮操作 */
- const handleQuery = () => {
- queryParams.value.pageNum = 1;
- getList();
- };
- /** 重置按钮操作 */
- const resetQuery = () => {
- queryFormRef.value?.resetFields();
- handleQuery();
- };
- /** 查看按钮操作 */
- const handleView = async (row: StglActivityVo) => {
- const res = await getActivityDetail(row.id);
- viewForm.value = res.data;
- viewDialog.visible = true;
- viewDialog.title = '查看活动信息';
- };
- /** 报名按钮操作 */
- const handleRegister = async (row: StglActivityVo) => {
- selectedActivity.value = row;
- resetRegisterForm();
- registerDialog.visible = true;
- };
- /** 重置报名表单 */
- const resetRegisterForm = () => {
- Object.assign(registerForm, {
- activityId: selectedActivity.value.id,
- registrationType: undefined,
- studentName: undefined,
- studentNo: undefined,
- gender: undefined,
- phone: undefined,
- email: undefined,
- department: undefined,
- major: undefined,
- className: undefined,
- teamName: undefined,
- teamDescription: undefined,
- teamMembers: [],
- teamMembersNew: [],
- remark: undefined,
- presidentStudent: null
- });
- nextTick(() => {
- registerFormRef.value?.resetFields();
- });
- };
- /** 加载用户信息到报名表单 */
- const loadUserInfoToForm = async () => {
- try {
- const response = await getPersonalInfo();
- const studentInfo: StudentMsgForm = response.data;
- if (studentInfo) {
- registerForm.studentName = studentInfo.name || '';
- registerForm.studentNo = studentInfo.studentNo || '';
- registerForm.gender = studentInfo.gender || '';
- registerForm.phone = studentInfo.phone || '';
- registerForm.email = studentInfo.email || '';
- registerForm.department = studentInfo.collegeName || '';
- registerForm.major = studentInfo.majorName || '';
- registerForm.className = studentInfo.className || '';
- } else {
- proxy?.$modal.msgWarning('未能获取到用户信息,请手动填写报名表单');
- }
- } catch (error) {
- console.error('获取用户信息失败:', error);
- proxy?.$modal.msgWarning('获取用户信息失败,请联系管理员或手动填写');
- }
- };
- /** 报名类型变化处理 */
- const handleRegistrationTypeChange = async (value: number) => {
- if (value === 1) {
- // 个人报名,清空团队相关信息并自动填充当前用户信息
- registerForm.teamName = undefined;
- registerForm.teamDescription = undefined;
- registerForm.teamMembers = [];
- registerForm.teamMembersNew = [];
- registerForm.presidentStudent = null;
- // 自动填充当前用户信息
- await loadUserInfoToForm();
- } else if (value === 2) {
- // 团队报名,自动填充当前用户信息作为团队负责人
- await loadUserInfoToForm();
-
- // 设置团队负责人为学生对象(用于StudentSelector组件)
- // 使用类型断言避免类型错误,因为我们只需要这些字段用于显示
- registerForm.presidentStudent = {
- id: 0, // 临时ID,实际提交时不需要
- name: registerForm.studentName || '',
- studentNo: registerForm.studentNo || '',
- gender: registerForm.gender || '',
- phone: registerForm.phone || '',
- email: registerForm.email || '',
- collegeId: '', // 必需的字段
- collegeName: registerForm.department || '',
- majorId: '', // 必需的字段
- majorName: registerForm.major || '',
- classId: '', // 必需的字段
- className: registerForm.className || '',
- grade: '', // 必需的字段
- studentStatus: '', // 必需的字段
- enrollmentYear: 0 // 必需的字段
- } as StudentVO;
- }
- };
- /** 团队负责人选择变化处理 */
- const handlePresidentChange = async (student: StudentVO | null) => {
- if (student) {
- // 自动填充负责人信息
- registerForm.studentName = student.name || '';
- registerForm.studentNo = student.studentNo || '';
- registerForm.gender = student.gender || '';
- registerForm.phone = student.phone || '';
- registerForm.department = student.collegeName || '';
- registerForm.major = student.majorName || '';
- registerForm.className = student.className || '';
- // 获取用户邮箱
- try {
- const userRes = await getUser(student.id);
- registerForm.email = userRes.data?.user?.email || '';
- } catch (error) {
- console.error('获取用户邮箱失败:', error);
- registerForm.email = ''; // 设置为空,让用户手动填写或通过其他方式获取
- }
- } else {
- // 清空负责人信息
- registerForm.studentName = undefined;
- registerForm.studentNo = undefined;
- registerForm.gender = undefined;
- registerForm.phone = undefined;
- registerForm.email = undefined;
- registerForm.department = undefined;
- registerForm.major = undefined;
- registerForm.className = undefined;
- }
- };
- /** 新版团队成员变化处理 */
- const handleTeamMembersNewChange = (members: VicePresidentVO[]) => {
- registerForm.teamMembersNew = members;
- // 同步到原有字段,用于兼容后端
- registerForm.teamMembers = members.map((member) => ({
- userId: member.student?.id || 0,
- studentNo: member.student?.studentNo || '',
- studentName: member.name || member.student?.name || '',
- gender: member.student?.gender || '',
- phone: member.phone || member.student?.phone || '',
- email: '', // VicePresidentVO没有email字段,设置为空
- department: member.dept || member.student?.collegeName || '',
- major: member.major || member.student?.majorName || '',
- className: member.class || member.student?.className || '',
- isLeader: 0 // 团队成员,非负责人
- }));
- // 验证团队人数限制
- const totalMembers = members.length + 1; // 包含负责人
- if (selectedActivity.value.teamSizeMin && totalMembers < selectedActivity.value.teamSizeMin) {
- proxy?.$modal.msgWarning(`团队人数不能少于${selectedActivity.value.teamSizeMin}人`);
- }
- if (selectedActivity.value.teamSizeMax && totalMembers > selectedActivity.value.teamSizeMax) {
- proxy?.$modal.msgWarning(`团队人数不能超过${selectedActivity.value.teamSizeMax}人`);
- }
- };
- /** 团队成员变化处理(兼容原有方法) */
- const handleTeamMembersChange = (members: TeamMemberInfo[]) => {
- registerForm.teamMembers = members;
- // 验证团队人数限制
- const totalMembers = members.length + 1; // 包含负责人
- if (selectedActivity.value.teamSizeMin && totalMembers < selectedActivity.value.teamSizeMin) {
- proxy?.$modal.msgWarning(`团队人数不能少于${selectedActivity.value.teamSizeMin}人`);
- }
- if (selectedActivity.value.teamSizeMax && totalMembers > selectedActivity.value.teamSizeMax) {
- proxy?.$modal.msgWarning(`团队人数不能超过${selectedActivity.value.teamSizeMax}人`);
- }
- };
- /** 提交报名 */
- const submitRegister = () => {
- registerFormRef.value?.validate(async (valid: boolean) => {
- if (valid) {
- // 团队报名时验证人数限制
- if (registerForm.registrationType === 2) {
- const totalMembers = (registerForm.teamMembersNew?.length || 0) + 1;
- if (selectedActivity.value.teamSizeMin && totalMembers < selectedActivity.value.teamSizeMin) {
- proxy?.$modal.msgError(`团队人数不能少于${selectedActivity.value.teamSizeMin}人,当前${totalMembers}人`);
- return;
- }
- if (selectedActivity.value.teamSizeMax && totalMembers > selectedActivity.value.teamSizeMax) {
- proxy?.$modal.msgError(`团队人数不能超过${selectedActivity.value.teamSizeMax}人,当前${totalMembers}人`);
- return;
- }
- }
- registerLoading.value = true;
- try {
- // 根据报名类型准备不同的提交数据
- const submitData: any = {
- activityId: registerForm.activityId,
- registrationType: registerForm.registrationType,
- studentName: registerForm.studentName,
- studentNo: registerForm.studentNo,
- gender: registerForm.gender,
- phone: registerForm.phone,
- email: registerForm.email,
- department: registerForm.department,
- major: registerForm.major,
- className: registerForm.className,
- remark: registerForm.remark
- };
- // 根据活动的审核设置自动设置报名状态
- // 如果活动设置为不需要审核(needApproval = 0),则自动设置为通过状态(approvalStatus = 1)
- // 如果活动设置为需要审核(needApproval = 1),则保持默认的待审核状态(approvalStatus = 0)
- if (selectedActivity.value.needApproval === 0) {
- submitData.approvalStatus = 1; // 自动通过
- } else {
- submitData.approvalStatus = 0; // 待审核
- }
- // 只有团队报名时才发送团队相关字段
- if (registerForm.registrationType === 2) {
- submitData.teamName = registerForm.teamName;
- submitData.teamDescription = registerForm.teamDescription;
- // 将团队成员数组转换为JSON字符串(后端期望String类型)
- if (registerForm.teamMembers && Array.isArray(registerForm.teamMembers)) {
- submitData.teamMembers = JSON.stringify(registerForm.teamMembers);
- } else {
- submitData.teamMembers = JSON.stringify([]);
- }
- }
- // 个人报名时不发送任何团队相关字段
- await registerActivity(submitData);
-
- // 根据审核设置显示不同的成功消息
- if (selectedActivity.value.needApproval === 0) {
- proxy?.$modal.msgSuccess('报名成功!您的报名已自动通过审核');
- } else {
- proxy?.$modal.msgSuccess('报名成功,请等待审核');
- }
-
- registerDialog.visible = false;
- // 更新报名状态
- userRegistrationStatus.value[selectedActivity.value.id as number] = true;
- } catch (error) {
- console.error('报名失败:', error);
- const errorMsg = (error as any)?.response?.data?.msg || (error as any)?.message || '报名失败,请稍后重试';
- proxy?.$modal.msgError(errorMsg);
- } finally {
- registerLoading.value = false;
- }
- }
- });
- };
- /** 判断是否可以报名 */
- const canRegister = (activity: StglActivityVo): boolean => {
- // 报名状态为0(未开始)或1(报名中),且用户未报名
- return [0, 1].includes(activity.registrationStatus || 0) && !isRegistered(activity);
- };
- /** 判断用户是否已报名 */
- const isRegistered = (activity: StglActivityVo): boolean => {
- return userRegistrationStatus.value[activity.id as number] || false;
- };
- /** 判断报名类型是否允许 */
- const isRegistrationTypeAllowed = (type: number): boolean => {
- const activityType = Number(selectedActivity.value.registrationType);
- return activityType === 3 || activityType === type; // 3表示两者均可
- };
- /** 格式化日期 */
- const formatDate = (dateStr: string): string => {
- if (!dateStr) return '';
- const date = new Date(dateStr);
- return date.toLocaleString('zh-CN', {
- month: '2-digit',
- day: '2-digit',
- hour: '2-digit',
- minute: '2-digit'
- });
- };
- onMounted(() => {
- getList();
- });
- </script>
- <style scoped>
- /* 页面容器样式 */
- .page-container {
- padding: 8px;
- background-color: #f5f5f5;
- }
- /* 表格卡片布局 */
- .table-card {
- margin-top: 0;
- border-radius: 12px;
- border: 1px solid #e4e7ed;
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
- }
- .table-card :deep(.el-card__body) {
- padding: 0px 20px 20px 20px !important;
- }
- /* 移除按钮栏底部边框 */
- .button-card :deep(.el-card__header) {
- border-bottom: none !important;
- background: linear-gradient(135deg, #fafbff 0%, #f8fafc 100%);
- padding: 16px 20px;
- }
- /* 页面标题 */
- .page-title {
- font-size: 18px;
- font-weight: 600;
- color: #303133;
- }
- /* 分页容器样式 */
- .pagination-container {
- display: flex;
- justify-content: flex-end;
- padding: 16px 20px 0 0 !important;
- background-color: #fff;
- margin-top: 0px !important;
- }
- /* 搜索按钮容器样式 */
- .search-btn-container {
- display: flex;
- justify-content: flex-end;
- margin-top: 10px;
- .el-form-item {
- margin-bottom: 0 !important;
- }
- }
- </style>
|