fix(前端): 修复 ID 类型和分页 total 类型不匹配问题

- 将 Props 中 ID 字段从 number 改为 number | string,兼容后端 Long 序列化为 String
- 修复分页组件 total 字段类型,使用 Number() 转换避免 Vue warn
- 影响组件: PrepareNavigation, LessonCard, SelectLessonsModal 等
- 影响视图: StudentListView, TeacherListView, ParentListView 等
This commit is contained in:
En 2026-03-25 10:47:19 +08:00
parent 5c9be63347
commit 55343ead0b
34 changed files with 39 additions and 38 deletions

View File

@ -4,7 +4,8 @@
"Bash(mvn compile:*)", "Bash(mvn compile:*)",
"Bash(sed:*)", "Bash(sed:*)",
"Bash(grep:*)", "Bash(grep:*)",
"Bash(export:*)" "Bash(export:*)",
"Bash(git:*)"
] ]
} }
} }

View File

@ -133,7 +133,7 @@ import type { Theme } from '@/api/theme';
interface BasicInfoData { interface BasicInfoData {
name: string; name: string;
themeId: number | undefined; themeId: number | string | undefined;
grades: string[]; grades: string[];
pictureBookName: string; pictureBookName: string;
coreContent: string; coreContent: string;

View File

@ -63,7 +63,7 @@ import { getLessonByType, createLesson, updateLesson, deleteLesson as deleteLess
import { parseAssessmentDataForDisplay } from '@/utils/assessmentData'; import { parseAssessmentDataForDisplay } from '@/utils/assessmentData';
interface Props { interface Props {
courseId: number; courseId: number | string;
} }
const props = defineProps<Props>(); const props = defineProps<Props>();

View File

@ -63,7 +63,7 @@ import { getLessonByType, createLesson as createLessonApi, updateLesson, deleteL
import { parseAssessmentDataForDisplay } from '@/utils/assessmentData'; import { parseAssessmentDataForDisplay } from '@/utils/assessmentData';
interface Props { interface Props {
courseId: number; courseId: number | string;
courseName: string; courseName: string;
} }

View File

@ -106,7 +106,7 @@ interface DomainConfig {
} }
interface Props { interface Props {
courseId: number; courseId: number | string;
courseName: string; courseName: string;
} }

View File

@ -200,7 +200,7 @@ import LessonStepsEditor from './LessonStepsEditor.vue';
import type { StepData } from './LessonStepsEditor.vue'; import type { StepData } from './LessonStepsEditor.vue';
export interface LessonData { export interface LessonData {
id?: number; id?: number | string;
tempId?: string; tempId?: string;
lessonType: string; lessonType: string;
name: string; name: string;

View File

@ -95,7 +95,7 @@ import {
} from '@ant-design/icons-vue'; } from '@ant-design/icons-vue';
export interface StepData { export interface StepData {
id?: number; id?: number | string;
tempId?: string; tempId?: string;
name: string; name: string;
content: string; content: string;

View File

@ -163,7 +163,7 @@ const fetchData = async () => {
...(filters.status ? { status: filters.status } : {}), ...(filters.status ? { status: filters.status } : {}),
}); });
dataSource.value = data.items; dataSource.value = data.items;
pagination.total = data.total; pagination.total = Number(data.total);
} catch (error) { } catch (error) {
console.error('获取套餐列表失败', error); console.error('获取套餐列表失败', error);
message.error('获取套餐列表失败'); message.error('获取套餐列表失败');

View File

@ -267,7 +267,7 @@ const fetchCourses = async () => {
// API { items, total, page, pageSize } // API { items, total, page, pageSize }
courses.value = (data as any).items || []; courses.value = (data as any).items || [];
pagination.total = (data as any).total || 0; pagination.total = Number((data as any).total) || 0;
console.log('📊 课程列表数据:', courses.value, '总数:', pagination.total); console.log('📊 课程列表数据:', courses.value, '总数:', pagination.total);
} catch (error) { } catch (error) {
console.error('获取课程包列表失败:', error); console.error('获取课程包列表失败:', error);

View File

@ -250,7 +250,7 @@ const fetchCourses = async () => {
// //
validationPassed: item.status !== 'REJECTED', validationPassed: item.status !== 'REJECTED',
})); }));
pagination.total = data.total || 0; pagination.total = Number(data.total) || 0;
} catch (error) { } catch (error) {
console.error('获取审核列表失败:', error); console.error('获取审核列表失败:', error);
message.error('获取审核列表失败'); message.error('获取审核列表失败');

View File

@ -130,7 +130,7 @@ import type { Theme } from '@/api/theme';
interface BasicInfoData { interface BasicInfoData {
name: string; name: string;
themeId: number | undefined; themeId: number | string | undefined;
grades: string[]; grades: string[];
pictureBookName: string; pictureBookName: string;
coreContent: string; coreContent: string;

View File

@ -58,7 +58,7 @@ import type { LessonData } from '@/components/course/LessonConfigPanel.vue';
import { getLessonByType, createLesson, updateLesson, deleteLesson as deleteLessonApi } from '@/api/lesson'; import { getLessonByType, createLesson, updateLesson, deleteLesson as deleteLessonApi } from '@/api/lesson';
interface Props { interface Props {
courseId: number; courseId: number | string;
} }
const props = defineProps<Props>(); const props = defineProps<Props>();

View File

@ -58,7 +58,7 @@ import type { LessonData } from '@/components/course/LessonConfigPanel.vue';
import { getLessonByType, createLesson as createLessonApi, updateLesson, deleteLesson as deleteLessonApi } from '@/api/lesson'; import { getLessonByType, createLesson as createLessonApi, updateLesson, deleteLesson as deleteLessonApi } from '@/api/lesson';
interface Props { interface Props {
courseId: number; courseId: number | string;
courseName: string; courseName: string;
} }

View File

@ -101,7 +101,7 @@ interface DomainConfig {
} }
interface Props { interface Props {
courseId: number; courseId: number | string;
courseName: string; courseName: string;
} }

View File

@ -218,7 +218,7 @@ const fetchPackages = async () => {
pageSize: pagination.pageSize, pageSize: pagination.pageSize,
}) as any; }) as any;
packages.value = res.list || []; packages.value = res.list || [];
pagination.total = res.total || 0; pagination.total = Number(res.total) || 0;
} catch (error) { } catch (error) {
console.error('获取套餐列表失败:', error); console.error('获取套餐列表失败:', error);
message.error('获取套餐列表失败'); message.error('获取套餐列表失败');

View File

@ -511,7 +511,7 @@ const fetchItems = async () => {
...filters, ...filters,
}); });
items.value = result?.list ?? []; items.value = result?.list ?? [];
pagination.total = result?.total ?? 0; pagination.total = Number(result?.total) ?? 0;
} catch (error) { } catch (error) {
message.error('获取资源列表失败'); message.error('获取资源列表失败');
} finally { } finally {

View File

@ -483,7 +483,7 @@ const loadData = async () => {
collectionId: searchForm.collectionId, collectionId: searchForm.collectionId,
}); });
tenants.value = res.list; tenants.value = res.list;
pagination.total = res.total; pagination.total = Number(res.total);
} catch (error) { } catch (error) {
console.error('加载租户列表失败', error); console.error('加载租户列表失败', error);
} finally { } finally {

View File

@ -569,7 +569,7 @@ const loadClassStudents = async (classId: number) => {
pageSize: studentsPagination.pageSize, pageSize: studentsPagination.pageSize,
}); });
classStudents.value = result.list; classStudents.value = result.list;
studentsPagination.total = result.total; studentsPagination.total = Number(result.total);
} catch (error) { } catch (error) {
console.error('Failed to load class students:', error); console.error('Failed to load class students:', error);
} finally { } finally {

View File

@ -246,7 +246,7 @@ const loading = ref(false);
const authLoading = ref(false); const authLoading = ref(false);
const authModalVisible = ref(false); const authModalVisible = ref(false);
const searchKeyword = ref(''); const searchKeyword = ref('');
const selectedCourseIds = ref<number[]>([]); const selectedCourseIds = ref<(number | string)[]>([]);
// //
const filters = reactive({ const filters = reactive({
@ -401,7 +401,7 @@ const searchCourses = () => {
}, 500); }, 500);
}; };
const toggleCourseSelection = (id: number) => { const toggleCourseSelection = (id: number | string) => {
const index = selectedCourseIds.value.indexOf(id); const index = selectedCourseIds.value.indexOf(id);
if (index > -1) { if (index > -1) {
selectedCourseIds.value.splice(index, 1); selectedCourseIds.value.splice(index, 1);

View File

@ -330,7 +330,7 @@ const fetchFeedbacks = async () => {
teacherId: filters.teacherId, teacherId: filters.teacherId,
}); });
feedbacks.value = result.list; feedbacks.value = result.list;
pagination.total = result.total; pagination.total = Number(result.total);
} catch (error) { } catch (error) {
message.error('获取反馈列表失败'); message.error('获取反馈列表失败');
} finally { } finally {

View File

@ -449,7 +449,7 @@ const loadParents = async () => {
keyword: searchKeyword.value || undefined, keyword: searchKeyword.value || undefined,
}); });
parents.value = result.list; parents.value = result.list;
pagination.total = result.total; pagination.total = Number(result.total);
} catch (error) { } catch (error) {
console.error('Failed to load parents:', error); console.error('Failed to load parents:', error);
} finally { } finally {
@ -684,7 +684,7 @@ const loadStudentsForSelect = async () => {
classId: studentClassFilter.value || undefined, classId: studentClassFilter.value || undefined,
}); });
studentTableData.value = result.list; studentTableData.value = result.list;
studentPagination.total = result.total; studentPagination.total = Number(result.total);
} catch (error) { } catch (error) {
console.error('Failed to load students:', error); console.error('Failed to load students:', error);
studentTableData.value = []; studentTableData.value = [];

View File

@ -219,7 +219,7 @@ const loadLogs = async () => {
...filters, ...filters,
}); });
logs.value = res.list; logs.value = res.list;
pagination.total = res.total; pagination.total = Number(res.total);
} catch (error) { } catch (error) {
message.error('加载日志失败'); message.error('加载日志失败');
} finally { } finally {
@ -241,7 +241,7 @@ const loadModules = async () => {
const loadStats = async () => { const loadStats = async () => {
try { try {
const res = await getOperationLogStats(filters.startDate, filters.endDate); const res = await getOperationLogStats(filters.startDate, filters.endDate);
stats.total = res.total; stats.total = Number(res.total);
stats.modules = res.modules || []; stats.modules = res.modules || [];
} catch (error) { } catch (error) {
console.error('加载统计失败', error); console.error('加载统计失败', error);

View File

@ -444,7 +444,7 @@ const loadStudents = async () => {
keyword: searchKeyword.value || undefined, keyword: searchKeyword.value || undefined,
}); });
students.value = result.list; students.value = result.list;
pagination.total = result.total; pagination.total = Number(result.total);
} catch (error) { } catch (error) {
console.error('Failed to load students:', error); console.error('Failed to load students:', error);
} finally { } finally {

View File

@ -329,7 +329,7 @@ const loadTeachers = async () => {
keyword: searchKeyword.value || undefined, keyword: searchKeyword.value || undefined,
}); });
teachers.value = result.list; teachers.value = result.list;
pagination.total = result.total; pagination.total = Number(result.total);
} catch (error) { } catch (error) {
console.error('Failed to load teachers:', error); console.error('Failed to load teachers:', error);
} finally { } finally {

View File

@ -322,7 +322,7 @@ const loadCourses = async () => {
pictureUrl: item.coverImagePath ?? item.pictureUrl, pictureUrl: item.coverImagePath ?? item.pictureUrl,
}; };
}); });
pagination.total = data.total || 0; pagination.total = Number(data.total) || 0;
} catch (error: any) { } catch (error: any) {
message.error(error.message || '获取课程列表失败'); message.error(error.message || '获取课程列表失败');
} finally { } finally {

View File

@ -109,7 +109,7 @@ const loading = ref(false);
// //
const selectedSection = ref<'overview' | 'lesson'>('overview'); const selectedSection = ref<'overview' | 'lesson'>('overview');
const selectedLessonId = ref<number | null>(null); const selectedLessonId = ref<number | string | null>(null);
const selectedItem = ref<string>('basic'); const selectedItem = ref<string>('basic');
const selectedStep = ref<any>(null); const selectedStep = ref<any>(null);

View File

@ -88,7 +88,7 @@ import {
const props = defineProps<{ const props = defineProps<{
lesson: any; lesson: any;
courseId: number; courseId: number | string;
lessonType: string; lessonType: string;
index: number; index: number;
}>(); }>();

View File

@ -278,7 +278,7 @@ const props = defineProps<{
course: any; course: any;
lessons: any[]; lessons: any[];
selectedSection: 'overview' | 'lesson'; selectedSection: 'overview' | 'lesson';
selectedLessonId: number | null; selectedLessonId: number | string | null;
selectedItem: string; selectedItem: string;
}>(); }>();

View File

@ -117,7 +117,7 @@ const props = defineProps<{
const emit = defineEmits<{ const emit = defineEmits<{
'update:open': [value: boolean]; 'update:open': [value: boolean];
'confirm': [lessonIds: number[], mode: string]; 'confirm': [lessonIds: (number | string)[], mode: string];
}>(); }>();
const visible = computed({ const visible = computed({
@ -126,7 +126,7 @@ const visible = computed({
}); });
const selectionMode = ref<'all' | 'custom'>('all'); const selectionMode = ref<'all' | 'custom'>('all');
const selectedLessonIds = ref<number[]>([]); const selectedLessonIds = ref<(number | string)[]>([]);
// //
const introductionLesson = computed(() => const introductionLesson = computed(() =>

View File

@ -308,7 +308,7 @@ const fetchFeedbacks = async () => {
pageSize: pagination.pageSize, pageSize: pagination.pageSize,
}); });
feedbacks.value = result.items; feedbacks.value = result.items;
pagination.total = result.total; pagination.total = Number(result.total);
} catch (error) { } catch (error) {
message.error('获取反馈列表失败'); message.error('获取反馈列表失败');
} finally { } finally {

View File

@ -335,7 +335,7 @@ const loadRecords = async () => {
keyword: filters.keyword || undefined, keyword: filters.keyword || undefined,
}); });
records.value = res.list || []; records.value = res.list || [];
pagination.total = res.total || 0; pagination.total = Number(res.total) || 0;
} catch (error) { } catch (error) {
message.error('加载档案失败'); message.error('加载档案失败');
} finally { } finally {

View File

@ -11,7 +11,7 @@
import Step4IntroLessonAdmin from '@/components/course-edit/Step4IntroLesson.vue'; import Step4IntroLessonAdmin from '@/components/course-edit/Step4IntroLesson.vue';
defineProps<{ defineProps<{
schoolCourseId: number; schoolCourseId: number | string;
lessonData?: any; lessonData?: any;
}>(); }>();

View File

@ -12,7 +12,7 @@
import Step5CollectiveLessonAdmin from '@/components/course-edit/Step5CollectiveLesson.vue'; import Step5CollectiveLessonAdmin from '@/components/course-edit/Step5CollectiveLesson.vue';
defineProps<{ defineProps<{
schoolCourseId: number; schoolCourseId: number | string;
lessonData?: any; lessonData?: any;
}>(); }>();

View File

@ -12,7 +12,7 @@
import Step6DomainLessonsAdmin from '@/components/course-edit/Step6DomainLessons.vue'; import Step6DomainLessonsAdmin from '@/components/course-edit/Step6DomainLessons.vue';
defineProps<{ defineProps<{
schoolCourseId: number; schoolCourseId: number | string;
domainLessons?: { domainLessons?: {
LANGUAGE?: any; LANGUAGE?: any;
HEALTH?: any; HEALTH?: any;