2
0

2 کامیت‌ها b2cc3df51e ... bb2a04ffb9

نویسنده SHA1 پیام تاریخ
  李旭明 bb2a04ffb9 Merge branch 'master' of http://47.99.164.66:3000/hzdyjs-xg/all-project 1 سال پیش
  李旭明 e80446145f lxm0901 1 سال پیش

+ 1 - 1
backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/bo/StglClassBo.java

@@ -30,7 +30,7 @@ public class StglClassBo extends BaseEntity {
     /**
      * 学生姓名
      */
-    private String name;
+    private String studentName;
 
     /**
      * 性别

+ 7 - 0
backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/vo/StglActivityVo.java

@@ -217,11 +217,18 @@ public class StglActivityVo implements Serializable {
 
     /**
      * 活动状态
+     * 注意:此字段返回的是根据时间动态计算后的状态
      */
     @ExcelProperty(value = "活动状态", converter = ExcelDictConvert.class, index = 24)
     @ExcelDictFormat(dictType = "stgl_activity_status")
     private String activityStatus;
 
+    /**
+     * 原始活动状态(数据库中存储的实际状态)
+     * 用于权限控制和业务逻辑判断
+     */
+    private String originalActivityStatus;
+
     /**
      * 是否为已办活动
      */

+ 3 - 3
backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/service/impl/StglClassServiceImpl.java

@@ -126,8 +126,8 @@ public class StglClassServiceImpl implements IStglClassService {
         if (StringUtils.isNotBlank(bo.getClassId())) {
             params.put("classId", bo.getClassId());
         }
-        if (StringUtils.isNotBlank(bo.getName())) {
-            params.put("studentName", bo.getName());
+        if (StringUtils.isNotBlank(bo.getStudentName())) {
+            params.put("studentName", bo.getStudentName());
         }
         if (StringUtils.isNotBlank(bo.getStudentNo())) {
             params.put("studentNo", bo.getStudentNo());
@@ -145,7 +145,7 @@ public class StglClassServiceImpl implements IStglClassService {
         Map<String, Object> params = bo.getParams();
         LambdaQueryWrapper<StglClass> lqw = Wrappers.lambdaQuery();
         lqw.eq(StringUtils.isNotBlank(bo.getClassId()), StglClass::getClassId, bo.getClassId());
-        lqw.like(StringUtils.isNotBlank(bo.getName()), StglClass::getName, bo.getName());
+        lqw.like(StringUtils.isNotBlank(bo.getStudentName()), StglClass::getName, bo.getStudentName());
         lqw.like(StringUtils.isNotBlank(bo.getStudentNo()), StglClass::getStudentNo, bo.getStudentNo());
         return lqw;
     }

+ 41 - 1
backend/ruoyi-modules/ruoyi-stgl/src/main/resources/mapper/stgl/StglActivityMapper.xml

@@ -34,6 +34,7 @@
         <result property="needApproval" column="need_approval"/>
         <result property="activityRange" column="activity_range"/>
         <result property="activityStatus" column="activity_status"/>
+        <result property="originalActivityStatus" column="original_activity_status"/>
         <result property="isFinished" column="is_finished"/>
         <result property="summary" column="summary"/>
         <result property="summaryAttachments" column="summary_attachments"/>
@@ -81,7 +82,26 @@
                 ELSE sa.registration_status
             END AS registration_status,
             sa.max_participants, sa.max_teams, sa.team_size_min, sa.team_size_max, sa.need_approval, sa.activity_range,
-            sa.activity_status, sa.is_finished, sa.summary, sa.summary_attachments, sa.achievements, sa.achievements_attachments, sa.import_source,
+            -- 动态计算活动状态:审批通过后根据时间自动更新状态
+            CASE 
+                -- 手动控制的状态保持不变(草稿、待审批、已取消、已驳回)
+                WHEN sa.activity_status IN ('0', '2', '6', '7') THEN sa.activity_status
+                
+                -- 审批通过后的状态根据时间自动计算
+                WHEN sa.activity_status IN ('3', '4', '5') THEN
+                    CASE 
+                        <![CDATA[WHEN NOW() < sa.start_time THEN '3']]>        -- 已通过(未开始)
+                        <![CDATA[WHEN NOW() >= sa.start_time AND NOW() <= sa.end_time THEN '4']]>  -- 进行中
+                        <![CDATA[WHEN NOW() > sa.end_time THEN '5']]>          -- 已结束
+                        ELSE sa.activity_status
+                    END
+                
+                -- 其他情况保持原状态
+                ELSE sa.activity_status
+            END AS activity_status,
+            -- 返回原始活动状态(用于权限控制)
+            sa.activity_status AS original_activity_status,
+            sa.is_finished, sa.summary, sa.summary_attachments, sa.achievements, sa.achievements_attachments, sa.import_source,
             sa.remark, sa.create_by, sa.create_time, sa.update_by, sa.update_time,
             -- 关联查询创建者姓名
             su.nick_name AS create_by_name,
@@ -215,6 +235,26 @@
             <if test="activity.organizerType != null and activity.organizerType != ''">
                 AND sa.organizer_type = #{activity.organizerType}
             </if>
+            <if test="activity.activityStatus != null and activity.activityStatus != ''">
+                AND (
+                    CASE 
+                        -- 手动控制的状态保持不变(草稿、待审批、已取消、已驳回)
+                        WHEN sa.activity_status IN ('0', '2', '6', '7') THEN sa.activity_status
+                        
+                        -- 审批通过后的状态根据时间自动计算
+                        WHEN sa.activity_status IN ('3', '4', '5') THEN
+                            CASE 
+                                <![CDATA[WHEN NOW() < sa.start_time THEN '3']]>        -- 已通过(未开始)
+                                <![CDATA[WHEN NOW() >= sa.start_time AND NOW() <= sa.end_time THEN '4']]>  -- 进行中
+                                <![CDATA[WHEN NOW() > sa.end_time THEN '5']]>          -- 已结束
+                                ELSE sa.activity_status
+                            END
+                        
+                        -- 其他情况保持原状态
+                        ELSE sa.activity_status
+                    END
+                ) = #{activity.activityStatus}
+            </if>
             <if test="activity.registrationStatus != null and activity.registrationStatus != ''">
                 AND (
                     CASE 

+ 43 - 8
backend/ruoyi-modules/ruoyi-stgl/src/main/resources/mapper/stgl/StglClassMapper.xml

@@ -81,13 +81,49 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             GROUP BY m.user_id
         ) volunteer_stats ON s.id = volunteer_stats.user_id
         LEFT JOIN (
-            SELECT
-                ar.user_id,
-                COUNT(DISTINCT ar.activity_id) as activity_count
-            FROM stgl_activity_registration ar
-            WHERE ar.deleted = 0
-            AND ar.approval_status = 1
-            GROUP BY ar.user_id
+            -- 修改活动统计逻辑:同时统计个人报名和团队报名的活动数量
+            SELECT 
+                user_id,
+                COUNT(DISTINCT activity_id) as activity_count
+            FROM (
+                -- 个人报名的活动
+                SELECT 
+                    ar.user_id,
+                    ar.activity_id
+                FROM stgl_activity_registration ar
+                WHERE ar.deleted = 0
+                AND ar.approval_status = 1
+                AND ar.tenant_id = '000000'
+                
+                UNION
+                
+                -- 团队报名的活动(通过团队成员信息)
+                SELECT 
+                    JSON_UNQUOTE(JSON_EXTRACT(ati.team_members, CONCAT('$[', numbers.n, '].userId'))) as user_id,
+                    ati.activity_id
+                FROM stgl_activity_team_info ati
+                CROSS JOIN (
+                    SELECT 0 as n UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION 
+                    SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 UNION
+                    SELECT 10 UNION SELECT 11 UNION SELECT 12 UNION SELECT 13 UNION SELECT 14 UNION
+                    SELECT 15 UNION SELECT 16 UNION SELECT 17 UNION SELECT 18 UNION SELECT 19
+                ) numbers
+                WHERE ati.deleted = 0
+                AND ati.tenant_id = '000000'
+                AND JSON_UNQUOTE(JSON_EXTRACT(ati.team_members, CONCAT('$[', numbers.n, '].userId'))) IS NOT NULL
+                AND JSON_UNQUOTE(JSON_EXTRACT(ati.team_members, CONCAT('$[', numbers.n, '].userId'))) != ''
+                AND EXISTS (
+                    SELECT 1 FROM stgl_activity_registration team_ar 
+                    WHERE team_ar.team_id = ati.id 
+                    AND team_ar.deleted = 0 
+                    AND team_ar.approval_status = 1
+                    AND team_ar.registration_type = 2
+                    AND team_ar.tenant_id = '000000'
+                )
+            ) all_activities
+            WHERE user_id IS NOT NULL
+            AND user_id != ''
+            GROUP BY user_id
         ) activity_stats ON s.id = activity_stats.user_id
         <where>
             s.deleted = 0
@@ -174,7 +210,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         AND m.deleted = 0
         AND m.status = 2
         AND vt.deleted = 0
-        AND vt.status = 1
         ORDER BY vt.create_time DESC
     </select>
 

+ 7 - 1
web/src/api/stgl/activity/types.ts

@@ -145,10 +145,16 @@ export interface StglActivityVO {
   activityRange?: number;
 
   /**
-   * 活动状态
+   * 活动状态(动态计算后的状态)
    */
   activityStatus?: string;
 
+  /**
+   * 原始活动状态(数据库中存储的实际状态)
+   * 用于权限控制和业务逻辑判断
+   */
+  originalActivityStatus?: string;
+
   /**
    * 是否为已办活动
    */

+ 18 - 8
web/src/views/stgl/activity/components/ActivityRatingView.vue

@@ -90,7 +90,7 @@
 </template>
 
 <script setup lang="ts">
-import { ref, computed, onMounted } from 'vue';
+import { ref, computed, onMounted, watch } from 'vue';
 import { getActivityRatings } from '@/api/stgl/activity';
 import { ActivityRatingVO } from '@/api/stgl/activity/types';
 
@@ -146,19 +146,23 @@ const formatDateTimeCompact = (dateStr?: string): string => {
 
 // 加载评分数据
 const loadRatings = async () => {
-  if (!props.activityId) return;
+  if (!props.activityId) {
+    ratings.value = [];
+    return;
+  }
 
   loading.value = true;
   try {
+    console.log('开始加载活动评分数据,活动ID:', props.activityId);
     const res = await getActivityRatings(props.activityId);
     ratings.value = res.data || [];
-    console.log('加载的评分数据:', ratings.value);
+    console.log('成功加载评分数据,活动ID:', props.activityId, '评分数量:', ratings.value.length);
   } catch (error: any) {
     // 如果是404错误,说明后端暂未实现该功能,静默处理
     if (error.response?.status === 404) {
-      console.log('活动评分功能暂未实现');
+      console.log('活动评分功能暂未实现,活动ID:', props.activityId);
     } else {
-      console.error('加载评分数据失败:', error);
+      console.error('加载评分数据失败,活动ID:', props.activityId, '错误:', error);
     }
     ratings.value = [];
   } finally {
@@ -166,9 +170,15 @@ const loadRatings = async () => {
   }
 };
 
-onMounted(() => {
-  loadRatings();
-});
+// 监听 activityId 变化,自动重新加载评分数据
+watch(() => props.activityId, (newId, oldId) => {
+  console.log('活动ID发生变化:', oldId, '->', newId);
+  if (newId && newId !== oldId) {
+    loadRatings();
+  }
+}, { immediate: true }); // immediate: true 确保组件挂载时也会执行一次
+
+// 移除 onMounted,因为 watch 的 immediate: true 已经覆盖了这个功能
 </script>
 
 <style scoped>

+ 27 - 5
web/src/views/stgl/activity/components/RegisteredMembersTab.vue

@@ -321,7 +321,7 @@
 </template>
 
 <script setup lang="ts">
-import { getCurrentInstance, onMounted, reactive, ref, toRefs } from 'vue';
+import { getCurrentInstance, onMounted, reactive, ref, toRefs, watch } from 'vue';
 import {
   listActivityRegister,
   getActivityRegister,
@@ -507,6 +507,20 @@ const data = reactive<PageData<ExtendedActivityRegisterForm, StglActivityRegistr
 
 const { queryParams, form, rules } = toRefs(data);
 
+// 监听activityId变化,同步更新查询参数
+watch(() => props.activityId, (newActivityId) => {
+  if (newActivityId) {
+    console.log('RegisteredMembersTab: activityId发生变化,从', queryParams.value.activityId, '更新为', newActivityId);
+    queryParams.value.activityId = newActivityId;
+    // 重置分页到第一页
+    queryParams.value.pageNum = 1;
+    // 如果组件已经挂载,则立即重新查询
+    if (memberList.value.length > 0 || loading.value === false) {
+      getList();
+    }
+  }
+}, { immediate: true });
+
 // 上传相关
 const uploadRef = ref<UploadInstance>();
 const upload = reactive<{
@@ -529,8 +543,11 @@ const upload = reactive<{
 const getList = async () => {
   loading.value = true;
   try {
-    // 构建查询参数,查询已审核通过的报名记录
-    const queryData = { ...queryParams.value };
+    // 构建查询参数,确保使用最新的activityId
+    const queryData = { 
+      ...queryParams.value,
+      activityId: props.activityId  // 强制使用最新的props值
+    };
     
     // 如果状态字段为空或未选择,则查询已通过(approvalStatus=1)的报名记录
     if (!queryData.approvalStatus) {
@@ -538,6 +555,8 @@ const getList = async () => {
     }
     
     console.log('RegisteredMembersTab: getList 开始查询,参数:', queryData);
+    console.log('RegisteredMembersTab: props.activityId:', props.activityId);
+    console.log('RegisteredMembersTab: queryParams.activityId:', queryParams.value.activityId);
     
     const res = await listActivityRegister(queryData);
     console.log('RegisteredMembersTab: 查询结果:', res);
@@ -560,7 +579,10 @@ const cancel = () => {
 
 /** 表单重置 */
 const reset = () => {
-  form.value = { ...initFormData, activityId: props.activityId };
+  form.value = { 
+    ...initFormData, 
+    activityId: props.activityId  // 确保使用最新的activityId
+  };
   memberFormRef.value?.resetFields();
 };
 
@@ -635,7 +657,7 @@ const submitForm = () => {
       const { selectedStudent, ...submitData } = form.value;
       
       // 确保包含必要字段
-      submitData.activityId = props.activityId;
+      submitData.activityId = props.activityId;  // 使用最新的activityId
       submitData.approvalStatus = 1; // 新增的报名默认为已通过状态
       
       try {

+ 2 - 2
web/src/views/stgl/activity/hall/index.vue

@@ -61,8 +61,8 @@
             <dict-tag :options="stgl_activity_type" :value="scope.row.activityType" />
           </template>
         </el-table-column>
-        <el-table-column label="主办方" align="center" prop="organizerName" width="120" show-overflow-tooltip />
-        <el-table-column label="关联社团/队伍" align="center" width="120" show-overflow-tooltip>
+        <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>

+ 24 - 14
web/src/views/stgl/activity/index.vue

@@ -84,13 +84,13 @@
           <el-col :span="1.5">
             <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['stgl:activity:add']">新增</el-button>
           </el-col>
-                      <el-col :span="1.5" v-if="!single && selectedActivity && ['0', '7', '6'].includes(selectedActivity.activityStatus) && hasActivityOperationPermission(selectedActivity)">
+                      <el-col :span="1.5" v-if="!single && selectedActivity && ['0', '7', '6'].includes(getOriginalActivityStatus(selectedActivity)) && hasActivityOperationPermission(selectedActivity)">
               <el-button icon="Edit" @click="handleUpdate()" v-hasPermi="['stgl:activity:edit']">修改</el-button>
             </el-col>
-            <el-col :span="1.5" v-if="!single && selectedActivity && selectedActivity.activityStatus === '0' && hasActivityOperationPermission(selectedActivity)">
+            <el-col :span="1.5" v-if="!single && selectedActivity && getOriginalActivityStatus(selectedActivity) === '0' && hasActivityOperationPermission(selectedActivity)">
               <el-button type="success" icon="Upload" @click="handleSubmit()" v-hasPermi="['stgl:activity:edit']">提交</el-button>
             </el-col>
-            <el-col :span="1.5" v-if="!single && selectedActivity && selectedActivity.activityStatus === '2' && hasActivityOperationPermission(selectedActivity)">
+            <el-col :span="1.5" v-if="!single && selectedActivity && getOriginalActivityStatus(selectedActivity) === '2' && hasActivityOperationPermission(selectedActivity)">
               <el-button type="warning" icon="Check" @click="handleApprove()" v-hasPermi="['stgl:activity:approve']">审批</el-button>
             </el-col>
             <el-col :span="1.5" v-if="!single && selectedActivity && ['3', '4'].includes(selectedActivity.activityStatus) && hasActivityOperationPermission(selectedActivity)">
@@ -102,10 +102,10 @@
           <el-col :span="1.5">
             <el-button
               icon="Delete"
-              :disabled="multiple || !['0', '7'].includes(selectedActivity?.activityStatus || '')"
+              :disabled="multiple || !['0', '7'].includes(getOriginalActivityStatus(selectedActivity) || '')"
               @click="handleDelete()"
               v-hasPermi="['stgl:activity:remove']"
-              :title="selectedActivity && !['0', '7'].includes(selectedActivity.activityStatus) ? '只有草稿和已驳回状态的活动可以删除' : ''"
+              :title="selectedActivity && !['0', '7'].includes(getOriginalActivityStatus(selectedActivity)) ? '只有草稿和已驳回状态的活动可以删除' : ''"
               >删除</el-button
             >
           </el-col>
@@ -209,7 +209,7 @@
                 v-hasPermi="['stgl:activity:query']"
               ></el-button>
             </el-tooltip>
-            <el-tooltip content="修改" placement="top" v-if="['0', '7', '6'].includes(scope.row.activityStatus) && hasActivityOperationPermission(scope.row)">
+            <el-tooltip content="修改" placement="top" v-if="['0', '7', '6'].includes(getOriginalActivityStatus(scope.row)) && hasActivityOperationPermission(scope.row)">
               <el-button
                 link
                 type="primary"
@@ -220,7 +220,7 @@
                 v-hasPermi="['stgl:activity:edit']"
               ></el-button>
             </el-tooltip>
-            <el-tooltip content="提交" placement="top" v-if="scope.row.activityStatus === '0' && hasActivityOperationPermission(scope.row)">
+            <el-tooltip content="提交" placement="top" v-if="getOriginalActivityStatus(scope.row) === '0' && hasActivityOperationPermission(scope.row)">
               <el-button
                 link
                 type="success"
@@ -231,7 +231,7 @@
                 v-hasPermi="['stgl:activity:edit']"
               ></el-button>
             </el-tooltip>
-            <el-tooltip content="审批" placement="top" v-if="scope.row.activityStatus === '2' && hasActivityOperationPermission(scope.row)">
+            <el-tooltip content="审批" placement="top" v-if="getOriginalActivityStatus(scope.row) === '2' && hasActivityOperationPermission(scope.row)">
               <el-button
                 link
                 type="warning"
@@ -286,7 +286,7 @@
                 v-hasPermi="['stgl:activity:query']"
               ></el-button>
             </el-tooltip>
-            <el-tooltip content="删除" placement="top" v-if="['0', '7'].includes(scope.row.activityStatus) && hasActivityOperationPermission(scope.row)">
+            <el-tooltip content="删除" placement="top" v-if="['0', '7'].includes(getOriginalActivityStatus(scope.row)) && hasActivityOperationPermission(scope.row)">
               <el-button
                 link
                 type="danger"
@@ -1014,8 +1014,9 @@ const handleUpdate = async (row?: StglActivityVO) => {
   const res = await getStglActivity(_id);
 
   // 检查活动状态是否允许修改(只有草稿0、已驳回7、已取消6状态允许修改)
-  if (!['0', '7', '6'].includes(res.data.activityStatus)) {
-    const statusDict = stgl_activity_status.value.find((dict: any) => dict.value === res.data.activityStatus);
+  const originalStatus = getOriginalActivityStatus(res.data);
+  if (!['0', '7', '6'].includes(originalStatus)) {
+    const statusDict = stgl_activity_status.value.find((dict: any) => dict.value === originalStatus);
     const statusName = statusDict ? statusDict.label : '当前状态';
     proxy?.$modal.msgWarning(`活动状态为"${statusName}",不允许修改`);
     return;
@@ -1276,8 +1277,9 @@ const handleDelete = async (row?: StglActivityVO) => {
 
   // 检查删除权限 - 只有草稿(状态0)和已驳回(状态7)的活动可以删除
   if (row) {
-    if (!['0', '7'].includes(row.activityStatus)) {
-      const statusDict = stgl_activity_status.value.find((dict: any) => dict.value === row.activityStatus);
+    const originalStatus = getOriginalActivityStatus(row);
+    if (!['0', '7'].includes(originalStatus)) {
+      const statusDict = stgl_activity_status.value.find((dict: any) => dict.value === originalStatus);
       const statusName = statusDict ? statusDict.label : '当前状态';
       proxy?.$modal.msgWarning(`活动状态为"${statusName}",只有草稿和已驳回状态的活动可以删除`);
       return;
@@ -1287,7 +1289,7 @@ const handleDelete = async (row?: StglActivityVO) => {
     const selectedItems = activityList.value.filter((item) => ids.value.includes(item.id));
 
     // 检查选中的活动是否都是草稿或已驳回状态
-    const nonDeletableItems = selectedItems.filter((item) => !['0', '7'].includes(item.activityStatus));
+    const nonDeletableItems = selectedItems.filter((item) => !['0', '7'].includes(getOriginalActivityStatus(item)));
     if (nonDeletableItems.length > 0) {
       const names = nonDeletableItems.map((item) => item.activityName).join('、');
       proxy?.$modal.msgWarning(`活动"${names}"不是草稿或已驳回状态,只有草稿和已驳回状态的活动可以删除`);
@@ -1505,6 +1507,7 @@ const handleRegistrationTypeChange = (value: string) => {
 /** 判断是否显示总结按钮 */
 const shouldShowSummaryButton = (row: StglActivityVO): boolean => {
   // 只有进行中(4)和已结束(5)状态的活动才显示总结按钮
+  // 注意:这里使用显示状态,因为总结功能应该基于活动的实际进行状态
   return row.activityStatus === '4' || row.activityStatus === '5';
 };
 
@@ -1716,6 +1719,13 @@ const hasActivityOperationPermission = (activity: StglActivityVO): boolean => {
   return false;
 };
 
+/** 获取原始活动状态(用于权限控制) */
+const getOriginalActivityStatus = (activity: StglActivityVO | null): string => {
+  if (!activity) return '';
+  // 优先使用 originalActivityStatus 字段,如果不存在则使用 activityStatus
+  return activity.originalActivityStatus || activity.activityStatus || '';
+};
+
 onMounted(() => {
   initUrlParams();
   getList();

+ 7 - 7
web/src/views/stgl/my/club/index.vue

@@ -45,7 +45,7 @@
 
       <el-table v-loading="loading" border :data="clubList" @row-dblclick="handleView">
         <el-table-column label="序号" type="index" align="center" width="60" />
-        <el-table-column label="社团LOGO" align="center" width="80">
+        <el-table-column label="社团LOGO" align="center" width="150">
           <template #default="scope">
             <div v-if="scope.row.logoUrl" class="table-image">
               <image-preview :src="scope.row.logoUrl" :width="50" :height="50" />
@@ -56,35 +56,35 @@
           </template>
         </el-table-column>
         <el-table-column label="社团名称" align="center" prop="clubName" min-width="150" show-overflow-tooltip />
-        <el-table-column label="社团类型" align="center" prop="clubType" width="100">
+        <el-table-column label="社团类型" align="center" prop="clubType" width="150">
           <template #default="scope">
             <dict-tag :options="stgl_club_type" :value="scope.row.clubType" />
           </template>
         </el-table-column>
-        <el-table-column label="我的角色" align="center" prop="myRole" width="100">
+        <el-table-column label="我的角色" align="center" prop="myRole" width="140">
           <template #default="scope">
             <span class="role-text">{{ scope.row.myRole || '暂无' }}</span>
           </template>
         </el-table-column>
-        <el-table-column label="社长姓名" align="center" prop="presidentName" width="100" show-overflow-tooltip />
+        <el-table-column label="社长姓名" align="center" prop="presidentName" width="140" show-overflow-tooltip />
         <el-table-column label="指导老师" align="center" width="120" show-overflow-tooltip>
           <template #default="scope">
             <span v-if="scope.row.advisorName">{{ scope.row.advisorName }}</span>
             <span v-else class="text-gray-400">暂无</span>
           </template>
         </el-table-column>
-        <el-table-column label="成员数量" align="center" width="100">
+        <el-table-column label="成员数量" align="center" width="140">
           <template #default="scope">
             <span class="member-count">{{ scope.row.memberCount || 0 }}</span>
             <span v-if="scope.row.memberLimit" class="member-limit">/ {{ scope.row.memberLimit }}</span>
           </template>
         </el-table-column>
-        <el-table-column label="加入时间" align="center" width="180">
+        <el-table-column label="加入时间" align="center" width="200">
           <template #default="scope">
             <span>{{ parseTime(scope.row.joinTime, '{y}-{m}-{d} {h}:{i}') }}</span>
           </template>
         </el-table-column>
-        <el-table-column label="状态" align="center" prop="status" width="80">
+        <el-table-column label="状态" align="center" prop="status" width="120">
           <template #default="scope">
             <dict-tag :options="sys_normal_disable" :value="scope.row.status" />
           </template>

+ 1 - 1
web/src/views/stgl/stclass/index.vue

@@ -50,7 +50,7 @@
         </el-row>
       </template>
 
-      <el-table v-loading="loading" border :data="studentList" @selection-change="handleSelectionChange" @row-dblclick="handleView">
+      <el-table v-loading="loading" border :data="studentList" row-key="id" @selection-change="handleSelectionChange" @row-dblclick="handleView">
         <el-table-column type="selection" width="55" align="center" />
         <el-table-column label="序号" type="index" width="60" align="center" />
         <el-table-column label="学生姓名" align="center" prop="studentName" min-width="40" />