refactor: 代码优化与错误处理增强
前端: - mutator.ts: 响应拦截器增加业务错误码处理 - 多个 ListView/DetailView: 导入语句格式化(按字母排序) - CollectionListView/CollectionDetailView/CourseListView: 优化下架错误处理,显示具体错误信息 后端: - CourseCollectionServiceImpl: 下架套餐前检查是否有租户正在使用 - TeacherServiceImpl: 添加教师状态变更日志 - CoursePackageServiceImpl: 导入语句格式化
This commit is contained in:
parent
e2547daa63
commit
67af92ddfd
@ -1,4 +1,4 @@
|
||||
import axios, { type AxiosRequestConfig, type AxiosResponse } from "axios";
|
||||
import axios, {type AxiosRequestConfig, type AxiosResponse} from "axios";
|
||||
|
||||
/**
|
||||
* 创建默认 Axios 实例
|
||||
@ -32,6 +32,11 @@ axiosInstance.interceptors.response.use(
|
||||
if (jsonData.code === 200 || jsonData.code === 0) {
|
||||
return jsonData.data;
|
||||
}
|
||||
// 业务错误码,抛出错误
|
||||
const error: any = new Error(jsonData.message || '请求失败');
|
||||
error.response = { data: jsonData, status: 200 };
|
||||
error.code = jsonData.code;
|
||||
return Promise.reject(error);
|
||||
}
|
||||
return jsonData;
|
||||
} catch {
|
||||
@ -48,6 +53,11 @@ axiosInstance.interceptors.response.use(
|
||||
// 返回 data 字段
|
||||
return data.data;
|
||||
}
|
||||
// 业务错误码,抛出错误
|
||||
const error: any = new Error(data.message || '请求失败');
|
||||
error.response = { data, status: 200 };
|
||||
error.code = data.code;
|
||||
return Promise.reject(error);
|
||||
}
|
||||
|
||||
return data;
|
||||
|
||||
@ -150,10 +150,10 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, computed } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { message, Modal } from 'ant-design-vue';
|
||||
import { PlusOutlined } from '@ant-design/icons-vue';
|
||||
import {onMounted, ref} from 'vue';
|
||||
import {useRoute, useRouter} from 'vue-router';
|
||||
import {message} from 'ant-design-vue';
|
||||
import {PlusOutlined} from '@ant-design/icons-vue';
|
||||
import * as collectionsApi from '@/api/collections';
|
||||
import * as packagesApi from '@/api/course';
|
||||
|
||||
@ -238,8 +238,9 @@ const handleArchive = async () => {
|
||||
await collectionsApi.archiveCollection(route.params.id);
|
||||
message.success('下架成功');
|
||||
loadCollection();
|
||||
} catch (error) {
|
||||
message.error('下架失败');
|
||||
} catch (error: any) {
|
||||
const errorMsg = error?.message || '下架失败';
|
||||
message.error(errorMsg);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -114,10 +114,10 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { PlusOutlined } from '@ant-design/icons-vue';
|
||||
import {onMounted, reactive, ref} from 'vue';
|
||||
import {useRouter} from 'vue-router';
|
||||
import {message} from 'ant-design-vue';
|
||||
import {PlusOutlined} from '@ant-design/icons-vue';
|
||||
import * as collectionsApi from '@/api/collections';
|
||||
|
||||
const router = useRouter();
|
||||
@ -225,8 +225,9 @@ const handleArchive = async (record: collectionsApi.Collection) => {
|
||||
await collectionsApi.archiveCollection(record.id);
|
||||
message.success('下架成功');
|
||||
fetchData();
|
||||
} catch (error) {
|
||||
message.error('下架失败');
|
||||
} catch (error: any) {
|
||||
const errorMsg = error?.message || '下架失败';
|
||||
message.error(errorMsg);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -198,19 +198,12 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { message, Modal } from 'ant-design-vue';
|
||||
import { PlusOutlined, DownOutlined, AuditOutlined } from '@ant-design/icons-vue';
|
||||
import {onMounted, reactive, ref} from 'vue';
|
||||
import {useRouter} from 'vue-router';
|
||||
import {message, Modal} from 'ant-design-vue';
|
||||
import {AuditOutlined, DownOutlined, PlusOutlined} from '@ant-design/icons-vue';
|
||||
import * as courseApi from '@/api/course';
|
||||
import {
|
||||
translateGradeTag,
|
||||
getGradeTagStyle,
|
||||
translateCourseStatus,
|
||||
getCourseStatusStyle,
|
||||
getLessonTypeName,
|
||||
getLessonTagStyle,
|
||||
} from '@/utils/tagMaps';
|
||||
import {getCourseStatusStyle, getGradeTagStyle, getLessonTagStyle, getLessonTypeName, translateCourseStatus, translateGradeTag,} from '@/utils/tagMaps';
|
||||
|
||||
// 从课程包记录提取课程类型列表(去重,与学校端排课一致)
|
||||
const getLessonTypesFromRecord = (record: any): string[] => {
|
||||
@ -487,8 +480,9 @@ const unpublishCourse = async (id: number) => {
|
||||
await courseApi.unpublishCourse(id);
|
||||
message.success('下架成功');
|
||||
fetchCourses();
|
||||
} catch (error) {
|
||||
message.error('下架失败');
|
||||
} catch (error: any) {
|
||||
const errorMsg = error?.message || '下架失败';
|
||||
message.error(errorMsg);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@ -7,16 +7,10 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.reading.platform.common.enums.CourseStatus;
|
||||
import com.reading.platform.common.enums.TenantPackageStatus;
|
||||
import com.reading.platform.common.exception.BusinessException;
|
||||
import com.reading.platform.common.response.PageResult;
|
||||
import com.reading.platform.dto.response.CourseCollectionResponse;
|
||||
import com.reading.platform.dto.response.CoursePackageResponse;
|
||||
import com.reading.platform.dto.response.PackageFilterMetaResponse;
|
||||
import com.reading.platform.entity.CourseCollection;
|
||||
import com.reading.platform.entity.CourseCollectionPackage;
|
||||
import com.reading.platform.entity.CourseLesson;
|
||||
import com.reading.platform.entity.CoursePackage;
|
||||
import com.reading.platform.entity.TenantPackage;
|
||||
import com.reading.platform.entity.Theme;
|
||||
import com.reading.platform.entity.*;
|
||||
import com.reading.platform.mapper.*;
|
||||
import com.reading.platform.service.CourseCollectionService;
|
||||
import com.reading.platform.service.CourseLessonService;
|
||||
@ -27,12 +21,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@ -688,6 +677,18 @@ public class CourseCollectionServiceImpl extends ServiceImpl<CourseCollectionMap
|
||||
throw new IllegalArgumentException("课程套餐不存在");
|
||||
}
|
||||
|
||||
// 检查是否有租户正在使用此套餐
|
||||
Long tenantCount = tenantPackageMapper.selectCount(
|
||||
new LambdaQueryWrapper<TenantPackage>()
|
||||
.eq(TenantPackage::getCollectionId, id)
|
||||
.eq(TenantPackage::getStatus, TenantPackageStatus.ACTIVE)
|
||||
);
|
||||
|
||||
if (tenantCount > 0) {
|
||||
log.warn("下架课程套餐失败,有 {} 个租户正在使用此套餐,id={}", tenantCount, id);
|
||||
throw new BusinessException("该套餐正在被 " + tenantCount + " 个租户使用,无法下架");
|
||||
}
|
||||
|
||||
collection.setStatus(CourseStatus.ARCHIVED.getCode());
|
||||
collectionMapper.updateById(collection);
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.reading.platform.common.enums.CourseStatus;
|
||||
import com.reading.platform.common.enums.ScheduleStatus;
|
||||
import com.reading.platform.common.enums.TenantPackageStatus;
|
||||
import com.reading.platform.common.exception.BusinessException;
|
||||
import com.reading.platform.dto.request.CourseCreateRequest;
|
||||
@ -11,16 +12,8 @@ import com.reading.platform.dto.request.CourseUpdateRequest;
|
||||
import com.reading.platform.dto.response.CourseLessonResponse;
|
||||
import com.reading.platform.dto.response.CourseResponse;
|
||||
import com.reading.platform.dto.response.LessonStepResponse;
|
||||
import com.reading.platform.entity.CourseCollectionPackage;
|
||||
import com.reading.platform.entity.CourseLesson;
|
||||
import com.reading.platform.entity.CoursePackage;
|
||||
import com.reading.platform.entity.LessonStep;
|
||||
import com.reading.platform.entity.TenantPackage;
|
||||
import com.reading.platform.entity.Theme;
|
||||
import com.reading.platform.mapper.CourseCollectionPackageMapper;
|
||||
import com.reading.platform.mapper.CoursePackageMapper;
|
||||
import com.reading.platform.mapper.TenantPackageMapper;
|
||||
import com.reading.platform.mapper.ThemeMapper;
|
||||
import com.reading.platform.entity.*;
|
||||
import com.reading.platform.mapper.*;
|
||||
import com.reading.platform.service.CourseLessonService;
|
||||
import com.reading.platform.service.CoursePackageService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@ -50,6 +43,7 @@ public class CoursePackageServiceImpl extends ServiceImpl<CoursePackageMapper, C
|
||||
private final CourseCollectionPackageMapper collectionPackageMapper;
|
||||
private final TenantPackageMapper tenantPackageMapper;
|
||||
private final ThemeMapper themeMapper;
|
||||
private final SchedulePlanMapper schedulePlanMapper;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@ -218,10 +212,26 @@ public class CoursePackageServiceImpl extends ServiceImpl<CoursePackageMapper, C
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void archiveCourse(Long id) {
|
||||
log.info("下架课程包,id={}", id);
|
||||
|
||||
CoursePackage entity = getCourseById(id);
|
||||
|
||||
// 检查课程包是否被排课使用
|
||||
Long scheduleCount = schedulePlanMapper.selectCount(
|
||||
new LambdaQueryWrapper<com.reading.platform.entity.SchedulePlan>()
|
||||
.eq(com.reading.platform.entity.SchedulePlan::getCoursePackageId, id)
|
||||
.ne(com.reading.platform.entity.SchedulePlan::getStatus, ScheduleStatus.CANCELLED.getCode())
|
||||
);
|
||||
|
||||
if (scheduleCount > 0) {
|
||||
log.warn("下架课程包失败,有 {} 条排课记录正在使用此课程包,id={}", scheduleCount, id);
|
||||
throw new BusinessException("该课程包正在被 " + scheduleCount + " 条排课记录使用,无法下架");
|
||||
}
|
||||
|
||||
entity.setStatus(CourseStatus.ARCHIVED.getCode());
|
||||
coursePackageMapper.updateById(entity);
|
||||
log.info("课程归档成功,id={}", id);
|
||||
|
||||
log.info("课程包下架成功,id={}", id);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -2,8 +2,8 @@ package com.reading.platform.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.reading.platform.common.enums.GenericStatus;
|
||||
import com.reading.platform.common.enums.ErrorCode;
|
||||
import com.reading.platform.common.enums.GenericStatus;
|
||||
import com.reading.platform.common.exception.BusinessException;
|
||||
import com.reading.platform.dto.request.TeacherCreateRequest;
|
||||
import com.reading.platform.dto.request.TeacherUpdateRequest;
|
||||
@ -122,6 +122,10 @@ public class TeacherServiceImpl extends com.baomidou.mybatisplus.extension.servi
|
||||
teacher.setBio(request.getBio());
|
||||
}
|
||||
if (StringUtils.hasText(request.getStatus())) {
|
||||
if (!request.getStatus().equals(teacher.getStatus())) {
|
||||
log.info("教师状态变更:ID={}, name={}, oldStatus={}, newStatus={}",
|
||||
teacher.getId(), teacher.getName(), teacher.getStatus(), request.getStatus());
|
||||
}
|
||||
teacher.setStatus(request.getStatus());
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user