Explorar o código

前端token刷新进行修改

caojp hai 3 días
pai
achega
d4b563ecb2

+ 1 - 0
marriageAdmin-vue/src/config/api.js

@@ -37,6 +37,7 @@ export const API_ENDPOINTS = {
   // 活动管理
   ACTIVITY_LIST: '/api/activity/list',
   ACTIVITY_DETAIL: '/api/activity/detail',
+  ACTIVITY_ADMIN_LIST: '/admin/activity/list',
   ACTIVITY_CREATE: '/admin/activity/create',
   ACTIVITY_UPDATE: '/admin/activity/update',
   ACTIVITY_DELETE: '/admin/activity/delete',

+ 33 - 9
marriageAdmin-vue/src/utils/request.js

@@ -19,6 +19,20 @@ const showErrorMessage = (message) => {
   }
 }
 
+const isTokenExpiredLikeMessage = (message) => {
+  if (!message) return false
+  const msg = String(message).toLowerCase()
+  return (
+      msg.includes('access denied') ||
+      msg.includes('unauthorized') ||
+      msg.includes('token') ||
+      msg.includes('jwt') ||
+      msg.includes('expired') ||
+      msg.includes('authentication')
+  )
+}
+
+
 // 清除 token 并跳转登录页(用于服务重启等情况)
 const clearTokenAndRedirect = (message = '服务已重启,请重新登录') => {
   showErrorMessage(message)
@@ -65,18 +79,22 @@ request.interceptors.response.use(
     }
     
     const res = response.data
-    
+
     // 根据后端返回的结构判断
     if (res.code === 200 || res.code === 0) {
       return res
     } else if (res.code === 401) {
       // 未授权,跳转登录
-      clearTokenAndRedirect(res.msg || '未授权,请重新登录')
-      return Promise.reject(new Error(res.msg || '未授权'))
+      clearTokenAndRedirect('请刷新重新登录')
+      return Promise.reject(new Error('请刷新重新登录'))
     } else if (res.code === 403) {
-      // 拒绝访问:通常是权限不足,不应清token或强制跳转登录
-      showErrorMessage(res.msg || '拒绝访问')
-      return Promise.reject(new Error(res.msg || '拒绝访问'))
+      const msg = res.msg || res.message || ''
+      if (isTokenExpiredLikeMessage(msg)) {
+        clearTokenAndRedirect('请刷新重新登录')
+        return Promise.reject(new Error('请刷新重新登录'))
+      }
+      showErrorMessage(msg || '拒绝访问')
+      return Promise.reject(new Error(msg || '拒绝访问'))
     } else {
       // 其他错误
       showErrorMessage(res.msg || '请求失败')
@@ -100,11 +118,17 @@ request.interceptors.response.use(
       
       switch (status) {
         case 401:
-          clearTokenAndRedirect('未授权,请重新登录')
+          clearTokenAndRedirect('请刷新重新登录')
           break
         case 403:
-          // 权限不足:仅提示,不跳转登录
-          showErrorMessage(error.response.data?.msg || '拒绝访问')
+          {
+            const msg = error.response.data?.msg || error.response.data?.message || ''
+            if (isTokenExpiredLikeMessage(msg)) {
+              clearTokenAndRedirect('请刷新重新登录')
+            } else {
+              showErrorMessage(msg || '拒绝访问')
+            }
+          }
           break
         case 404:
           // 只对API请求显示404提示

+ 38 - 1
marriageAdmin-vue/src/views/activity/ActivityList.vue

@@ -145,6 +145,19 @@
             />
           </template>
         </el-table-column>
+
+        <el-table-column prop="isDeleted" label="上下架" width="90" align="center">
+          <template #default="{ row }">
+            <el-switch
+              :model-value="row.isDeleted"
+              :active-value="0"
+              :inactive-value="1"
+              active-color="var(--success-color)"
+              inactive-color="var(--border-dark)"
+              @change="(val) => handleShelfChange(row, val)"
+            />
+          </template>
+        </el-table-column>
         
         <el-table-column prop="startTime" label="开始时间" width="180">
           <template #default="{ row }">
@@ -263,7 +276,7 @@ const getCoverPreviewList = (row) => {
 const loadActivityList = async () => {
   loading.value = true
   try {
-    const response = await request.get(API_ENDPOINTS.ACTIVITY_LIST, {
+    const response = await request.get(API_ENDPOINTS.ACTIVITY_ADMIN_LIST, {
       params: {
         page: currentPage.value,
         pageSize: pageSize.value,
@@ -284,6 +297,7 @@ const loadActivityList = async () => {
           item.isHot === '1' ||
           item.is_hot === true ||
           item.is_hot === 1,
+        isDeleted: Number(item.isDeleted ?? item.is_deleted ?? 0),
         // 兼容下划线命名与不同字段名
         startTime: item.startTime || item.start_time || item.start_at || '',
         endTime: item.endTime || item.end_time || item.end_at || '',
@@ -305,6 +319,29 @@ const loadActivityList = async () => {
     loading.value = false
   }
 }
+const handleShelfChange = async (row, newValue) => {
+  const oldValue = row.isDeleted
+  row.isDeleted = newValue
+
+  try {
+    const response = await request.put(`${API_ENDPOINTS.ACTIVITY_UPDATE}/${row.id}`, {
+      isDeleted: newValue,
+      is_deleted: newValue
+    })
+
+    if (response.code === 200) {
+      ElMessage.success('状态更新成功')
+      loadActivityList()
+    } else {
+      row.isDeleted = oldValue
+      ElMessage.error(response.message || '状态更新失败')
+    }
+  } catch (error) {
+    console.error('状态更新失败:', error)
+    row.isDeleted = oldValue
+    ElMessage.error('状态更新失败,请重试')
+  }
+}
 
 // 获取状态文本
 const getStatusText = (status) => {

+ 47 - 0
service/admin/src/main/java/com/zhentao/controller/ActivityController.java

@@ -2,6 +2,7 @@ package com.zhentao.controller;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.zhentao.common.Result;
 import com.zhentao.entity.Activity;
 import com.zhentao.entity.ActivityRegistration;
@@ -28,6 +29,41 @@ public class ActivityController {
     private ActivityRegistrationService activityRegistrationService;
     
     private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+    @GetMapping("/list")
+    public Result<?> list(
+            @RequestParam(value = "page", defaultValue = "1") Integer page,
+            @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize,
+            @RequestParam(value = "type", required = false) Integer type,
+            @RequestParam(value = "status", required = false) Integer status,
+            @RequestParam(value = "keyword", required = false) String keyword
+    ) {
+        try {
+            Page<Activity> pageObj = new Page<>(page, pageSize);
+            Page<Activity> result = activityMapper.selectActivityPage(pageObj, type, status, keyword);
+
+            // 计算每个活动实际报名人数(排除已取消 status=2)
+            if (result.getRecords() != null) {
+                for (Activity activity : result.getRecords()) {
+                    if (activity == null || activity.getId() == null) continue;
+                    LambdaQueryWrapper<ActivityRegistration> regQuery = new LambdaQueryWrapper<ActivityRegistration>()
+                            .eq(ActivityRegistration::getActivityId, activity.getId())
+                            .ne(ActivityRegistration::getStatus, 2);
+                    long cnt = activityRegistrationService.count(regQuery);
+                    activity.setActualParticipants((int) cnt);
+                }
+            }
+
+            java.util.Map<String, Object> data = new java.util.HashMap<>();
+            data.put("list", result.getRecords());
+            data.put("total", result.getTotal());
+            data.put("page", page);
+            data.put("pageSize", pageSize);
+            return Result.success(data);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return Result.error("查询活动列表失败:" + e.getMessage());
+        }
+    }
     
     /**
      * 创建活动
@@ -48,6 +84,9 @@ public class ActivityController {
             if (activity.getIsHot() == null) {
                 activity.setIsHot(false);
             }
+            if (activity.getIsDeleted() == null) {
+                activity.setIsDeleted(0);
+            }
             activity.setCreatedTime(LocalDateTime.now());
             
             int rows = activityMapper.insert(activity);
@@ -72,6 +111,14 @@ public class ActivityController {
             System.out.println("=== 更新活动 ===");
             System.out.println("活动ID: " + id);
             System.out.println("活动数据: " + activity);
+
+            if (activity != null && activity.getIsDeleted() != null && activity.getName() == null) {
+                int rows = activityMapper.updateIsDeletedById(id, activity.getIsDeleted());
+                if (rows > 0) {
+                    return Result.success("更新成功");
+                }
+                return Result.error("更新失败");
+            }
             
             // 检查活动是否存在
             Activity existingActivity = activityMapper.selectById(id);

+ 2 - 0
service/admin/src/main/java/com/zhentao/controller/UserController.java

@@ -93,6 +93,8 @@ public class UserController {
             data.put("list", userVOList);
             data.put("total", result.getTotal());
             data.put("page", page);
+
+
             data.put("pageSize", pageSize);
             
             return Result.success(data);

+ 14 - 0
service/admin/src/main/java/com/zhentao/mapper/ActivityMapper.java

@@ -1,13 +1,27 @@
 package com.zhentao.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.zhentao.entity.Activity;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
 
 /**
  * 活动Mapper接口
  */
 @Mapper
 public interface ActivityMapper extends BaseMapper<Activity> {
+
+    Page<Activity> selectActivityPage(
+            Page<Activity> page,
+            @Param("type") Integer type,
+            @Param("status") Integer status,
+            @Param("keyword") String keyword
+    );
+
+    int updateIsDeletedById(
+            @Param("id") Integer id,
+            @Param("isDeleted") Integer isDeleted
+    );
 }
 

+ 44 - 0
service/admin/src/main/resources/mapper/ActivityMapper.xml

@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.zhentao.mapper.ActivityMapper">
+
+    <select id="selectActivityPage" resultType="com.zhentao.entity.Activity">
+        SELECT
+            id,
+            name,
+            type,
+            category,
+            max_participants,
+            actual_participants,
+            location,
+            start_time,
+            end_time,
+            cover_image,
+            price,
+            status,
+            registration_end_time,
+            is_deleted,
+            description,
+            notes,
+            is_hot
+        FROM activity
+        WHERE 1 = 1
+        <if test="type != null">
+            AND type = #{type}
+        </if>
+        <if test="status != null">
+            AND status = #{status}
+        </if>
+        <if test="keyword != null and keyword != ''">
+            AND name LIKE CONCAT('%', #{keyword}, '%')
+        </if>
+        ORDER BY start_time DESC
+    </select>
+
+    <update id="updateIsDeletedById">
+        UPDATE activity
+        SET is_deleted = #{isDeleted}
+        WHERE id = #{id}
+    </update>
+
+</mapper>