feat: 课程包年级筛选与适用年级对齐,修复JSON_CONTAINS占位符
Made-with: Cursor
This commit is contained in:
parent
fceef0fa12
commit
4122bcd240
@ -1,15 +1,19 @@
|
|||||||
import { getReadingPlatformAPI } from './generated';
|
import { getReadingPlatformAPI } from "./generated";
|
||||||
import { axios, customMutator } from './generated/mutator';
|
import { axios, customMutator } from "./generated/mutator";
|
||||||
|
|
||||||
// 创建 API 实例
|
// 创建 API 实例
|
||||||
const api = getReadingPlatformAPI();
|
const api = getReadingPlatformAPI();
|
||||||
|
|
||||||
// 封装 http 方法(兼容原有代码)
|
// 封装 http 方法(兼容原有代码)
|
||||||
export const http = {
|
export const http = {
|
||||||
get: <T = any>(url: string, config?: any) => customMutator<T>({ url, method: 'get', ...config }),
|
get: <T = any>(url: string, config?: any) =>
|
||||||
post: <T = any>(url: string, data?: any, config?: any) => customMutator<T>({ url, method: 'post', data, ...config }),
|
customMutator<T>({ url, method: "get", ...config }),
|
||||||
put: <T = any>(url: string, data?: any, config?: any) => customMutator<T>({ url, method: 'put', data, ...config }),
|
post: <T = any>(url: string, data?: any, config?: any) =>
|
||||||
delete: <T = any>(url: string, config?: any) => customMutator<T>({ url, method: 'delete', ...config }),
|
customMutator<T>({ url, method: "post", data, ...config }),
|
||||||
|
put: <T = any>(url: string, data?: any, config?: any) =>
|
||||||
|
customMutator<T>({ url, method: "put", data, ...config }),
|
||||||
|
delete: <T = any>(url: string, config?: any) =>
|
||||||
|
customMutator<T>({ url, method: "delete", ...config }),
|
||||||
};
|
};
|
||||||
|
|
||||||
// ============= 类型定义(保持向后兼容) =============
|
// ============= 类型定义(保持向后兼容) =============
|
||||||
@ -18,7 +22,7 @@ export interface CourseQueryParams {
|
|||||||
pageNum?: number;
|
pageNum?: number;
|
||||||
pageSize?: number;
|
pageSize?: number;
|
||||||
grade?: string;
|
grade?: string;
|
||||||
gradeTags?: string; // 年级筛选(逗号分隔,如 "小班,中班,大班")
|
gradeTags?: string; // 年级筛选(逗号分隔,如 "小班,中班,大班")
|
||||||
status?: string;
|
status?: string;
|
||||||
keyword?: string;
|
keyword?: string;
|
||||||
/** 审核管理页专用:仅返回待审核和已驳回,排除已通过 */
|
/** 审核管理页专用:仅返回待审核和已驳回,排除已通过 */
|
||||||
@ -126,7 +130,7 @@ const toFindAllParams = (params: CourseQueryParams): any => ({
|
|||||||
pageSize: params.pageSize ?? 10,
|
pageSize: params.pageSize ?? 10,
|
||||||
keyword: params.keyword,
|
keyword: params.keyword,
|
||||||
category: params.grade,
|
category: params.grade,
|
||||||
gradeTags: params.gradeTags, // 年级筛选(逗号分隔)
|
gradeTags: params.gradeTags, // 年级筛选(逗号分隔)
|
||||||
status: params.status || undefined,
|
status: params.status || undefined,
|
||||||
reviewOnly: params.reviewOnly,
|
reviewOnly: params.reviewOnly,
|
||||||
});
|
});
|
||||||
@ -149,13 +153,20 @@ function normalizePageResult(raw: any): {
|
|||||||
|
|
||||||
// 获取课程包列表(7 步流程创建的教学资源)
|
// 获取课程包列表(7 步流程创建的教学资源)
|
||||||
// 注意:这里的 Course 实际对应后端的 CoursePackage(课程包)
|
// 注意:这里的 Course 实际对应后端的 CoursePackage(课程包)
|
||||||
|
// 使用扁平 query 参数,确保 gradeTags(适用年级)正确传给后端
|
||||||
export function getCourses(params: CourseQueryParams): Promise<{
|
export function getCourses(params: CourseQueryParams): Promise<{
|
||||||
items: Course[];
|
items: Course[];
|
||||||
total: number;
|
total: number;
|
||||||
page: number;
|
page: number;
|
||||||
pageSize: number;
|
pageSize: number;
|
||||||
}> {
|
}> {
|
||||||
return api.getCoursePage1(toFindAllParams(params)).then(normalizePageResult) as any;
|
const flatParams = toFindAllParams(params);
|
||||||
|
return http
|
||||||
|
.get<{ list?: Course[]; items?: Course[]; total?: number; pageNum?: number; pageSize?: number }>(
|
||||||
|
"/v1/admin/packages",
|
||||||
|
{ params: flatParams }
|
||||||
|
)
|
||||||
|
.then(normalizePageResult) as any;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取审核列表(仅返回待审核和已驳回,不含已通过)
|
// 获取审核列表(仅返回待审核和已驳回,不含已通过)
|
||||||
@ -165,7 +176,13 @@ export function getReviewList(params: CourseQueryParams): Promise<{
|
|||||||
page: number;
|
page: number;
|
||||||
pageSize: number;
|
pageSize: number;
|
||||||
}> {
|
}> {
|
||||||
return api.getCoursePage1(toFindAllParams({ ...params, reviewOnly: true })).then(normalizePageResult) as any;
|
const flatParams = toFindAllParams({ ...params, reviewOnly: true });
|
||||||
|
return http
|
||||||
|
.get<{ list?: Course[]; items?: Course[]; total?: number; pageNum?: number; pageSize?: number }>(
|
||||||
|
"/v1/admin/packages",
|
||||||
|
{ params: flatParams }
|
||||||
|
)
|
||||||
|
.then(normalizePageResult) as any;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取课程包详情(id 支持 number | string,避免大整数精度丢失)
|
// 获取课程包详情(id 支持 number | string,避免大整数精度丢失)
|
||||||
@ -197,8 +214,14 @@ export function validateCourse(_id: number): Promise<ValidationResult> {
|
|||||||
export function submitCourse(id: number | string): Promise<any> {
|
export function submitCourse(id: number | string): Promise<any> {
|
||||||
return http.post(`/v1/admin/packages/${id}/submit`).then((res: any) => {
|
return http.post(`/v1/admin/packages/${id}/submit`).then((res: any) => {
|
||||||
const body = res;
|
const body = res;
|
||||||
if (body && typeof body === 'object' && 'code' in body && body.code !== 200 && body.code !== 0) {
|
if (
|
||||||
throw new Error(body.message || '提交失败');
|
body &&
|
||||||
|
typeof body === "object" &&
|
||||||
|
"code" in body &&
|
||||||
|
body.code !== 200 &&
|
||||||
|
body.code !== 0
|
||||||
|
) {
|
||||||
|
throw new Error(body.message || "提交失败");
|
||||||
}
|
}
|
||||||
return body?.data;
|
return body?.data;
|
||||||
});
|
});
|
||||||
@ -206,27 +229,42 @@ export function submitCourse(id: number | string): Promise<any> {
|
|||||||
|
|
||||||
// 撤销审核 (暂时使用更新接口,需要确认后端是否有此功能)
|
// 撤销审核 (暂时使用更新接口,需要确认后端是否有此功能)
|
||||||
export function withdrawCourse(id: number): Promise<any> {
|
export function withdrawCourse(id: number): Promise<any> {
|
||||||
return api.updateCourse(id, { status: 'DRAFT' }) as any;
|
return api.updateCourse(id, { status: "DRAFT" }) as any;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 审核通过
|
// 审核通过
|
||||||
export function approveCourse(id: number, _data: { checklist?: any; comment?: string }): Promise<any> {
|
export function approveCourse(
|
||||||
|
id: number,
|
||||||
|
_data: { checklist?: any; comment?: string },
|
||||||
|
): Promise<any> {
|
||||||
return api.publishCourse(id) as any;
|
return api.publishCourse(id) as any;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 审核驳回(课程专用,调用 POST /v1/admin/packages/{id}/reject)
|
// 审核驳回(课程专用,调用 POST /v1/admin/packages/{id}/reject)
|
||||||
export function rejectCourse(id: number | string, data: { comment: string }): Promise<any> {
|
export function rejectCourse(
|
||||||
|
id: number | string,
|
||||||
|
data: { comment: string },
|
||||||
|
): Promise<any> {
|
||||||
return http.post(`/v1/admin/packages/${id}/reject`, data).then((res: any) => {
|
return http.post(`/v1/admin/packages/${id}/reject`, data).then((res: any) => {
|
||||||
const body = res;
|
const body = res;
|
||||||
if (body && typeof body === 'object' && 'code' in body && body.code !== 200 && body.code !== 0) {
|
if (
|
||||||
throw new Error(body.message || '驳回失败');
|
body &&
|
||||||
|
typeof body === "object" &&
|
||||||
|
"code" in body &&
|
||||||
|
body.code !== 200 &&
|
||||||
|
body.code !== 0
|
||||||
|
) {
|
||||||
|
throw new Error(body.message || "驳回失败");
|
||||||
}
|
}
|
||||||
return body?.data;
|
return body?.data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 直接发布(超级管理员)
|
// 直接发布(超级管理员)
|
||||||
export function directPublishCourse(id: number, _skipValidation?: boolean): Promise<any> {
|
export function directPublishCourse(
|
||||||
|
id: number,
|
||||||
|
_skipValidation?: boolean,
|
||||||
|
): Promise<any> {
|
||||||
return api.publishCourse(id) as any;
|
return api.publishCourse(id) as any;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,15 +296,18 @@ export function getCourseVersions(_id: number): Promise<any[]> {
|
|||||||
// ============= 常量 =============
|
// ============= 常量 =============
|
||||||
|
|
||||||
// 课程状态映射
|
// 课程状态映射
|
||||||
export const COURSE_STATUS_MAP: Record<string, { label: string; color: string }> = {
|
export const COURSE_STATUS_MAP: Record<
|
||||||
DRAFT: { label: '草稿', color: 'default' },
|
string,
|
||||||
PENDING: { label: '审核中', color: 'processing' },
|
{ label: string; color: string }
|
||||||
REJECTED: { label: '已驳回', color: 'error' },
|
> = {
|
||||||
PUBLISHED: { label: '已发布', color: 'success' },
|
DRAFT: { label: "草稿", color: "default" },
|
||||||
ARCHIVED: { label: '已下架', color: 'warning' },
|
PENDING: { label: "审核中", color: "processing" },
|
||||||
|
REJECTED: { label: "已驳回", color: "error" },
|
||||||
|
PUBLISHED: { label: "已发布", color: "success" },
|
||||||
|
ARCHIVED: { label: "已下架", color: "warning" },
|
||||||
};
|
};
|
||||||
|
|
||||||
// 获取状态显示信息
|
// 获取状态显示信息
|
||||||
export function getCourseStatusInfo(status: string) {
|
export function getCourseStatusInfo(status: string) {
|
||||||
return COURSE_STATUS_MAP[status] || { label: status, color: 'default' };
|
return COURSE_STATUS_MAP[status] || { label: status, color: "default" };
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
<a-row :gutter="16" align="middle">
|
<a-row :gutter="16" align="middle">
|
||||||
<a-col :span="16">
|
<a-col :span="16">
|
||||||
<a-space>
|
<a-space>
|
||||||
<a-select v-model:value="filters.gradeTags" placeholder="年级" style="width: 150px" allow-clear
|
<a-select v-model:value="filters.gradeTags" placeholder="适用年级" style="width: 180px" allow-clear
|
||||||
mode="multiple" @change="fetchCourses">
|
mode="multiple" @change="fetchCourses">
|
||||||
<a-select-option value="小班">小班</a-select-option>
|
<a-select-option value="小班">小班</a-select-option>
|
||||||
<a-select-option value="中班">中班</a-select-option>
|
<a-select-option value="中班">中班</a-select-option>
|
||||||
@ -59,12 +59,7 @@
|
|||||||
|
|
||||||
<template v-else-if="column.key === 'lessonConfig'">
|
<template v-else-if="column.key === 'lessonConfig'">
|
||||||
<div class="lesson-config-tags">
|
<div class="lesson-config-tags">
|
||||||
<a-tag
|
<a-tag v-for="lt in getLessonTypesFromRecord(record)" :key="lt" size="small" :style="getLessonTagStyle(lt)">
|
||||||
v-for="lt in getLessonTypesFromRecord(record)"
|
|
||||||
:key="lt"
|
|
||||||
size="small"
|
|
||||||
:style="getLessonTagStyle(lt)"
|
|
||||||
>
|
|
||||||
{{ getLessonTypeName(lt) }}
|
{{ getLessonTypeName(lt) }}
|
||||||
</a-tag>
|
</a-tag>
|
||||||
<span v-if="!getLessonTypesFromRecord(record).length" class="empty-text">-</span>
|
<span v-if="!getLessonTypesFromRecord(record).length" class="empty-text">-</span>
|
||||||
|
|||||||
@ -172,9 +172,9 @@ public class CoursePackageServiceImpl extends ServiceImpl<CoursePackageMapper, C
|
|||||||
String grade = selectedGrades[i].trim();
|
String grade = selectedGrades[i].trim();
|
||||||
if (StringUtils.hasText(grade)) {
|
if (StringUtils.hasText(grade)) {
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
w.apply("JSON_CONTAINS(grade_tags, ?)", "\"" + grade + "\"");
|
w.apply("JSON_CONTAINS(grade_tags, {0})", "\"" + grade + "\"");
|
||||||
} else {
|
} else {
|
||||||
w.or().apply("JSON_CONTAINS(grade_tags, ?)", "\"" + grade + "\"");
|
w.or().apply("JSON_CONTAINS(grade_tags, {0})", "\"" + grade + "\"");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user