Compare commits
No commits in common. "673214481dbf524b70d2e28471c1f087cb7c34ac" and "459fa434ac8c5b02886cf3d40e11ad840710264f" have entirely different histories.
673214481d
...
459fa434ac
@ -47,7 +47,7 @@ model SchoolCourse {
|
||||
createdBy Int @map("created_by")
|
||||
changesSummary String? @map("changes_summary") // 修改说明
|
||||
usageCount Int @default(0) @map("usage_count")
|
||||
status String @default("ACTIVE") // ACTIVE, PENDING, REJECTED
|
||||
status String @default("ACTIVE") // ACTIVE, PENDING_REVIEW, REJECTED
|
||||
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
@ -82,7 +82,7 @@ PUT /api/v1/admin/packages/{id}/courses
|
||||
POST /api/v1/admin/packages/{id}/submit
|
||||
```
|
||||
|
||||
✅ 提交成功,状态变为 `PENDING`
|
||||
✅ 提交成功,状态变为 `PENDING_REVIEW`
|
||||
|
||||
#### 4. 审核通过
|
||||
|
||||
|
||||
@ -241,7 +241,7 @@ export class CoursePackageService {
|
||||
return this.prisma.coursePackage.update({
|
||||
where: { id },
|
||||
data: {
|
||||
status: 'PENDING',
|
||||
status: 'PENDING_REVIEW',
|
||||
submittedAt: new Date(),
|
||||
submittedBy: userId,
|
||||
},
|
||||
@ -262,7 +262,7 @@ export class CoursePackageService {
|
||||
throw new Error('套餐不存在');
|
||||
}
|
||||
|
||||
if (pkg.status !== 'PENDING') {
|
||||
if (pkg.status !== 'PENDING_REVIEW') {
|
||||
throw new Error('只有待审核状态的套餐可以审核');
|
||||
}
|
||||
|
||||
|
||||
@ -34,7 +34,7 @@ export interface CoursePackage {
|
||||
gradeLevels?: string;
|
||||
/** 课程数量 */
|
||||
courseCount?: number;
|
||||
/** 状态:DRAFT、PENDING、APPROVED、REJECTED、PUBLISHED、OFFLINE */
|
||||
/** 状态:DRAFT、PENDING_REVIEW、APPROVED、REJECTED、PUBLISHED、OFFLINE */
|
||||
status?: string;
|
||||
/** 提交时间 */
|
||||
submittedAt?: string;
|
||||
|
||||
@ -97,7 +97,7 @@ export function submitPackage(id: number | string) {
|
||||
}
|
||||
|
||||
// 审核套餐
|
||||
export function reviewPackage(id: number | string, data: { approved: boolean; comment?: string; publish?: boolean }) {
|
||||
export function reviewPackage(id: number | string, data: { approved: boolean; comment?: string }) {
|
||||
return http.post(`/v1/admin/packages/${id}/review`, data);
|
||||
}
|
||||
|
||||
|
||||
@ -11,8 +11,10 @@ declare module 'vue' {
|
||||
AAvatar: typeof import('ant-design-vue/es')['Avatar']
|
||||
ABadge: typeof import('ant-design-vue/es')['Badge']
|
||||
AButton: typeof import('ant-design-vue/es')['Button']
|
||||
AButtonGroup: typeof import('ant-design-vue/es')['ButtonGroup']
|
||||
ACard: typeof import('ant-design-vue/es')['Card']
|
||||
ACheckbox: typeof import('ant-design-vue/es')['Checkbox']
|
||||
ACheckboxGroup: typeof import('ant-design-vue/es')['CheckboxGroup']
|
||||
ACol: typeof import('ant-design-vue/es')['Col']
|
||||
ADatePicker: typeof import('ant-design-vue/es')['DatePicker']
|
||||
ADescriptions: typeof import('ant-design-vue/es')['Descriptions']
|
||||
@ -23,6 +25,8 @@ declare module 'vue' {
|
||||
AEmpty: typeof import('ant-design-vue/es')['Empty']
|
||||
AForm: typeof import('ant-design-vue/es')['Form']
|
||||
AFormItem: typeof import('ant-design-vue/es')['FormItem']
|
||||
AImage: typeof import('ant-design-vue/es')['Image']
|
||||
AImagePreviewGroup: typeof import('ant-design-vue/es')['ImagePreviewGroup']
|
||||
AInput: typeof import('ant-design-vue/es')['Input']
|
||||
AInputNumber: typeof import('ant-design-vue/es')['InputNumber']
|
||||
AInputPassword: typeof import('ant-design-vue/es')['InputPassword']
|
||||
@ -48,11 +52,14 @@ declare module 'vue' {
|
||||
ARate: typeof import('ant-design-vue/es')['Rate']
|
||||
ARow: typeof import('ant-design-vue/es')['Row']
|
||||
ASelect: typeof import('ant-design-vue/es')['Select']
|
||||
ASelectOptGroup: typeof import('ant-design-vue/es')['SelectOptGroup']
|
||||
ASelectOption: typeof import('ant-design-vue/es')['SelectOption']
|
||||
ASkeleton: typeof import('ant-design-vue/es')['Skeleton']
|
||||
ASpace: typeof import('ant-design-vue/es')['Space']
|
||||
ASpin: typeof import('ant-design-vue/es')['Spin']
|
||||
AStatistic: typeof import('ant-design-vue/es')['Statistic']
|
||||
AStep: typeof import('ant-design-vue/es')['Step']
|
||||
ASteps: typeof import('ant-design-vue/es')['Steps']
|
||||
ASubMenu: typeof import('ant-design-vue/es')['SubMenu']
|
||||
ASwitch: typeof import('ant-design-vue/es')['Switch']
|
||||
ATable: typeof import('ant-design-vue/es')['Table']
|
||||
|
||||
@ -84,7 +84,7 @@ const courseColumns = [
|
||||
|
||||
const statusColors: Record<string, string> = {
|
||||
DRAFT: 'default',
|
||||
PENDING: 'processing',
|
||||
PENDING_REVIEW: 'processing',
|
||||
APPROVED: 'success',
|
||||
REJECTED: 'error',
|
||||
PUBLISHED: 'blue',
|
||||
@ -93,7 +93,7 @@ const statusColors: Record<string, string> = {
|
||||
|
||||
const statusTexts: Record<string, string> = {
|
||||
DRAFT: '草稿',
|
||||
PENDING: '待审核',
|
||||
PENDING_REVIEW: '待审核',
|
||||
APPROVED: '已通过',
|
||||
REJECTED: '已拒绝',
|
||||
PUBLISHED: '已发布',
|
||||
|
||||
@ -27,7 +27,7 @@
|
||||
@change="fetchData"
|
||||
>
|
||||
<a-select-option value="DRAFT">草稿</a-select-option>
|
||||
<a-select-option value="PENDING">待审核</a-select-option>
|
||||
<a-select-option value="PENDING_REVIEW">待审核</a-select-option>
|
||||
<a-select-option value="APPROVED">已通过</a-select-option>
|
||||
<a-select-option value="REJECTED">已拒绝</a-select-option>
|
||||
<a-select-option value="PUBLISHED">已发布</a-select-option>
|
||||
@ -81,7 +81,7 @@
|
||||
<a-button
|
||||
type="link"
|
||||
size="small"
|
||||
v-if="record.status === 'PENDING'"
|
||||
v-if="record.status === 'PENDING_REVIEW'"
|
||||
@click="handleReview(record)"
|
||||
>
|
||||
审核
|
||||
@ -143,7 +143,7 @@ const columns = [
|
||||
|
||||
const statusColors: Record<string, string> = {
|
||||
DRAFT: 'default',
|
||||
PENDING: 'processing',
|
||||
PENDING_REVIEW: 'processing',
|
||||
APPROVED: 'success',
|
||||
REJECTED: 'error',
|
||||
PUBLISHED: 'blue',
|
||||
@ -152,7 +152,7 @@ const statusColors: Record<string, string> = {
|
||||
|
||||
const statusTexts: Record<string, string> = {
|
||||
DRAFT: '草稿',
|
||||
PENDING: '待审核',
|
||||
PENDING_REVIEW: '待审核',
|
||||
APPROVED: '已通过',
|
||||
REJECTED: '已拒绝',
|
||||
PUBLISHED: '已发布',
|
||||
@ -183,7 +183,7 @@ const fetchData = async () => {
|
||||
pagination.total = res.total || 0;
|
||||
// 获取待审核数量
|
||||
try {
|
||||
const pendingRes = await getPackageList({ status: 'PENDING', pageNum: 1, pageSize: 1 }) as any;
|
||||
const pendingRes = await getPackageList({ status: 'PENDING_REVIEW', pageNum: 1, pageSize: 1 }) as any;
|
||||
pendingCount.value = pendingRes.total || 0;
|
||||
} catch {
|
||||
pendingCount.value = 0;
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<template #extra>
|
||||
<a-space>
|
||||
<a-select v-model:value="filters.status" placeholder="全部状态" style="width: 120px" @change="fetchPackages">
|
||||
<a-select-option value="PENDING">待审核</a-select-option>
|
||||
<a-select-option value="PENDING_REVIEW">待审核</a-select-option>
|
||||
<a-select-option value="REJECTED">已驳回</a-select-option>
|
||||
</a-select>
|
||||
<a-button @click="fetchPackages">
|
||||
@ -39,8 +39,8 @@
|
||||
</a-tag>
|
||||
</template>
|
||||
<template v-else-if="column.key === 'status'">
|
||||
<a-tag :color="record.status === 'PENDING' ? 'processing' : 'error'">
|
||||
{{ record.status === 'PENDING' ? '待审核' : '已驳回' }}
|
||||
<a-tag :color="record.status === 'PENDING_REVIEW' ? 'processing' : 'error'">
|
||||
{{ record.status === 'PENDING_REVIEW' ? '待审核' : '已驳回' }}
|
||||
</a-tag>
|
||||
</template>
|
||||
<template v-else-if="column.key === 'submittedAt'">
|
||||
@ -48,7 +48,7 @@
|
||||
</template>
|
||||
<template v-else-if="column.key === 'actions'">
|
||||
<a-space>
|
||||
<a-button v-if="record.status === 'PENDING'" type="primary" size="small" @click="showReviewModal(record)">
|
||||
<a-button v-if="record.status === 'PENDING_REVIEW'" type="primary" size="small" @click="showReviewModal(record)">
|
||||
审核
|
||||
</a-button>
|
||||
<a-button v-if="record.status === 'REJECTED'" size="small" @click="viewRejectReason(record)">
|
||||
@ -107,15 +107,12 @@
|
||||
</a-form>
|
||||
|
||||
<div class="modal-footer">
|
||||
<a-space v-if="currentPackage.status === 'PENDING'">
|
||||
<a-space v-if="currentPackage.status === 'PENDING_REVIEW'">
|
||||
<a-button @click="closeReviewModal">取消</a-button>
|
||||
<a-button type="default" danger :loading="reviewing" @click="rejectPackage">
|
||||
驳回
|
||||
</a-button>
|
||||
<a-button :loading="reviewing" @click="approveOnly">
|
||||
通过
|
||||
</a-button>
|
||||
<a-button type="primary" :loading="reviewing" @click="approveAndPublish">
|
||||
<a-button type="primary" :loading="reviewing" @click="approvePackage">
|
||||
通过并发布
|
||||
</a-button>
|
||||
</a-space>
|
||||
@ -147,7 +144,7 @@ const loadingDetail = ref(false);
|
||||
const packages = ref<CoursePackage[]>([]);
|
||||
|
||||
const filters = reactive<{ status?: string }>({
|
||||
status: 'PENDING',
|
||||
status: 'PENDING_REVIEW',
|
||||
});
|
||||
|
||||
const pagination = reactive({
|
||||
@ -230,8 +227,7 @@ const closeReviewModal = () => {
|
||||
currentPackage.value = null;
|
||||
};
|
||||
|
||||
// 仅通过
|
||||
const approveOnly = async () => {
|
||||
const approvePackage = async () => {
|
||||
if (!currentPackage.value) return;
|
||||
|
||||
reviewing.value = true;
|
||||
@ -239,28 +235,6 @@ const approveOnly = async () => {
|
||||
await reviewPackage(currentPackage.value.id, {
|
||||
approved: true,
|
||||
comment: reviewComment.value || '审核通过',
|
||||
publish: false,
|
||||
});
|
||||
message.success('审核通过');
|
||||
closeReviewModal();
|
||||
fetchPackages();
|
||||
} catch (error: any) {
|
||||
message.error(error.response?.data?.message || '审核失败');
|
||||
} finally {
|
||||
reviewing.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 通过并发布
|
||||
const approveAndPublish = async () => {
|
||||
if (!currentPackage.value) return;
|
||||
|
||||
reviewing.value = true;
|
||||
try {
|
||||
await reviewPackage(currentPackage.value.id, {
|
||||
approved: true,
|
||||
comment: reviewComment.value || '审核通过',
|
||||
publish: true,
|
||||
});
|
||||
message.success('审核通过,套餐已发布');
|
||||
closeReviewModal();
|
||||
|
||||
@ -1,58 +0,0 @@
|
||||
package com.reading.platform.common.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 是/否枚举
|
||||
* 用于替代数据库中的 0/1 魔法值
|
||||
*/
|
||||
@Getter
|
||||
public enum YesNo {
|
||||
|
||||
NO(0, "否"),
|
||||
YES(1, "是");
|
||||
|
||||
private final Integer code;
|
||||
private final String description;
|
||||
|
||||
YesNo(Integer code, String description) {
|
||||
this.code = code;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 code 获取枚举
|
||||
*/
|
||||
public static YesNo fromCode(Integer code) {
|
||||
if (code == null) {
|
||||
return NO;
|
||||
}
|
||||
for (YesNo value : values()) {
|
||||
if (value.getCode().equals(code)) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 Boolean 获取枚举
|
||||
*/
|
||||
public static YesNo fromBoolean(Boolean bool) {
|
||||
return Boolean.TRUE.equals(bool) ? YES : NO;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为"是"
|
||||
*/
|
||||
public static boolean isYes(Integer code) {
|
||||
return YES.getCode().equals(code);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为"否"
|
||||
*/
|
||||
public static boolean isNo(Integer code) {
|
||||
return NO.getCode().equals(code);
|
||||
}
|
||||
}
|
||||
@ -18,9 +18,6 @@ import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 课程管理控制器(超管端)
|
||||
*/
|
||||
@ -36,12 +33,12 @@ public class AdminCourseController {
|
||||
|
||||
@PostMapping
|
||||
@Operation(summary = "创建课程")
|
||||
public Result<CourseResponse> createCourse(@Valid @RequestBody CourseCreateRequest request) {
|
||||
public Result<Course> createCourse(@Valid @RequestBody CourseCreateRequest request) {
|
||||
log.info("收到课程创建请求,name={}, themeId={}, gradeTags={}", request.getName(), request.getThemeId(), request.getGradeTags());
|
||||
try {
|
||||
Course course = courseService.createSystemCourse(request);
|
||||
log.info("课程创建成功,id={}", course.getId());
|
||||
return Result.success(courseService.getCourseByIdWithLessons(course.getId()));
|
||||
return Result.success(course);
|
||||
} catch (Exception e) {
|
||||
log.error("课程创建失败", e);
|
||||
throw e;
|
||||
@ -50,9 +47,8 @@ public class AdminCourseController {
|
||||
|
||||
@PutMapping("/{id}")
|
||||
@Operation(summary = "更新课程")
|
||||
public Result<CourseResponse> updateCourse(@PathVariable Long id, @RequestBody CourseUpdateRequest request) {
|
||||
courseService.updateCourse(id, request);
|
||||
return Result.success(courseService.getCourseByIdWithLessons(id));
|
||||
public Result<Course> updateCourse(@PathVariable Long id, @RequestBody CourseUpdateRequest request) {
|
||||
return Result.success(courseService.updateCourse(id, request));
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
@ -63,7 +59,7 @@ public class AdminCourseController {
|
||||
|
||||
@GetMapping
|
||||
@Operation(summary = "分页查询课程")
|
||||
public Result<PageResult<CourseResponse>> getCoursePage(CoursePageQueryRequest request) {
|
||||
public Result<PageResult<Course>> getCoursePage(CoursePageQueryRequest request) {
|
||||
log.info("查询课程列表,pageNum={}, pageSize={}, keyword={}, category={}, status={}, reviewOnly={}",
|
||||
request.getPageNum(), request.getPageSize(), request.getKeyword(), request.getCategory(), request.getStatus(), request.getReviewOnly());
|
||||
// 页码
|
||||
@ -79,13 +75,7 @@ public class AdminCourseController {
|
||||
request.getCategory(),
|
||||
request.getStatus(),
|
||||
request.getReviewOnly());
|
||||
|
||||
// 转换为 CourseResponse
|
||||
List<CourseResponse> responseList = page.getRecords().stream()
|
||||
.map(course -> courseService.getCourseByIdWithLessons(course.getId()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
PageResult<CourseResponse> result = PageResult.of(responseList, page.getTotal(), page.getCurrent(), page.getSize());
|
||||
PageResult<Course> result = PageResult.of(page);
|
||||
log.info("课程列表查询结果,total={}, list={}", result.getTotal(), result.getList().size());
|
||||
return Result.success(result);
|
||||
}
|
||||
|
||||
@ -4,9 +4,6 @@ import com.reading.platform.common.annotation.RequireRole;
|
||||
import com.reading.platform.common.enums.UserRole;
|
||||
import com.reading.platform.common.response.Result;
|
||||
import com.reading.platform.dto.request.CourseLessonCreateRequest;
|
||||
import com.reading.platform.dto.request.LessonStepCreateRequest;
|
||||
import com.reading.platform.dto.response.CourseLessonResponse;
|
||||
import com.reading.platform.dto.response.LessonStepResponse;
|
||||
import com.reading.platform.entity.CourseLesson;
|
||||
import com.reading.platform.entity.LessonStep;
|
||||
import com.reading.platform.service.CourseLessonService;
|
||||
@ -17,7 +14,6 @@ import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 课程环节控制器(超管端)
|
||||
@ -32,42 +28,33 @@ public class AdminCourseLessonController {
|
||||
|
||||
@GetMapping("/{courseId}/lessons")
|
||||
@Operation(summary = "获取课程的所有环节")
|
||||
public Result<List<CourseLessonResponse>> findAll(@PathVariable Long courseId) {
|
||||
List<CourseLesson> lessons = courseLessonService.findByCourseId(courseId);
|
||||
List<CourseLessonResponse> responses = lessons.stream()
|
||||
.map(this::toLessonResponse)
|
||||
.collect(Collectors.toList());
|
||||
return Result.success(responses);
|
||||
public Result<List<CourseLesson>> findAll(@PathVariable Long courseId) {
|
||||
return Result.success(courseLessonService.findByCourseId(courseId));
|
||||
}
|
||||
|
||||
@GetMapping("/{courseId}/lessons/{id}")
|
||||
@Operation(summary = "获取课程环节详情")
|
||||
public Result<CourseLessonResponse> findOne(
|
||||
public Result<CourseLesson> findOne(
|
||||
@PathVariable Long courseId,
|
||||
@PathVariable Long id) {
|
||||
CourseLesson lesson = courseLessonService.findById(id);
|
||||
return Result.success(toLessonResponse(lesson));
|
||||
return Result.success(courseLessonService.findById(id));
|
||||
}
|
||||
|
||||
@GetMapping("/{courseId}/lessons/type/{lessonType}")
|
||||
@Operation(summary = "按类型获取课程环节")
|
||||
public Result<CourseLessonResponse> findByType(
|
||||
public Result<CourseLesson> findByType(
|
||||
@PathVariable Long courseId,
|
||||
@PathVariable String lessonType) {
|
||||
CourseLesson lesson = courseLessonService.findByType(courseId, lessonType);
|
||||
if (lesson == null) {
|
||||
return Result.success(null);
|
||||
}
|
||||
return Result.success(toLessonResponse(lesson));
|
||||
return Result.success(courseLessonService.findByType(courseId, lessonType));
|
||||
}
|
||||
|
||||
@PostMapping("/{courseId}/lessons")
|
||||
@Operation(summary = "创建课程环节")
|
||||
@RequireRole(UserRole.ADMIN)
|
||||
public Result<CourseLessonResponse> create(
|
||||
public Result<CourseLesson> create(
|
||||
@PathVariable Long courseId,
|
||||
@Valid @RequestBody CourseLessonCreateRequest request) {
|
||||
CourseLesson lesson = courseLessonService.create(
|
||||
return Result.success(courseLessonService.create(
|
||||
courseId,
|
||||
request.getLessonType(),
|
||||
request.getName(),
|
||||
@ -85,18 +72,17 @@ public class AdminCourseLessonController {
|
||||
request.getReflection(),
|
||||
request.getAssessmentData(),
|
||||
request.getUseTemplate()
|
||||
);
|
||||
return Result.success(toLessonResponse(lesson));
|
||||
));
|
||||
}
|
||||
|
||||
@PutMapping("/{courseId}/lessons/{id}")
|
||||
@Operation(summary = "更新课程环节")
|
||||
@RequireRole(UserRole.ADMIN)
|
||||
public Result<CourseLessonResponse> update(
|
||||
public Result<CourseLesson> update(
|
||||
@PathVariable Long courseId,
|
||||
@PathVariable Long id,
|
||||
@RequestBody CourseLessonCreateRequest request) {
|
||||
CourseLesson lesson = courseLessonService.update(
|
||||
return Result.success(courseLessonService.update(
|
||||
id,
|
||||
request.getName(),
|
||||
request.getDescription(),
|
||||
@ -113,8 +99,7 @@ public class AdminCourseLessonController {
|
||||
request.getReflection(),
|
||||
request.getAssessmentData(),
|
||||
request.getUseTemplate()
|
||||
);
|
||||
return Result.success(toLessonResponse(lesson));
|
||||
));
|
||||
}
|
||||
|
||||
@DeleteMapping("/{courseId}/lessons/{id}")
|
||||
@ -141,50 +126,44 @@ public class AdminCourseLessonController {
|
||||
|
||||
@GetMapping("/{courseId}/lessons/{lessonId}/steps")
|
||||
@Operation(summary = "获取课时的教学环节")
|
||||
public Result<List<LessonStepResponse>> findSteps(
|
||||
public Result<List<LessonStep>> findSteps(
|
||||
@PathVariable Long courseId,
|
||||
@PathVariable Long lessonId) {
|
||||
List<LessonStep> steps = courseLessonService.findSteps(lessonId);
|
||||
List<LessonStepResponse> responses = steps.stream()
|
||||
.map(this::toStepResponse)
|
||||
.collect(Collectors.toList());
|
||||
return Result.success(responses);
|
||||
return Result.success(courseLessonService.findSteps(lessonId));
|
||||
}
|
||||
|
||||
@PostMapping("/{courseId}/lessons/{lessonId}/steps")
|
||||
@Operation(summary = "创建教学环节")
|
||||
@RequireRole(UserRole.ADMIN)
|
||||
public Result<LessonStepResponse> createStep(
|
||||
public Result<LessonStep> createStep(
|
||||
@PathVariable Long courseId,
|
||||
@PathVariable Long lessonId,
|
||||
@Valid @RequestBody LessonStepCreateRequest request) {
|
||||
LessonStep step = courseLessonService.createStep(
|
||||
@RequestBody StepCreateRequest request) {
|
||||
return Result.success(courseLessonService.createStep(
|
||||
lessonId,
|
||||
request.getName(),
|
||||
request.getContent(),
|
||||
request.getDuration(),
|
||||
request.getObjective(),
|
||||
request.getResourceIds()
|
||||
);
|
||||
return Result.success(toStepResponse(step));
|
||||
));
|
||||
}
|
||||
|
||||
@PutMapping("/{courseId}/lessons/steps/{stepId}")
|
||||
@Operation(summary = "更新教学环节")
|
||||
@RequireRole(UserRole.ADMIN)
|
||||
public Result<LessonStepResponse> updateStep(
|
||||
public Result<LessonStep> updateStep(
|
||||
@PathVariable Long courseId,
|
||||
@PathVariable Long stepId,
|
||||
@Valid @RequestBody LessonStepCreateRequest request) {
|
||||
LessonStep step = courseLessonService.updateStep(
|
||||
@RequestBody StepCreateRequest request) {
|
||||
return Result.success(courseLessonService.updateStep(
|
||||
stepId,
|
||||
request.getName(),
|
||||
request.getContent(),
|
||||
request.getDuration(),
|
||||
request.getObjective(),
|
||||
request.getResourceIds()
|
||||
);
|
||||
return Result.success(toStepResponse(step));
|
||||
));
|
||||
}
|
||||
|
||||
@DeleteMapping("/{courseId}/lessons/steps/{stepId}")
|
||||
@ -209,56 +188,24 @@ public class AdminCourseLessonController {
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 CourseLesson 实体转换为 CourseLessonResponse
|
||||
* 教学环节创建请求
|
||||
*/
|
||||
private CourseLessonResponse toLessonResponse(CourseLesson lesson) {
|
||||
// 获取教学环节
|
||||
List<LessonStep> steps = courseLessonService.findSteps(lesson.getId());
|
||||
List<LessonStepResponse> stepResponses = steps.stream()
|
||||
.map(this::toStepResponse)
|
||||
.collect(Collectors.toList());
|
||||
public static class StepCreateRequest {
|
||||
private String name;
|
||||
private String content;
|
||||
private Integer duration;
|
||||
private String objective;
|
||||
private List<Long> resourceIds;
|
||||
|
||||
return CourseLessonResponse.builder()
|
||||
.id(lesson.getId())
|
||||
.courseId(lesson.getCourseId())
|
||||
.lessonType(lesson.getLessonType())
|
||||
.name(lesson.getName())
|
||||
.description(lesson.getDescription())
|
||||
.duration(lesson.getDuration())
|
||||
.videoPath(lesson.getVideoPath())
|
||||
.videoName(lesson.getVideoName())
|
||||
.pptPath(lesson.getPptPath())
|
||||
.pptName(lesson.getPptName())
|
||||
.pdfPath(lesson.getPdfPath())
|
||||
.pdfName(lesson.getPdfName())
|
||||
.objectives(lesson.getObjectives())
|
||||
.preparation(lesson.getPreparation())
|
||||
.extension(lesson.getExtension())
|
||||
.reflection(lesson.getReflection())
|
||||
.assessmentData(lesson.getAssessmentData())
|
||||
.useTemplate(lesson.getUseTemplate())
|
||||
.sortOrder(lesson.getSortOrder())
|
||||
.steps(stepResponses)
|
||||
.createdAt(lesson.getCreatedAt())
|
||||
.updatedAt(lesson.getUpdatedAt())
|
||||
.build();
|
||||
public String getName() { return name; }
|
||||
public void setName(String name) { this.name = name; }
|
||||
public String getContent() { return content; }
|
||||
public void setContent(String content) { this.content = content; }
|
||||
public Integer getDuration() { return duration; }
|
||||
public void setDuration(Integer duration) { this.duration = duration; }
|
||||
public String getObjective() { return objective; }
|
||||
public void setObjective(String objective) { this.objective = objective; }
|
||||
public List<Long> getResourceIds() { return resourceIds; }
|
||||
public void setResourceIds(List<Long> resourceIds) { this.resourceIds = resourceIds; }
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 LessonStep 实体转换为 LessonStepResponse
|
||||
*/
|
||||
private LessonStepResponse toStepResponse(LessonStep step) {
|
||||
return LessonStepResponse.builder()
|
||||
.id(step.getId())
|
||||
.lessonId(step.getLessonId())
|
||||
.name(step.getName())
|
||||
.content(step.getContent())
|
||||
.duration(step.getDuration())
|
||||
.objective(step.getObjective())
|
||||
.resourceIds(step.getResourceIds())
|
||||
.sortOrder(step.getSortOrder())
|
||||
.createdAt(step.getCreatedAt())
|
||||
.updatedAt(step.getUpdatedAt())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,13 +1,12 @@
|
||||
package com.reading.platform.controller.admin;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.reading.platform.common.annotation.RequireRole;
|
||||
import com.reading.platform.common.enums.UserRole;
|
||||
import com.reading.platform.common.security.SecurityUtils;
|
||||
import com.reading.platform.common.response.PageResult;
|
||||
import com.reading.platform.common.response.Result;
|
||||
import com.reading.platform.dto.request.PackageCreateRequest;
|
||||
import com.reading.platform.dto.request.PackageGrantRequest;
|
||||
import com.reading.platform.dto.request.PackageReviewRequest;
|
||||
import com.reading.platform.dto.response.CoursePackageResponse;
|
||||
import com.reading.platform.entity.CoursePackage;
|
||||
import com.reading.platform.service.CoursePackageService;
|
||||
@ -20,7 +19,6 @@ import org.springframework.web.bind.annotation.*;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 课程套餐控制器(超管端)
|
||||
@ -51,25 +49,24 @@ public class AdminPackageController {
|
||||
@PostMapping
|
||||
@Operation(summary = "创建套餐")
|
||||
@RequireRole(UserRole.ADMIN)
|
||||
public Result<CoursePackageResponse> create(@Valid @RequestBody PackageCreateRequest request) {
|
||||
CoursePackage pkg = packageService.createPackage(
|
||||
public Result<CoursePackage> create(@Valid @RequestBody PackageCreateRequest request) {
|
||||
return Result.success(packageService.createPackage(
|
||||
request.getName(),
|
||||
request.getDescription(),
|
||||
request.getPrice(),
|
||||
request.getDiscountPrice(),
|
||||
request.getDiscountType(),
|
||||
request.getGradeLevels()
|
||||
);
|
||||
return Result.success(packageService.findOnePackage(pkg.getId()));
|
||||
));
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
@Operation(summary = "更新套餐")
|
||||
@RequireRole(UserRole.ADMIN)
|
||||
public Result<CoursePackageResponse> update(
|
||||
public Result<CoursePackage> update(
|
||||
@PathVariable Long id,
|
||||
@RequestBody PackageCreateRequest request) {
|
||||
packageService.updatePackage(
|
||||
return Result.success(packageService.updatePackage(
|
||||
id,
|
||||
request.getName(),
|
||||
request.getDescription(),
|
||||
@ -77,8 +74,7 @@ public class AdminPackageController {
|
||||
request.getDiscountPrice(),
|
||||
request.getDiscountType(),
|
||||
request.getGradeLevels()
|
||||
);
|
||||
return Result.success(packageService.findOnePackage(id));
|
||||
));
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
@ -112,14 +108,8 @@ public class AdminPackageController {
|
||||
@RequireRole(UserRole.ADMIN)
|
||||
public Result<Void> review(
|
||||
@PathVariable Long id,
|
||||
@Valid @RequestBody PackageReviewRequest request) {
|
||||
packageService.reviewPackage(
|
||||
id,
|
||||
SecurityUtils.getCurrentUserId(),
|
||||
request.getApproved(),
|
||||
request.getComment(),
|
||||
request.getPublish()
|
||||
);
|
||||
@RequestBody ReviewRequest request) {
|
||||
packageService.reviewPackage(id, SecurityUtils.getCurrentUserId(), request.getApproved(), request.getComment());
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@ -141,12 +131,8 @@ public class AdminPackageController {
|
||||
|
||||
@GetMapping("/all")
|
||||
@Operation(summary = "查询所有已发布的套餐列表")
|
||||
public Result<List<CoursePackageResponse>> getPublishedPackages() {
|
||||
List<CoursePackage> packages = packageService.findPublishedPackages();
|
||||
List<CoursePackageResponse> responses = packages.stream()
|
||||
.map(pkg -> packageService.findOnePackage(pkg.getId()))
|
||||
.collect(Collectors.toList());
|
||||
return Result.success(responses);
|
||||
public Result<List<CoursePackage>> getPublishedPackages() {
|
||||
return Result.success(packageService.findPublishedPackages());
|
||||
}
|
||||
|
||||
@PostMapping("/{id}/grant")
|
||||
@ -154,7 +140,7 @@ public class AdminPackageController {
|
||||
@RequireRole(UserRole.ADMIN)
|
||||
public Result<Void> grantToTenant(
|
||||
@PathVariable Long id,
|
||||
@Valid @RequestBody PackageGrantRequest request) {
|
||||
@RequestBody GrantRequest request) {
|
||||
LocalDate endDate = LocalDate.parse(request.getEndDate(), DateTimeFormatter.ISO_DATE);
|
||||
packageService.renewTenantPackage(
|
||||
request.getTenantId(),
|
||||
@ -164,4 +150,33 @@ public class AdminPackageController {
|
||||
);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 审核请求
|
||||
*/
|
||||
public static class ReviewRequest {
|
||||
private Boolean approved;
|
||||
private String comment;
|
||||
|
||||
public Boolean getApproved() { return approved; }
|
||||
public void setApproved(Boolean approved) { this.approved = approved; }
|
||||
public String getComment() { return comment; }
|
||||
public void setComment(String comment) { this.comment = comment; }
|
||||
}
|
||||
|
||||
/**
|
||||
* 授权请求
|
||||
*/
|
||||
public static class GrantRequest {
|
||||
private Long tenantId;
|
||||
private String endDate;
|
||||
private Long pricePaid;
|
||||
|
||||
public Long getTenantId() { return tenantId; }
|
||||
public void setTenantId(Long tenantId) { this.tenantId = tenantId; }
|
||||
public String getEndDate() { return endDate; }
|
||||
public void setEndDate(String endDate) { this.endDate = endDate; }
|
||||
public Long getPricePaid() { return pricePaid; }
|
||||
public void setPricePaid(Long pricePaid) { this.pricePaid = pricePaid; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,24 +5,16 @@ import com.reading.platform.common.annotation.RequireRole;
|
||||
import com.reading.platform.common.enums.UserRole;
|
||||
import com.reading.platform.common.response.PageResult;
|
||||
import com.reading.platform.common.response.Result;
|
||||
import com.reading.platform.dto.request.ResourceLibraryCreateRequest;
|
||||
import com.reading.platform.dto.request.ResourceLibraryUpdateRequest;
|
||||
import com.reading.platform.dto.request.ResourceItemCreateRequest;
|
||||
import com.reading.platform.dto.request.ResourceItemUpdateRequest;
|
||||
import com.reading.platform.dto.response.ResourceLibraryResponse;
|
||||
import com.reading.platform.dto.response.ResourceItemResponse;
|
||||
import com.reading.platform.entity.ResourceItem;
|
||||
import com.reading.platform.entity.ResourceLibrary;
|
||||
import com.reading.platform.service.ResourceLibraryService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 资源库控制器(超管端)
|
||||
@ -39,52 +31,44 @@ public class AdminResourceController {
|
||||
|
||||
@GetMapping("/libraries")
|
||||
@Operation(summary = "分页查询资源库")
|
||||
public Result<PageResult<ResourceLibraryResponse>> findAllLibraries(
|
||||
public Result<PageResult<ResourceLibrary>> findAllLibraries(
|
||||
@RequestParam(required = false) String libraryType,
|
||||
@RequestParam(required = false) String keyword,
|
||||
@RequestParam(required = false, defaultValue = "1") Integer pageNum,
|
||||
@RequestParam(required = false, defaultValue = "10") Integer pageSize) {
|
||||
Page<ResourceLibrary> page = resourceLibraryService.findAllLibraries(libraryType, keyword, pageNum, pageSize);
|
||||
|
||||
List<ResourceLibraryResponse> responses = page.getRecords().stream()
|
||||
.map(this::toLibraryResponse)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return Result.success(PageResult.of(responses, page.getTotal(), page.getCurrent(), page.getSize()));
|
||||
return Result.success(PageResult.of(page.getRecords(), page.getTotal(), page.getCurrent(), page.getSize()));
|
||||
}
|
||||
|
||||
@GetMapping("/libraries/{id}")
|
||||
@Operation(summary = "查询资源库详情")
|
||||
public Result<ResourceLibraryResponse> findLibrary(@PathVariable String id) {
|
||||
ResourceLibrary library = resourceLibraryService.findLibraryById(id);
|
||||
return Result.success(toLibraryResponse(library));
|
||||
public Result<ResourceLibrary> findLibrary(@PathVariable String id) {
|
||||
return Result.success(resourceLibraryService.findLibraryById(id));
|
||||
}
|
||||
|
||||
@PostMapping("/libraries")
|
||||
@Operation(summary = "创建资源库")
|
||||
@RequireRole(UserRole.ADMIN)
|
||||
public Result<ResourceLibraryResponse> createLibrary(@Valid @RequestBody ResourceLibraryCreateRequest request) {
|
||||
ResourceLibrary library = resourceLibraryService.createLibrary(
|
||||
public Result<ResourceLibrary> createLibrary(@RequestBody LibraryCreateRequest request) {
|
||||
return Result.success(resourceLibraryService.createLibrary(
|
||||
request.getName(),
|
||||
request.getType(),
|
||||
request.getDescription(),
|
||||
request.getTenantId()
|
||||
);
|
||||
return Result.success(toLibraryResponse(library));
|
||||
));
|
||||
}
|
||||
|
||||
@PutMapping("/libraries/{id}")
|
||||
@Operation(summary = "更新资源库")
|
||||
@RequireRole(UserRole.ADMIN)
|
||||
public Result<ResourceLibraryResponse> updateLibrary(
|
||||
public Result<ResourceLibrary> updateLibrary(
|
||||
@PathVariable String id,
|
||||
@Valid @RequestBody ResourceLibraryUpdateRequest request) {
|
||||
ResourceLibrary library = resourceLibraryService.updateLibrary(
|
||||
@RequestBody LibraryUpdateRequest request) {
|
||||
return Result.success(resourceLibraryService.updateLibrary(
|
||||
id,
|
||||
request.getName(),
|
||||
request.getDescription()
|
||||
);
|
||||
return Result.success(toLibraryResponse(library));
|
||||
));
|
||||
}
|
||||
|
||||
@DeleteMapping("/libraries/{id}")
|
||||
@ -99,33 +83,27 @@ public class AdminResourceController {
|
||||
|
||||
@GetMapping("/items")
|
||||
@Operation(summary = "分页查询资源项目")
|
||||
public Result<PageResult<ResourceItemResponse>> findAllItems(
|
||||
public Result<PageResult<ResourceItem>> findAllItems(
|
||||
@RequestParam(required = false) String libraryId,
|
||||
@RequestParam(required = false) String fileType,
|
||||
@RequestParam(required = false) String keyword,
|
||||
@RequestParam(required = false, defaultValue = "1") Integer pageNum,
|
||||
@RequestParam(required = false, defaultValue = "20") Integer pageSize) {
|
||||
Page<ResourceItem> page = resourceLibraryService.findAllItems(libraryId, fileType, keyword, pageNum, pageSize);
|
||||
|
||||
List<ResourceItemResponse> responses = page.getRecords().stream()
|
||||
.map(this::toItemResponse)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return Result.success(PageResult.of(responses, page.getTotal(), page.getCurrent(), page.getSize()));
|
||||
return Result.success(PageResult.of(page.getRecords(), page.getTotal(), page.getCurrent(), page.getSize()));
|
||||
}
|
||||
|
||||
@GetMapping("/items/{id}")
|
||||
@Operation(summary = "查询资源项目详情")
|
||||
public Result<ResourceItemResponse> findItem(@PathVariable String id) {
|
||||
ResourceItem item = resourceLibraryService.findItemById(id);
|
||||
return Result.success(toItemResponse(item));
|
||||
public Result<ResourceItem> findItem(@PathVariable String id) {
|
||||
return Result.success(resourceLibraryService.findItemById(id));
|
||||
}
|
||||
|
||||
@PostMapping("/items")
|
||||
@Operation(summary = "创建资源项目")
|
||||
@RequireRole(UserRole.ADMIN)
|
||||
public Result<ResourceItemResponse> createItem(@Valid @RequestBody ResourceItemCreateRequest request) {
|
||||
ResourceItem item = resourceLibraryService.createItem(
|
||||
public Result<ResourceItem> createItem(@RequestBody ItemCreateRequest request) {
|
||||
return Result.success(resourceLibraryService.createItem(
|
||||
request.getLibraryId(),
|
||||
request.getTitle(),
|
||||
request.getFileType(),
|
||||
@ -134,23 +112,21 @@ public class AdminResourceController {
|
||||
request.getDescription(),
|
||||
request.getTags(),
|
||||
request.getTenantId()
|
||||
);
|
||||
return Result.success(toItemResponse(item));
|
||||
));
|
||||
}
|
||||
|
||||
@PutMapping("/items/{id}")
|
||||
@Operation(summary = "更新资源项目")
|
||||
@RequireRole(UserRole.ADMIN)
|
||||
public Result<ResourceItemResponse> updateItem(
|
||||
public Result<ResourceItem> updateItem(
|
||||
@PathVariable String id,
|
||||
@Valid @RequestBody ResourceItemUpdateRequest request) {
|
||||
ResourceItem item = resourceLibraryService.updateItem(
|
||||
@RequestBody ItemUpdateRequest request) {
|
||||
return Result.success(resourceLibraryService.updateItem(
|
||||
id,
|
||||
request.getTitle(),
|
||||
request.getDescription(),
|
||||
request.getTags()
|
||||
);
|
||||
return Result.success(toItemResponse(item));
|
||||
));
|
||||
}
|
||||
|
||||
@DeleteMapping("/items/{id}")
|
||||
@ -178,35 +154,81 @@ public class AdminResourceController {
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 ResourceLibrary 实体转换为 ResourceLibraryResponse
|
||||
* 资源库创建请求
|
||||
*/
|
||||
private ResourceLibraryResponse toLibraryResponse(ResourceLibrary library) {
|
||||
return ResourceLibraryResponse.builder()
|
||||
.id(library.getId())
|
||||
.tenantId(library.getTenantId())
|
||||
.name(library.getName())
|
||||
.description(library.getDescription())
|
||||
.type(library.getLibraryType())
|
||||
.createdBy(library.getCreatedBy() != null ? String.valueOf(library.getCreatedBy()) : null)
|
||||
.createdAt(library.getCreatedAt())
|
||||
.updatedAt(library.getUpdatedAt())
|
||||
.build();
|
||||
public static class LibraryCreateRequest {
|
||||
private String name;
|
||||
private String type;
|
||||
private String description;
|
||||
private String tenantId;
|
||||
|
||||
public String getName() { return name; }
|
||||
public void setName(String name) { this.name = name; }
|
||||
public String getType() { return type; }
|
||||
public void setType(String type) { this.type = type; }
|
||||
public String getDescription() { return description; }
|
||||
public void setDescription(String description) { this.description = description; }
|
||||
public String getTenantId() { return tenantId; }
|
||||
public void setTenantId(String tenantId) { this.tenantId = tenantId; }
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 ResourceItem 实体转换为 ResourceItemResponse
|
||||
* 资源库更新请求
|
||||
*/
|
||||
private ResourceItemResponse toItemResponse(ResourceItem item) {
|
||||
return ResourceItemResponse.builder()
|
||||
.id(item.getId())
|
||||
.libraryId(item.getLibraryId())
|
||||
.tenantId(item.getTenantId())
|
||||
.type(item.getFileType())
|
||||
.name(item.getTitle())
|
||||
.description(item.getDescription())
|
||||
.status(item.getStatus())
|
||||
.createdAt(item.getCreatedAt())
|
||||
.updatedAt(item.getUpdatedAt())
|
||||
.build();
|
||||
public static class LibraryUpdateRequest {
|
||||
private String name;
|
||||
private String description;
|
||||
|
||||
public String getName() { return name; }
|
||||
public void setName(String name) { this.name = name; }
|
||||
public String getDescription() { return description; }
|
||||
public void setDescription(String description) { this.description = description; }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 资源项目创建请求(数字资源)
|
||||
*/
|
||||
public static class ItemCreateRequest {
|
||||
private String libraryId;
|
||||
private String title;
|
||||
private String fileType;
|
||||
private String filePath;
|
||||
private Long fileSize;
|
||||
private String description;
|
||||
private String tags;
|
||||
private String tenantId;
|
||||
|
||||
public String getLibraryId() { return libraryId; }
|
||||
public void setLibraryId(String libraryId) { this.libraryId = libraryId; }
|
||||
public String getTitle() { return title; }
|
||||
public void setTitle(String title) { this.title = title; }
|
||||
public String getFileType() { return fileType; }
|
||||
public void setFileType(String fileType) { this.fileType = fileType; }
|
||||
public String getFilePath() { return filePath; }
|
||||
public void setFilePath(String filePath) { this.filePath = filePath; }
|
||||
public Long getFileSize() { return fileSize; }
|
||||
public void setFileSize(Long fileSize) { this.fileSize = fileSize; }
|
||||
public String getDescription() { return description; }
|
||||
public void setDescription(String description) { this.description = description; }
|
||||
public String getTags() { return tags; }
|
||||
public void setTags(String tags) { this.tags = tags; }
|
||||
public String getTenantId() { return tenantId; }
|
||||
public void setTenantId(String tenantId) { this.tenantId = tenantId; }
|
||||
}
|
||||
|
||||
/**
|
||||
* 资源项目更新请求(数字资源)
|
||||
*/
|
||||
public static class ItemUpdateRequest {
|
||||
private String title;
|
||||
private String description;
|
||||
private String tags;
|
||||
|
||||
public String getTitle() { return title; }
|
||||
public void setTitle(String title) { this.title = title; }
|
||||
public String getDescription() { return description; }
|
||||
public void setDescription(String description) { this.description = description; }
|
||||
public String getTags() { return tags; }
|
||||
public void setTags(String tags) { this.tags = tags; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,7 +11,6 @@ import com.reading.platform.dto.response.PopularCourseItemResponse;
|
||||
import com.reading.platform.dto.response.RecentActivityItemResponse;
|
||||
import com.reading.platform.dto.response.StatsResponse;
|
||||
import com.reading.platform.dto.response.StatsTrendResponse;
|
||||
import com.reading.platform.service.StatsService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@ -20,6 +19,7 @@ import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@ -32,36 +32,55 @@ import java.util.List;
|
||||
@Tag(name = "超管端 - 统计管理")
|
||||
public class AdminStatsController {
|
||||
|
||||
private final StatsService statsService;
|
||||
|
||||
@GetMapping
|
||||
@Operation(summary = "获取统计数据")
|
||||
public Result<StatsResponse> getStats() {
|
||||
return Result.success(statsService.getStats());
|
||||
// TODO: 实现统计数据查询
|
||||
return Result.success(StatsResponse.builder()
|
||||
.totalTenants(0L)
|
||||
.activeTenants(0L)
|
||||
.totalTeachers(0L)
|
||||
.totalStudents(0L)
|
||||
.totalCourses(0L)
|
||||
.totalLessons(0L)
|
||||
.build());
|
||||
}
|
||||
|
||||
@GetMapping("/trend")
|
||||
@Operation(summary = "获取趋势数据")
|
||||
public Result<StatsTrendResponse> getTrendData() {
|
||||
return Result.success(statsService.getTrendData());
|
||||
// TODO: 实现趋势数据查询
|
||||
return Result.success(StatsTrendResponse.builder()
|
||||
.dates(new ArrayList<>())
|
||||
.newStudents(new ArrayList<>())
|
||||
.newTeachers(new ArrayList<>())
|
||||
.newCourses(new ArrayList<>())
|
||||
.build());
|
||||
}
|
||||
|
||||
@GetMapping("/tenants/active")
|
||||
@Operation(summary = "获取活跃租户")
|
||||
public Result<List<ActiveTenantItemResponse>> getActiveTenants(@ModelAttribute ActiveTenantsQueryRequest request) {
|
||||
return Result.success(statsService.getActiveTenants(request));
|
||||
// 返回数量限制
|
||||
// TODO: 实现活跃租户查询
|
||||
return Result.success(new ArrayList<>());
|
||||
}
|
||||
|
||||
@GetMapping("/courses/popular")
|
||||
@Operation(summary = "获取热门课程")
|
||||
public Result<List<PopularCourseItemResponse>> getPopularCourses(@ModelAttribute PopularCoursesQueryRequest request) {
|
||||
return Result.success(statsService.getPopularCourses(request));
|
||||
// 返回数量限制
|
||||
// TODO: 实现热门课程查询
|
||||
return Result.success(new ArrayList<>());
|
||||
}
|
||||
|
||||
@GetMapping("/activities")
|
||||
@Operation(summary = "获取最近活动")
|
||||
public Result<List<RecentActivityItemResponse>> getRecentActivities(@ModelAttribute RecentActivitiesQueryRequest request) {
|
||||
return Result.success(statsService.getRecentActivities(request));
|
||||
// 返回数量限制
|
||||
// TODO: 实现最近活动查询
|
||||
return Result.success(new ArrayList<>());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,14 +1,20 @@
|
||||
package com.reading.platform.controller.admin;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.reading.platform.common.annotation.RequireRole;
|
||||
import com.reading.platform.common.enums.UserRole;
|
||||
import com.reading.platform.common.mapper.TenantMapper;
|
||||
import com.reading.platform.common.response.PageResult;
|
||||
import com.reading.platform.common.response.Result;
|
||||
import com.reading.platform.dto.request.TenantCreateRequest;
|
||||
import com.reading.platform.dto.request.TenantUpdateRequest;
|
||||
import com.reading.platform.dto.response.TenantResponse;
|
||||
import com.reading.platform.entity.Student;
|
||||
import com.reading.platform.entity.Teacher;
|
||||
import com.reading.platform.entity.Tenant;
|
||||
import com.reading.platform.mapper.StudentMapper;
|
||||
import com.reading.platform.mapper.TeacherMapper;
|
||||
import com.reading.platform.service.TenantService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
@ -19,7 +25,6 @@ import org.springframework.web.bind.annotation.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Tag(name = "超管端 - 租户管理", description = "Tenant Management APIs for Admin")
|
||||
@RestController
|
||||
@ -29,26 +34,29 @@ import java.util.stream.Collectors;
|
||||
public class AdminTenantController {
|
||||
|
||||
private final TenantService tenantService;
|
||||
private final TenantMapper tenantMapper;
|
||||
private final TeacherMapper teacherMapper;
|
||||
private final StudentMapper studentMapper;
|
||||
|
||||
@Operation(summary = "Create tenant")
|
||||
@PostMapping
|
||||
public Result<TenantResponse> createTenant(@Valid @RequestBody TenantCreateRequest request) {
|
||||
Tenant tenant = tenantService.createTenant(request);
|
||||
return Result.success(toResponse(tenant));
|
||||
return Result.success(tenantMapper.toVO(tenant));
|
||||
}
|
||||
|
||||
@Operation(summary = "Update tenant")
|
||||
@PutMapping("/{id}")
|
||||
public Result<TenantResponse> updateTenant(@PathVariable Long id, @RequestBody TenantUpdateRequest request) {
|
||||
Tenant tenant = tenantService.updateTenant(id, request);
|
||||
return Result.success(toResponse(tenant));
|
||||
return Result.success(tenantMapper.toVO(tenant));
|
||||
}
|
||||
|
||||
@Operation(summary = "Get tenant by ID")
|
||||
@GetMapping("/{id}")
|
||||
public Result<TenantResponse> getTenant(@PathVariable Long id) {
|
||||
Tenant tenant = tenantService.getTenantById(id);
|
||||
return Result.success(toResponse(tenant));
|
||||
return Result.success(tenantMapper.toVO(tenant));
|
||||
}
|
||||
|
||||
@Operation(summary = "Get tenant page")
|
||||
@ -58,15 +66,27 @@ public class AdminTenantController {
|
||||
@RequestParam(required = false, defaultValue = "10") Integer pageSize,
|
||||
@RequestParam(required = false) String keyword,
|
||||
@RequestParam(required = false) String status) {
|
||||
// 调用 Service 层方法获取带统计数据的租户分页
|
||||
Page<TenantResponse> pageResult = tenantService.getTenantPageWithStats(pageNum, pageSize, keyword, status);
|
||||
Page<Tenant> pageResult = tenantService.getTenantPage(pageNum, pageSize, keyword, status);
|
||||
List<TenantResponse> voList = tenantMapper.toVO(pageResult.getRecords());
|
||||
|
||||
return Result.success(PageResult.of(
|
||||
pageResult.getRecords(),
|
||||
pageResult.getTotal(),
|
||||
pageResult.getCurrent(),
|
||||
pageResult.getSize()
|
||||
));
|
||||
// 填充教师数量和学生数量
|
||||
for (TenantResponse vo : voList) {
|
||||
if (vo.getId() != null) {
|
||||
Long teacherCount = teacherMapper.selectCount(
|
||||
new LambdaQueryWrapper<Teacher>()
|
||||
.eq(Teacher::getTenantId, vo.getId())
|
||||
);
|
||||
vo.setTeacherCount(teacherCount != null ? teacherCount.intValue() : 0);
|
||||
|
||||
Long studentCount = studentMapper.selectCount(
|
||||
new LambdaQueryWrapper<Student>()
|
||||
.eq(Student::getTenantId, vo.getId())
|
||||
);
|
||||
vo.setStudentCount(studentCount != null ? studentCount.intValue() : 0);
|
||||
}
|
||||
}
|
||||
|
||||
return Result.success(PageResult.of(voList, pageResult.getTotal(), pageResult.getCurrent(), pageResult.getSize()));
|
||||
}
|
||||
|
||||
@Operation(summary = "Delete tenant")
|
||||
@ -80,10 +100,7 @@ public class AdminTenantController {
|
||||
@GetMapping("/active")
|
||||
public Result<List<TenantResponse>> getAllActiveTenants() {
|
||||
List<Tenant> tenants = tenantService.getAllActiveTenants();
|
||||
List<TenantResponse> responses = tenants.stream()
|
||||
.map(this::toResponse)
|
||||
.collect(Collectors.toList());
|
||||
return Result.success(responses);
|
||||
return Result.success(tenantMapper.toVO(tenants));
|
||||
}
|
||||
|
||||
@Operation(summary = "获取租户统计信息")
|
||||
@ -101,7 +118,7 @@ public class AdminTenantController {
|
||||
public Result<TenantResponse> updateTenantQuota(@PathVariable Long id, @RequestBody Map<String, Object> quota) {
|
||||
// TODO: 实现更新租户配额逻辑
|
||||
Tenant tenant = tenantService.getTenantById(id);
|
||||
return Result.success(toResponse(tenant));
|
||||
return Result.success(tenantMapper.toVO(tenant));
|
||||
}
|
||||
|
||||
@Operation(summary = "更新租户状态")
|
||||
@ -109,7 +126,7 @@ public class AdminTenantController {
|
||||
public Result<TenantResponse> updateTenantStatus(@PathVariable Long id, @RequestBody Map<String, Object> status) {
|
||||
// TODO: 实现更新租户状态逻辑
|
||||
Tenant tenant = tenantService.getTenantById(id);
|
||||
return Result.success(toResponse(tenant));
|
||||
return Result.success(tenantMapper.toVO(tenant));
|
||||
}
|
||||
|
||||
@Operation(summary = "重置租户密码")
|
||||
@ -119,34 +136,4 @@ public class AdminTenantController {
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 Tenant 实体转换为 TenantResponse
|
||||
*/
|
||||
private TenantResponse toResponse(Tenant tenant) {
|
||||
return TenantResponse.builder()
|
||||
.id(tenant.getId())
|
||||
.name(tenant.getName())
|
||||
.code(tenant.getCode())
|
||||
.username(tenant.getUsername())
|
||||
.contactName(tenant.getContactName())
|
||||
.contactPhone(tenant.getContactPhone())
|
||||
.contactEmail(tenant.getContactEmail())
|
||||
.address(tenant.getAddress())
|
||||
.logoUrl(tenant.getLogoUrl())
|
||||
.status(tenant.getStatus())
|
||||
.expireAt(tenant.getExpireAt())
|
||||
.maxStudents(tenant.getMaxStudents())
|
||||
.maxTeachers(tenant.getMaxTeachers())
|
||||
.packageType(tenant.getPackageType())
|
||||
.teacherQuota(tenant.getTeacherQuota())
|
||||
.studentQuota(tenant.getStudentQuota())
|
||||
.storageQuota(tenant.getStorageQuota())
|
||||
.storageUsed(tenant.getStorageUsed())
|
||||
.startDate(tenant.getStartDate())
|
||||
.expireDate(tenant.getExpireDate())
|
||||
.createdAt(tenant.getCreatedAt())
|
||||
.updatedAt(tenant.getUpdatedAt())
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,7 +4,6 @@ import com.reading.platform.common.annotation.RequireRole;
|
||||
import com.reading.platform.common.enums.UserRole;
|
||||
import com.reading.platform.common.response.Result;
|
||||
import com.reading.platform.dto.request.ThemeCreateRequest;
|
||||
import com.reading.platform.dto.response.ThemeResponse;
|
||||
import com.reading.platform.entity.Theme;
|
||||
import com.reading.platform.service.ThemeService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
@ -14,7 +13,6 @@ import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 主题字典控制器(超管端)
|
||||
@ -29,47 +27,40 @@ public class AdminThemeController {
|
||||
|
||||
@GetMapping
|
||||
@Operation(summary = "查询所有主题")
|
||||
public Result<List<ThemeResponse>> findAll() {
|
||||
List<Theme> themes = themeService.findAll();
|
||||
List<ThemeResponse> responses = themes.stream()
|
||||
.map(this::toResponse)
|
||||
.collect(Collectors.toList());
|
||||
return Result.success(responses);
|
||||
public Result<List<Theme>> findAll() {
|
||||
return Result.success(themeService.findAll());
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
@Operation(summary = "查询主题详情")
|
||||
public Result<ThemeResponse> findOne(@PathVariable Long id) {
|
||||
Theme theme = themeService.findById(id);
|
||||
return Result.success(toResponse(theme));
|
||||
public Result<Theme> findOne(@PathVariable Long id) {
|
||||
return Result.success(themeService.findById(id));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@Operation(summary = "创建主题")
|
||||
@RequireRole(UserRole.ADMIN)
|
||||
public Result<ThemeResponse> create(@Valid @RequestBody ThemeCreateRequest request) {
|
||||
Theme theme = themeService.create(
|
||||
public Result<Theme> create(@Valid @RequestBody ThemeCreateRequest request) {
|
||||
return Result.success(themeService.create(
|
||||
request.getName(),
|
||||
request.getDescription(),
|
||||
request.getSortOrder()
|
||||
);
|
||||
return Result.success(toResponse(theme));
|
||||
));
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
@Operation(summary = "更新主题")
|
||||
@RequireRole(UserRole.ADMIN)
|
||||
public Result<ThemeResponse> update(
|
||||
public Result<Theme> update(
|
||||
@PathVariable Long id,
|
||||
@RequestBody ThemeCreateRequest request) {
|
||||
Theme theme = themeService.update(
|
||||
return Result.success(themeService.update(
|
||||
id,
|
||||
request.getName(),
|
||||
request.getDescription(),
|
||||
request.getSortOrder(),
|
||||
null
|
||||
);
|
||||
return Result.success(toResponse(theme));
|
||||
));
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
@ -87,19 +78,4 @@ public class AdminThemeController {
|
||||
themeService.reorder(ids);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 Theme 实体转换为 ThemeResponse
|
||||
*/
|
||||
private ThemeResponse toResponse(Theme theme) {
|
||||
return ThemeResponse.builder()
|
||||
.id(theme.getId())
|
||||
.name(theme.getName())
|
||||
.description(theme.getDescription())
|
||||
.sortOrder(theme.getSortOrder())
|
||||
.status(theme.getStatus())
|
||||
.createdAt(theme.getCreatedAt())
|
||||
.updatedAt(theme.getUpdatedAt())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
package com.reading.platform.controller.teacher;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.reading.platform.common.enums.CourseStatus;
|
||||
import com.reading.platform.common.mapper.ClassMapper;
|
||||
import com.reading.platform.common.mapper.CourseMapper;
|
||||
import com.reading.platform.common.mapper.StudentMapper;
|
||||
@ -69,7 +68,7 @@ public class TeacherCourseController {
|
||||
@RequestParam(required = false) String keyword,
|
||||
@RequestParam(required = false) String category) {
|
||||
Long tenantId = SecurityUtils.getCurrentTenantId();
|
||||
Page<Course> page = courseService.getCoursePage(tenantId, pageNum, pageSize, keyword, category, CourseStatus.PUBLISHED.getCode());
|
||||
Page<Course> page = courseService.getCoursePage(tenantId, pageNum, pageSize, keyword, category, "published");
|
||||
List<CourseResponse> voList = courseMapper.toVO(page.getRecords());
|
||||
return Result.success(PageResult.of(voList, page.getTotal(), page.getCurrent(), page.getSize()));
|
||||
}
|
||||
|
||||
@ -1,29 +0,0 @@
|
||||
package com.reading.platform.dto.request;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 教学环节创建请求
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "教学环节创建请求")
|
||||
public class LessonStepCreateRequest {
|
||||
|
||||
@Schema(description = "环节名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "环节内容")
|
||||
private String content;
|
||||
|
||||
@Schema(description = "时长(分钟)")
|
||||
private Integer duration;
|
||||
|
||||
@Schema(description = "教学目标")
|
||||
private String objective;
|
||||
|
||||
@Schema(description = "关联资源 ID 列表")
|
||||
private List<Long> resourceIds;
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
package com.reading.platform.dto.request;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 套餐授权请求
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "套餐授权请求")
|
||||
public class PackageGrantRequest {
|
||||
|
||||
@Schema(description = "租户 ID")
|
||||
private Long tenantId;
|
||||
|
||||
@Schema(description = "结束日期")
|
||||
private String endDate;
|
||||
|
||||
@Schema(description = "支付金额(分)")
|
||||
private Long pricePaid;
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
package com.reading.platform.dto.request;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 套餐审核请求
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "套餐审核请求")
|
||||
public class PackageReviewRequest {
|
||||
|
||||
@Schema(description = "是否通过")
|
||||
private Boolean approved;
|
||||
|
||||
@Schema(description = "审核意见")
|
||||
private String comment;
|
||||
|
||||
@Schema(description = "是否同时发布(仅当 approved=true 时有效)")
|
||||
private Boolean publish;
|
||||
}
|
||||
@ -1,36 +0,0 @@
|
||||
package com.reading.platform.dto.request;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 资源项目创建请求
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "资源项目创建请求")
|
||||
public class ResourceItemCreateRequest {
|
||||
|
||||
@Schema(description = "资源库 ID")
|
||||
private String libraryId;
|
||||
|
||||
@Schema(description = "资源标题")
|
||||
private String title;
|
||||
|
||||
@Schema(description = "文件类型")
|
||||
private String fileType;
|
||||
|
||||
@Schema(description = "文件路径")
|
||||
private String filePath;
|
||||
|
||||
@Schema(description = "文件大小(字节)")
|
||||
private Long fileSize;
|
||||
|
||||
@Schema(description = "资源描述")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "标签")
|
||||
private String tags;
|
||||
|
||||
@Schema(description = "租户 ID")
|
||||
private String tenantId;
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
package com.reading.platform.dto.request;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 资源项目更新请求
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "资源项目更新请求")
|
||||
public class ResourceItemUpdateRequest {
|
||||
|
||||
@Schema(description = "资源标题")
|
||||
private String title;
|
||||
|
||||
@Schema(description = "资源描述")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "标签")
|
||||
private String tags;
|
||||
}
|
||||
@ -1,24 +0,0 @@
|
||||
package com.reading.platform.dto.request;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 资源库创建请求
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "资源库创建请求")
|
||||
public class ResourceLibraryCreateRequest {
|
||||
|
||||
@Schema(description = "资源库名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "资源库类型")
|
||||
private String type;
|
||||
|
||||
@Schema(description = "资源库描述")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "租户 ID")
|
||||
private String tenantId;
|
||||
}
|
||||
@ -1,18 +0,0 @@
|
||||
package com.reading.platform.dto.request;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 资源库更新请求
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "资源库更新请求")
|
||||
public class ResourceLibraryUpdateRequest {
|
||||
|
||||
@Schema(description = "资源库名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "资源库描述")
|
||||
private String description;
|
||||
}
|
||||
@ -16,7 +16,7 @@ import java.time.LocalDateTime;
|
||||
public class ResourceItemResponse {
|
||||
|
||||
@Schema(description = "ID")
|
||||
private Long id;
|
||||
private String id;
|
||||
|
||||
@Schema(description = "资源库 ID")
|
||||
private String libraryId;
|
||||
|
||||
@ -16,7 +16,7 @@ import java.time.LocalDateTime;
|
||||
public class ResourceLibraryResponse {
|
||||
|
||||
@Schema(description = "ID")
|
||||
private Long id;
|
||||
private String id;
|
||||
|
||||
@Schema(description = "租户 ID")
|
||||
private String tenantId;
|
||||
|
||||
@ -37,7 +37,7 @@ public class CoursePackage extends BaseEntity {
|
||||
@Schema(description = "课程数量")
|
||||
private Integer courseCount;
|
||||
|
||||
@Schema(description = "状态:DRAFT、PENDING、APPROVED、REJECTED、PUBLISHED、OFFLINE")
|
||||
@Schema(description = "状态:DRAFT、PENDING_REVIEW、APPROVED、REJECTED、PUBLISHED、OFFLINE")
|
||||
private String status;
|
||||
|
||||
@Schema(description = "提交时间")
|
||||
|
||||
@ -300,15 +300,10 @@ public class CoursePackageService extends ServiceImpl<CoursePackageMapper, Cours
|
||||
|
||||
/**
|
||||
* 审核套餐
|
||||
* @param id 套餐ID
|
||||
* @param userId 审核人ID
|
||||
* @param approved 是否通过
|
||||
* @param comment 审核意见
|
||||
* @param publish 是否同时发布(仅当 approved=true 时有效)
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void reviewPackage(Long id, Long userId, Boolean approved, String comment, Boolean publish) {
|
||||
log.info("审核套餐,id={}, userId={}, approved={}, publish={}", id, userId, approved, publish);
|
||||
public void reviewPackage(Long id, Long userId, Boolean approved, String comment) {
|
||||
log.info("审核套餐,id={}, userId={}, approved={}", id, userId, approved);
|
||||
CoursePackage pkg = packageMapper.selectById(id);
|
||||
if (pkg == null) {
|
||||
log.warn("套餐不存在,id={}", id);
|
||||
@ -320,27 +315,12 @@ public class CoursePackageService extends ServiceImpl<CoursePackageMapper, Cours
|
||||
throw new BusinessException("只有待审核状态的套餐可以审核");
|
||||
}
|
||||
|
||||
// 如果驳回
|
||||
if (!Boolean.TRUE.equals(approved)) {
|
||||
pkg.setStatus(CourseStatus.REJECTED.getCode());
|
||||
}
|
||||
// 如果通过且同时发布
|
||||
else if (Boolean.TRUE.equals(publish)) {
|
||||
pkg.setStatus(CourseStatus.PUBLISHED.getCode());
|
||||
pkg.setPublishedAt(LocalDateTime.now());
|
||||
}
|
||||
// 仅通过
|
||||
else {
|
||||
pkg.setStatus(CourseStatus.APPROVED.getCode());
|
||||
}
|
||||
|
||||
pkg.setStatus(approved ? CourseStatus.APPROVED.getCode() : CourseStatus.REJECTED.getCode());
|
||||
pkg.setReviewedAt(LocalDateTime.now());
|
||||
pkg.setReviewedBy(userId);
|
||||
pkg.setReviewComment(comment);
|
||||
packageMapper.updateById(pkg);
|
||||
log.info("套餐审核成功,id={}, result={}", id,
|
||||
!Boolean.TRUE.equals(approved) ? "rejected" :
|
||||
(Boolean.TRUE.equals(publish) ? "approved_and_published" : "approved"));
|
||||
log.info("套餐审核成功,id={}, result={}", id, approved ? "approved" : "rejected");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,43 +0,0 @@
|
||||
package com.reading.platform.service;
|
||||
|
||||
import com.reading.platform.dto.request.ActiveTenantsQueryRequest;
|
||||
import com.reading.platform.dto.request.PopularCoursesQueryRequest;
|
||||
import com.reading.platform.dto.request.RecentActivitiesQueryRequest;
|
||||
import com.reading.platform.dto.response.ActiveTenantItemResponse;
|
||||
import com.reading.platform.dto.response.PopularCourseItemResponse;
|
||||
import com.reading.platform.dto.response.RecentActivityItemResponse;
|
||||
import com.reading.platform.dto.response.StatsResponse;
|
||||
import com.reading.platform.dto.response.StatsTrendResponse;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 统计服务接口
|
||||
*/
|
||||
public interface StatsService {
|
||||
|
||||
/**
|
||||
* 获取统计数据
|
||||
*/
|
||||
StatsResponse getStats();
|
||||
|
||||
/**
|
||||
* 获取趋势数据
|
||||
*/
|
||||
StatsTrendResponse getTrendData();
|
||||
|
||||
/**
|
||||
* 获取活跃租户
|
||||
*/
|
||||
List<ActiveTenantItemResponse> getActiveTenants(ActiveTenantsQueryRequest request);
|
||||
|
||||
/**
|
||||
* 获取热门课程
|
||||
*/
|
||||
List<PopularCourseItemResponse> getPopularCourses(PopularCoursesQueryRequest request);
|
||||
|
||||
/**
|
||||
* 获取最近活动
|
||||
*/
|
||||
List<RecentActivityItemResponse> getRecentActivities(RecentActivitiesQueryRequest request);
|
||||
}
|
||||
@ -3,7 +3,6 @@ package com.reading.platform.service;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.reading.platform.dto.request.TenantCreateRequest;
|
||||
import com.reading.platform.dto.request.TenantUpdateRequest;
|
||||
import com.reading.platform.dto.response.TenantResponse;
|
||||
import com.reading.platform.entity.Tenant;
|
||||
|
||||
import java.util.List;
|
||||
@ -33,11 +32,6 @@ public interface TenantService extends com.baomidou.mybatisplus.extension.servic
|
||||
*/
|
||||
Page<Tenant> getTenantPage(Integer pageNum, Integer pageSize, String keyword, String status);
|
||||
|
||||
/**
|
||||
* 分页查询租户(带教师和学生统计)
|
||||
*/
|
||||
Page<TenantResponse> getTenantPageWithStats(Integer pageNum, Integer pageSize, String keyword, String status);
|
||||
|
||||
/**
|
||||
* 删除租户
|
||||
*/
|
||||
|
||||
@ -6,7 +6,6 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.reading.platform.common.enums.CourseStatus;
|
||||
import com.reading.platform.common.enums.ErrorCode;
|
||||
import com.reading.platform.common.enums.TenantPackageStatus;
|
||||
import com.reading.platform.common.enums.YesNo;
|
||||
import com.reading.platform.common.exception.BusinessException;
|
||||
import com.reading.platform.dto.request.CourseCreateRequest;
|
||||
import com.reading.platform.dto.request.CourseUpdateRequest;
|
||||
@ -61,7 +60,7 @@ public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course>
|
||||
course.setDurationMinutes(request.getDurationMinutes());
|
||||
course.setObjectives(request.getObjectives());
|
||||
course.setStatus(CourseStatus.DRAFT.getCode());
|
||||
course.setIsSystem(YesNo.NO.getCode());
|
||||
course.setIsSystem(0);
|
||||
|
||||
// Course Package Fields
|
||||
course.setCoreContent(request.getCoreContent());
|
||||
@ -91,10 +90,10 @@ public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course>
|
||||
course.setAssessmentData(nullIfEmptyJson(request.getAssessmentData()));
|
||||
course.setGradeTags(nullIfEmptyJson(request.getGradeTags()));
|
||||
course.setDomainTags(nullIfEmptyJson(request.getDomainTags()));
|
||||
course.setHasCollectiveLesson(YesNo.fromBoolean(request.getHasCollectiveLesson()).getCode());
|
||||
course.setHasCollectiveLesson(request.getHasCollectiveLesson() != null && request.getHasCollectiveLesson() ? 1 : 0);
|
||||
|
||||
course.setVersion("1.0");
|
||||
course.setIsLatest(YesNo.YES.getCode());
|
||||
course.setIsLatest(1);
|
||||
course.setUsageCount(0);
|
||||
course.setTeacherCount(0);
|
||||
|
||||
@ -122,7 +121,7 @@ public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course>
|
||||
course.setDurationMinutes(request.getDurationMinutes());
|
||||
course.setObjectives(request.getObjectives());
|
||||
course.setStatus(CourseStatus.DRAFT.getCode());
|
||||
course.setIsSystem(YesNo.YES.getCode());
|
||||
course.setIsSystem(1);
|
||||
|
||||
// Course Package Fields
|
||||
course.setCoreContent(request.getCoreContent());
|
||||
@ -152,10 +151,10 @@ public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course>
|
||||
course.setAssessmentData(nullIfEmptyJson(request.getAssessmentData()));
|
||||
course.setGradeTags(nullIfEmptyJson(request.getGradeTags()));
|
||||
course.setDomainTags(nullIfEmptyJson(request.getDomainTags()));
|
||||
course.setHasCollectiveLesson(YesNo.fromBoolean(request.getHasCollectiveLesson()).getCode());
|
||||
course.setHasCollectiveLesson(request.getHasCollectiveLesson() != null && request.getHasCollectiveLesson() ? 1 : 0);
|
||||
|
||||
course.setVersion("1.0");
|
||||
course.setIsLatest(YesNo.YES.getCode());
|
||||
course.setIsLatest(1);
|
||||
course.setUsageCount(0);
|
||||
course.setTeacherCount(0);
|
||||
|
||||
@ -288,7 +287,7 @@ public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course>
|
||||
course.setDomainTags(nullIfEmptyJson(request.getDomainTags()));
|
||||
}
|
||||
if (request.getHasCollectiveLesson() != null) {
|
||||
course.setHasCollectiveLesson(YesNo.fromBoolean(request.getHasCollectiveLesson()).getCode());
|
||||
course.setHasCollectiveLesson(request.getHasCollectiveLesson() ? 1 : 0);
|
||||
}
|
||||
|
||||
courseMapper.updateById(course);
|
||||
@ -347,7 +346,7 @@ public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course>
|
||||
wrapper.and(w -> w
|
||||
.eq(Course::getTenantId, tenantId)
|
||||
.or()
|
||||
.eq(Course::getIsSystem, YesNo.YES.getCode())
|
||||
.eq(Course::getIsSystem, 1)
|
||||
);
|
||||
|
||||
if (StringUtils.hasText(keyword)) {
|
||||
@ -375,7 +374,7 @@ public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course>
|
||||
LambdaQueryWrapper<Course> wrapper = new LambdaQueryWrapper<>();
|
||||
|
||||
// 只过滤系统课程
|
||||
wrapper.eq(Course::getIsSystem, YesNo.YES.getCode());
|
||||
wrapper.eq(Course::getIsSystem, 1);
|
||||
|
||||
// 审核管理页:仅过滤待审核和已驳回,排除已通过/已发布
|
||||
if (reviewOnly) {
|
||||
@ -454,7 +453,7 @@ public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course>
|
||||
.and(w -> w
|
||||
.eq(Course::getTenantId, tenantId)
|
||||
.or()
|
||||
.eq(Course::getIsSystem, YesNo.YES.getCode())
|
||||
.eq(Course::getIsSystem, 1)
|
||||
)
|
||||
.eq(Course::getStatus, CourseStatus.PUBLISHED.getCode())
|
||||
.orderByAsc(Course::getName)
|
||||
|
||||
@ -1,224 +0,0 @@
|
||||
package com.reading.platform.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.reading.platform.dto.request.ActiveTenantsQueryRequest;
|
||||
import com.reading.platform.dto.request.PopularCoursesQueryRequest;
|
||||
import com.reading.platform.dto.request.RecentActivitiesQueryRequest;
|
||||
import com.reading.platform.dto.response.ActiveTenantItemResponse;
|
||||
import com.reading.platform.dto.response.PopularCourseItemResponse;
|
||||
import com.reading.platform.dto.response.RecentActivityItemResponse;
|
||||
import com.reading.platform.dto.response.StatsResponse;
|
||||
import com.reading.platform.dto.response.StatsTrendResponse;
|
||||
import com.reading.platform.entity.Course;
|
||||
import com.reading.platform.entity.CourseLesson;
|
||||
import com.reading.platform.entity.Student;
|
||||
import com.reading.platform.entity.Teacher;
|
||||
import com.reading.platform.entity.Tenant;
|
||||
import com.reading.platform.mapper.CourseLessonMapper;
|
||||
import com.reading.platform.mapper.CourseMapper;
|
||||
import com.reading.platform.mapper.StudentMapper;
|
||||
import com.reading.platform.mapper.TeacherMapper;
|
||||
import com.reading.platform.mapper.TenantMapper;
|
||||
import com.reading.platform.service.StatsService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 统计服务实现类
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class StatsServiceImpl implements StatsService {
|
||||
|
||||
private final TenantMapper tenantMapper;
|
||||
private final TeacherMapper teacherMapper;
|
||||
private final StudentMapper studentMapper;
|
||||
private final CourseMapper courseMapper;
|
||||
private final CourseLessonMapper courseLessonMapper;
|
||||
|
||||
@Override
|
||||
public StatsResponse getStats() {
|
||||
log.info("获取统计数据");
|
||||
|
||||
// 租户总数
|
||||
Long totalTenants = tenantMapper.selectCount(null);
|
||||
|
||||
// 活跃租户数
|
||||
Long activeTenants = tenantMapper.selectCount(
|
||||
new LambdaQueryWrapper<Tenant>().eq(Tenant::getStatus, "ACTIVE")
|
||||
);
|
||||
|
||||
// 教师总数
|
||||
Long totalTeachers = teacherMapper.selectCount(null);
|
||||
|
||||
// 学生总数
|
||||
Long totalStudents = studentMapper.selectCount(null);
|
||||
|
||||
// 课程总数
|
||||
Long totalCourses = courseMapper.selectCount(null);
|
||||
|
||||
// 课时总数
|
||||
Long totalLessons = courseLessonMapper.selectCount(null);
|
||||
|
||||
return StatsResponse.builder()
|
||||
.totalTenants(totalTenants)
|
||||
.activeTenants(activeTenants)
|
||||
.totalTeachers(totalTeachers)
|
||||
.totalStudents(totalStudents)
|
||||
.totalCourses(totalCourses)
|
||||
.totalLessons(totalLessons)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public StatsTrendResponse getTrendData() {
|
||||
log.info("获取趋势数据");
|
||||
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
List<String> dates = new ArrayList<>();
|
||||
List<Integer> newStudents = new ArrayList<>();
|
||||
List<Integer> newTeachers = new ArrayList<>();
|
||||
List<Integer> newCourses = new ArrayList<>();
|
||||
|
||||
// 获取最近 7 天的趋势数据
|
||||
for (int i = 6; i >= 0; i--) {
|
||||
LocalDate date = now.minusDays(i).toLocalDate();
|
||||
dates.add(date.format(DateTimeFormatter.ofPattern("MM-dd")));
|
||||
|
||||
// 当天新增学生数
|
||||
LocalDateTime dayStart = date.atStartOfDay();
|
||||
LocalDateTime dayEnd = date.plusDays(1).atStartOfDay();
|
||||
|
||||
Long students = studentMapper.selectCount(
|
||||
new LambdaQueryWrapper<Student>()
|
||||
.ge(Student::getCreatedAt, dayStart)
|
||||
.lt(Student::getCreatedAt, dayEnd)
|
||||
);
|
||||
newStudents.add(students != null ? students.intValue() : 0);
|
||||
|
||||
// 当天新增教师数
|
||||
Long teachers = teacherMapper.selectCount(
|
||||
new LambdaQueryWrapper<Teacher>()
|
||||
.ge(Teacher::getCreatedAt, dayStart)
|
||||
.lt(Teacher::getCreatedAt, dayEnd)
|
||||
);
|
||||
newTeachers.add(teachers != null ? teachers.intValue() : 0);
|
||||
|
||||
// 当天新增课程数
|
||||
Long courses = courseMapper.selectCount(
|
||||
new LambdaQueryWrapper<Course>()
|
||||
.ge(Course::getCreatedAt, dayStart)
|
||||
.lt(Course::getCreatedAt, dayEnd)
|
||||
);
|
||||
newCourses.add(courses != null ? courses.intValue() : 0);
|
||||
}
|
||||
|
||||
return StatsTrendResponse.builder()
|
||||
.dates(dates)
|
||||
.newStudents(newStudents)
|
||||
.newTeachers(newTeachers)
|
||||
.newCourses(newCourses)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ActiveTenantItemResponse> getActiveTenants(ActiveTenantsQueryRequest request) {
|
||||
log.info("获取活跃租户,limit={}", request != null ? request.getLimit() : 10);
|
||||
|
||||
int limit = request != null && request.getLimit() != null ? request.getLimit() : 10;
|
||||
|
||||
// 查询所有活跃租户
|
||||
List<Tenant> tenants = tenantMapper.selectList(
|
||||
new LambdaQueryWrapper<Tenant>()
|
||||
.eq(Tenant::getStatus, "ACTIVE")
|
||||
.orderByDesc(Tenant::getUpdatedAt)
|
||||
.last("LIMIT " + limit)
|
||||
);
|
||||
|
||||
return tenants.stream().map(tenant -> {
|
||||
// 查询该租户的活跃用户数(教师+学生)
|
||||
Long teacherCount = teacherMapper.selectCount(
|
||||
new LambdaQueryWrapper<Teacher>().eq(Teacher::getTenantId, tenant.getId())
|
||||
);
|
||||
Long studentCount = studentMapper.selectCount(
|
||||
new LambdaQueryWrapper<Student>().eq(Student::getTenantId, tenant.getId())
|
||||
);
|
||||
|
||||
// 查询该租户使用的课程数(通过租户套餐)
|
||||
// 简化处理,返回 0
|
||||
int courseCount = 0;
|
||||
|
||||
return ActiveTenantItemResponse.builder()
|
||||
.tenantId(tenant.getId())
|
||||
.tenantName(tenant.getName())
|
||||
.activeUsers((teacherCount != null ? teacherCount.intValue() : 0) +
|
||||
(studentCount != null ? studentCount.intValue() : 0))
|
||||
.courseCount(courseCount)
|
||||
.build();
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PopularCourseItemResponse> getPopularCourses(PopularCoursesQueryRequest request) {
|
||||
log.info("获取热门课程,limit={}", request != null ? request.getLimit() : 10);
|
||||
|
||||
int limit = request != null && request.getLimit() != null ? request.getLimit() : 10;
|
||||
|
||||
// 查询使用次数最多的课程
|
||||
List<Course> courses = courseMapper.selectList(
|
||||
new LambdaQueryWrapper<Course>()
|
||||
.eq(Course::getIsSystem, 1)
|
||||
.orderByDesc(Course::getUsageCount)
|
||||
.last("LIMIT " + limit)
|
||||
);
|
||||
|
||||
return courses.stream().map(course -> PopularCourseItemResponse.builder()
|
||||
.courseId(course.getId())
|
||||
.courseName(course.getName())
|
||||
.usageCount(course.getUsageCount() != null ? course.getUsageCount() : 0)
|
||||
.teacherCount(course.getTeacherCount() != null ? course.getTeacherCount() : 0)
|
||||
.build()
|
||||
).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RecentActivityItemResponse> getRecentActivities(RecentActivitiesQueryRequest request) {
|
||||
log.info("获取最近活动,limit={}", request != null ? request.getLimit() : 10);
|
||||
|
||||
int limit = request != null && request.getLimit() != null ? request.getLimit() : 10;
|
||||
|
||||
// 由于没有专门的活动记录表,这里返回空列表
|
||||
// 实际项目中应该从操作日志表获取
|
||||
List<RecentActivityItemResponse> activities = new ArrayList<>();
|
||||
|
||||
// 可以从最近的课程更新中生成一些活动记录
|
||||
List<Course> recentCourses = courseMapper.selectList(
|
||||
new LambdaQueryWrapper<Course>()
|
||||
.orderByDesc(Course::getUpdatedAt)
|
||||
.last("LIMIT " + limit)
|
||||
);
|
||||
|
||||
for (Course course : recentCourses) {
|
||||
activities.add(RecentActivityItemResponse.builder()
|
||||
.activityId(course.getId())
|
||||
.activityType("COURSE_UPDATE")
|
||||
.description("课程「" + course.getName() + "」已更新")
|
||||
.operatorId(course.getSubmittedBy())
|
||||
.operatorName("系统")
|
||||
.operationTime(course.getUpdatedAt())
|
||||
.build());
|
||||
}
|
||||
|
||||
return activities;
|
||||
}
|
||||
}
|
||||
@ -7,14 +7,9 @@ import com.reading.platform.common.enums.TenantPackageStatus;
|
||||
import com.reading.platform.common.exception.BusinessException;
|
||||
import com.reading.platform.dto.request.TenantCreateRequest;
|
||||
import com.reading.platform.dto.request.TenantUpdateRequest;
|
||||
import com.reading.platform.dto.response.TenantResponse;
|
||||
import com.reading.platform.entity.CoursePackage;
|
||||
import com.reading.platform.entity.Student;
|
||||
import com.reading.platform.entity.Teacher;
|
||||
import com.reading.platform.entity.Tenant;
|
||||
import com.reading.platform.entity.TenantPackage;
|
||||
import com.reading.platform.mapper.StudentMapper;
|
||||
import com.reading.platform.mapper.TeacherMapper;
|
||||
import com.reading.platform.mapper.TenantMapper;
|
||||
import com.reading.platform.mapper.TenantPackageMapper;
|
||||
import com.reading.platform.service.CoursePackageService;
|
||||
@ -27,7 +22,6 @@ import org.springframework.util.StringUtils;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 租户服务实现类
|
||||
@ -41,8 +35,6 @@ public class TenantServiceImpl extends com.baomidou.mybatisplus.extension.servic
|
||||
private final TenantMapper tenantMapper;
|
||||
private final TenantPackageMapper tenantPackageMapper;
|
||||
private final CoursePackageService coursePackageService;
|
||||
private final TeacherMapper teacherMapper;
|
||||
private final StudentMapper studentMapper;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
@ -248,67 +240,4 @@ public class TenantServiceImpl extends com.baomidou.mybatisplus.extension.servic
|
||||
return tenants;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<TenantResponse> getTenantPageWithStats(Integer pageNum, Integer pageSize, String keyword, String status) {
|
||||
log.debug("分页查询租户(带统计),页码:{},每页数量:{}", pageNum, pageSize);
|
||||
|
||||
// 先查询租户分页数据
|
||||
Page<Tenant> tenantPage = getTenantPage(pageNum, pageSize, keyword, status);
|
||||
|
||||
// 转换为 TenantResponse 并填充统计信息
|
||||
List<TenantResponse> responses = tenantPage.getRecords().stream()
|
||||
.map(this::toResponseWithStats)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 构建返回的分页对象
|
||||
Page<TenantResponse> resultPage = new Page<>(tenantPage.getCurrent(), tenantPage.getSize(), tenantPage.getTotal());
|
||||
resultPage.setRecords(responses);
|
||||
|
||||
return resultPage;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 Tenant 实体转换为 TenantResponse(带教师和学生统计)
|
||||
*/
|
||||
private TenantResponse toResponseWithStats(Tenant tenant) {
|
||||
// 查询教师数量
|
||||
Long teacherCount = teacherMapper.selectCount(
|
||||
new LambdaQueryWrapper<Teacher>()
|
||||
.eq(Teacher::getTenantId, tenant.getId())
|
||||
);
|
||||
|
||||
// 查询学生数量
|
||||
Long studentCount = studentMapper.selectCount(
|
||||
new LambdaQueryWrapper<Student>()
|
||||
.eq(Student::getTenantId, tenant.getId())
|
||||
);
|
||||
|
||||
return TenantResponse.builder()
|
||||
.id(tenant.getId())
|
||||
.name(tenant.getName())
|
||||
.code(tenant.getCode())
|
||||
.username(tenant.getUsername())
|
||||
.contactName(tenant.getContactName())
|
||||
.contactPhone(tenant.getContactPhone())
|
||||
.contactEmail(tenant.getContactEmail())
|
||||
.address(tenant.getAddress())
|
||||
.logoUrl(tenant.getLogoUrl())
|
||||
.status(tenant.getStatus())
|
||||
.expireAt(tenant.getExpireAt())
|
||||
.maxStudents(tenant.getMaxStudents())
|
||||
.maxTeachers(tenant.getMaxTeachers())
|
||||
.packageType(tenant.getPackageType())
|
||||
.teacherQuota(tenant.getTeacherQuota())
|
||||
.studentQuota(tenant.getStudentQuota())
|
||||
.storageQuota(tenant.getStorageQuota())
|
||||
.storageUsed(tenant.getStorageUsed())
|
||||
.teacherCount(teacherCount != null ? teacherCount.intValue() : 0)
|
||||
.studentCount(studentCount != null ? studentCount.intValue() : 0)
|
||||
.startDate(tenant.getStartDate())
|
||||
.expireDate(tenant.getExpireDate())
|
||||
.createdAt(tenant.getCreatedAt())
|
||||
.updatedAt(tenant.getUpdatedAt())
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user