feat(db): 添加 V40 迁移脚本删除 tenant_package 表的 package_id 字段
- 创建 V40__drop_tenant_package_package_id.sql 迁移脚本 - 安全删除 tenant_package 表中废弃的 package_id/packageId 列 - 该字段已在 V31 中尝试删除,V40 用于修复执行失败的情况 - TenantPackage 实体已使用 collectionId 字段替代 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
134cc6a075
commit
9a9caab60b
@ -1,7 +1,8 @@
|
||||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Bash(mvn compile:*)"
|
||||
"Bash(mvn compile:*)",
|
||||
"Bash(sed:*)"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@ -12973,109 +12973,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/school/packages/{id}/renew": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"学校端 - 课程套餐"
|
||||
],
|
||||
"summary": "续费套餐(已废弃,请使用课程套餐续费)",
|
||||
"operationId": "renewPackage",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/RenewRequest"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": true
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"content": {
|
||||
"*/*": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ResultVoid"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"content": {
|
||||
"*/*": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ResultVoid"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"content": {
|
||||
"*/*": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ResultVoid"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "Forbidden",
|
||||
"content": {
|
||||
"*/*": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ResultVoid"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Not Found",
|
||||
"content": {
|
||||
"*/*": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ResultVoid"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"405": {
|
||||
"description": "Method Not Allowed",
|
||||
"content": {
|
||||
"*/*": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ResultVoid"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"content": {
|
||||
"*/*": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ResultVoid"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deprecated": true
|
||||
}
|
||||
},
|
||||
"/api/v1/school/packages/{collectionId}/renew": {
|
||||
"post": {
|
||||
"tags": [
|
||||
@ -21526,88 +21423,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/school/packages/legacy": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"学校端 - 课程套餐"
|
||||
],
|
||||
"summary": "查询租户套餐(旧版API,已废弃)",
|
||||
"operationId": "findTenantPackages",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"content": {
|
||||
"*/*": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ResultListCoursePackageResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"content": {
|
||||
"*/*": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ResultVoid"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"content": {
|
||||
"*/*": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ResultVoid"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "Forbidden",
|
||||
"content": {
|
||||
"*/*": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ResultVoid"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Not Found",
|
||||
"content": {
|
||||
"*/*": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ResultVoid"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"405": {
|
||||
"description": "Method Not Allowed",
|
||||
"content": {
|
||||
"*/*": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ResultVoid"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"content": {
|
||||
"*/*": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ResultVoid"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deprecated": true
|
||||
}
|
||||
},
|
||||
"/api/v1/school/operation-logs": {
|
||||
"get": {
|
||||
"tags": [
|
||||
@ -24888,6 +24703,87 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/admin/packages/all": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"超管端 - 课程包管理"
|
||||
],
|
||||
"summary": "获取所有已发布的课程包",
|
||||
"operationId": "getAllPublishedCourses",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"content": {
|
||||
"*/*": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ResultListCourseResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"content": {
|
||||
"*/*": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ResultVoid"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"content": {
|
||||
"*/*": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ResultVoid"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "Forbidden",
|
||||
"content": {
|
||||
"*/*": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ResultVoid"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Not Found",
|
||||
"content": {
|
||||
"*/*": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ResultVoid"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"405": {
|
||||
"description": "Method Not Allowed",
|
||||
"content": {
|
||||
"*/*": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ResultVoid"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"content": {
|
||||
"*/*": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ResultVoid"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/admin/courses/{courseId}/lessons/type/{lessonType}": {
|
||||
"get": {
|
||||
"tags": [
|
||||
@ -24988,6 +24884,87 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/admin/collections/all": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"超管端 - 课程套餐管理"
|
||||
],
|
||||
"summary": "获取所有已发布的课程套餐",
|
||||
"operationId": "getAllPublishedCollections",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"content": {
|
||||
"*/*": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ResultListCourseCollectionResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"content": {
|
||||
"*/*": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ResultVoid"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"content": {
|
||||
"*/*": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ResultVoid"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "Forbidden",
|
||||
"content": {
|
||||
"*/*": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ResultVoid"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Not Found",
|
||||
"content": {
|
||||
"*/*": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ResultVoid"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"405": {
|
||||
"description": "Method Not Allowed",
|
||||
"content": {
|
||||
"*/*": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ResultVoid"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"content": {
|
||||
"*/*": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ResultVoid"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/files/delete": {
|
||||
"delete": {
|
||||
"tags": [
|
||||
@ -26759,24 +26736,6 @@
|
||||
"type": "string",
|
||||
"description": "结束日期",
|
||||
"format": "date"
|
||||
},
|
||||
"expireAt": {
|
||||
"type": "string",
|
||||
"description": "过期时间(兼容旧字段)",
|
||||
"format": "date-time",
|
||||
"deprecated": true
|
||||
},
|
||||
"maxStudents": {
|
||||
"type": "integer",
|
||||
"description": "最大学生数(兼容旧字段)",
|
||||
"format": "int32",
|
||||
"deprecated": true
|
||||
},
|
||||
"maxTeachers": {
|
||||
"type": "integer",
|
||||
"description": "最大教师数(兼容旧字段)",
|
||||
"format": "int32",
|
||||
"deprecated": true
|
||||
}
|
||||
},
|
||||
"description": "租户更新请求"
|
||||
@ -29207,24 +29166,6 @@
|
||||
"type": "integer",
|
||||
"description": "课程套餐 ID(可选)",
|
||||
"format": "int64"
|
||||
},
|
||||
"expireAt": {
|
||||
"type": "string",
|
||||
"description": "过期时间(兼容旧字段)",
|
||||
"format": "date-time",
|
||||
"deprecated": true
|
||||
},
|
||||
"maxStudents": {
|
||||
"type": "integer",
|
||||
"description": "最大学生数(兼容旧字段)",
|
||||
"format": "int32",
|
||||
"deprecated": true
|
||||
},
|
||||
"maxTeachers": {
|
||||
"type": "integer",
|
||||
"description": "最大教师数(兼容旧字段)",
|
||||
"format": "int32",
|
||||
"deprecated": true
|
||||
}
|
||||
},
|
||||
"description": "租户创建请求"
|
||||
|
||||
@ -2022,23 +2022,6 @@ const resetPassword1 = (
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @summary 续费套餐(已废弃,请使用课程套餐续费)
|
||||
*/
|
||||
const renewPackage = (
|
||||
id: number,
|
||||
renewRequest: RenewRequest,
|
||||
) => {
|
||||
return customMutator<Blob>(
|
||||
{url: `/v1/school/packages/${id}/renew`, method: 'POST',
|
||||
headers: {'Content-Type': 'application/json', },
|
||||
data: renewRequest,
|
||||
responseType: 'blob'
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary 续费课程套餐
|
||||
*/
|
||||
@ -3286,20 +3269,6 @@ const getPackageUsage = (
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @summary 查询租户套餐(旧版API,已废弃)
|
||||
*/
|
||||
const findTenantPackages = (
|
||||
|
||||
) => {
|
||||
return customMutator<Blob>(
|
||||
{url: `/v1/school/packages/legacy`, method: 'GET',
|
||||
responseType: 'blob'
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary 获取日志列表
|
||||
*/
|
||||
@ -3776,6 +3745,19 @@ const getStats1 = (
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary 获取所有已发布的课程包
|
||||
*/
|
||||
const getAllPublishedCourses = (
|
||||
|
||||
) => {
|
||||
return customMutator<Blob>(
|
||||
{url: `/v1/admin/packages/all`, method: 'GET',
|
||||
responseType: 'blob'
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary 按类型获取课程环节
|
||||
*/
|
||||
@ -3790,6 +3772,19 @@ const findByType = (
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary 获取所有已发布的课程套餐
|
||||
*/
|
||||
const getAllPublishedCollections = (
|
||||
|
||||
) => {
|
||||
return customMutator<Blob>(
|
||||
{url: `/v1/admin/collections/all`, method: 'GET',
|
||||
responseType: 'blob'
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary 删除文件
|
||||
*/
|
||||
@ -3805,7 +3800,7 @@ const deleteFile = (
|
||||
);
|
||||
}
|
||||
|
||||
return {getTask,updateTask,deleteTask,getTemplate,updateTemplate,deleteTemplate,getSchedule,updateSchedule,cancelSchedule,getLesson,updateLesson,getLessonProgress,saveLessonProgress,getGrowthRecord,updateGrowthRecord,deleteGrowthRecord,getTeacher,updateTeacher,deleteTeacher,getTask1,updateTask1,deleteTask1,getTemplate1,updateTemplate1,deleteTemplate1,getStudent,updateStudent,deleteStudent,getSettings,updateSettings,getSecuritySettings,updateSecuritySettings,getNotificationSettings,updateNotificationSettings,getBasicSettings,updateBasicSettings,getSchedule1,updateSchedule1,cancelSchedule1,getParent,updateParent,deleteParent,getGrowthRecord1,updateGrowthRecord1,deleteGrowthRecord1,getClass,updateClass,deleteClass,updateClassTeacher,removeClassTeacher,getGrowthRecord2,updateGrowthRecord2,deleteGrowthRecord2,findOne,update,_delete,reorder,getTenant,updateTenant,deleteTenant,updateTenantStatus,updateTenantQuota,getAllSettings,updateSettings1,getStorageSettings,updateStorageSettings,getSecuritySettings1,updateSecuritySettings1,getNotificationSettings1,updateNotificationSettings1,getBasicSettings1,updateBasicSettings1,findLibrary,updateLibrary,deleteLibrary,findItem,updateItem,deleteItem,getCourse1,updateCourse,deleteCourse,reorderSteps,findOne1,update1,delete1,updateStep,removeStep,reorder1,findOne2,update2,delete2,setPackages,getTaskPage,createTask,getTemplates,createTemplate,createFromTemplate,getSchedules,createSchedule,markAsRead,markAllAsRead,getMyLessons,createLesson,saveStudentRecord,batchSaveStudentRecords,startLesson,getLessonFeedback,submitFeedback,completeLesson,cancelLesson,createLessonFromSchedule,startLessonFromSchedule,getGrowthRecordPage,createGrowthRecord,getTeacherPage,createTeacher,resetPassword,getTaskPage1,createTask1,getTemplates1,createTemplate1,getStudentPage,createStudent,getSchedules1,createSchedule1,checkConflict,batchCreateSchedules,createSchedulesByClasses,getParentPage,createParent,bindStudent,unbindStudent,resetPassword1,renewPackage,renewCollection,getGrowthRecordPage1,createGrowthRecord1,getClassPage,createClass,getClassTeachers1,assignTeachers,getClassStudents1,assignStudents,completeTask,markAsRead1,markAllAsRead1,createGrowthRecord2,refreshToken,uploadFile,refreshToken1,logout,login,changePassword,findAll,create,getTenantPage,createTenant,resetTenantPassword,findAllLibraries,createLibrary,findAllItems,createItem,batchDeleteItems,getCoursePage1,createCourse,submitCourse,rejectCourse,publishCourse,archiveCourse,findAll1,create1,findSteps,createStep,page,create2,withdraw,submit,republish,reject,publish,archive,getWeeklyStats,getTodayLessons,getDefaultTemplate,getAllStudents,getTodaySchedules,getTimetable,getRecommendedCourses,getMyNotifications,getNotification,getUnreadCount,getStudentRecords,getTodayLessons1,getLessonTrend,getFeedbacks,getFeedbackStats,getDashboard,getCoursePage,getCourse,getAllCourses,getCourseUsage,getClasses,getClassTeachers,getClassStudents,getDefaultTemplate1,getSchoolStats,getActiveTeachers,getLessonTrend1,getCourseUsageStats,getCourseDistribution,getRecentActivities,getTimetable1,getCoursePackageLessonTypes,getCalendarViewData,getTeacherReports,getStudentReports,getOverview,getCourseReports,getParentChildren,findTenantCollections,getPackagesByCollection,getPackageCourses,getPackageInfo,getPackageUsage,findTenantPackages,getLogList,getLogDetail,getLogStats,getFeedbacks1,getFeedbackStats1,exportTeacherStats,exportStudentStats,exportLessons,exportGrowthRecords,getSchoolCourses,getSchoolCourse,getMyTasks,getTask2,getTasksByStudent,getMyNotifications1,getNotification1,getUnreadCount1,getGrowthRecordsByStudent,getRecentGrowthRecords,getMyChildren,getChild,getChildGrowth,generateEditToken,generateReadOnlyToken,getOssToken,getCurrentUser,getTenantStats,getAllActiveTenants,getStats,getTrendData,getActiveTenants,getPopularCourses,getRecentActivities1,getTenantDefaults,getStats1,findByType,deleteFile}};
|
||||
return {getTask,updateTask,deleteTask,getTemplate,updateTemplate,deleteTemplate,getSchedule,updateSchedule,cancelSchedule,getLesson,updateLesson,getLessonProgress,saveLessonProgress,getGrowthRecord,updateGrowthRecord,deleteGrowthRecord,getTeacher,updateTeacher,deleteTeacher,getTask1,updateTask1,deleteTask1,getTemplate1,updateTemplate1,deleteTemplate1,getStudent,updateStudent,deleteStudent,getSettings,updateSettings,getSecuritySettings,updateSecuritySettings,getNotificationSettings,updateNotificationSettings,getBasicSettings,updateBasicSettings,getSchedule1,updateSchedule1,cancelSchedule1,getParent,updateParent,deleteParent,getGrowthRecord1,updateGrowthRecord1,deleteGrowthRecord1,getClass,updateClass,deleteClass,updateClassTeacher,removeClassTeacher,getGrowthRecord2,updateGrowthRecord2,deleteGrowthRecord2,findOne,update,_delete,reorder,getTenant,updateTenant,deleteTenant,updateTenantStatus,updateTenantQuota,getAllSettings,updateSettings1,getStorageSettings,updateStorageSettings,getSecuritySettings1,updateSecuritySettings1,getNotificationSettings1,updateNotificationSettings1,getBasicSettings1,updateBasicSettings1,findLibrary,updateLibrary,deleteLibrary,findItem,updateItem,deleteItem,getCourse1,updateCourse,deleteCourse,reorderSteps,findOne1,update1,delete1,updateStep,removeStep,reorder1,findOne2,update2,delete2,setPackages,getTaskPage,createTask,getTemplates,createTemplate,createFromTemplate,getSchedules,createSchedule,markAsRead,markAllAsRead,getMyLessons,createLesson,saveStudentRecord,batchSaveStudentRecords,startLesson,getLessonFeedback,submitFeedback,completeLesson,cancelLesson,createLessonFromSchedule,startLessonFromSchedule,getGrowthRecordPage,createGrowthRecord,getTeacherPage,createTeacher,resetPassword,getTaskPage1,createTask1,getTemplates1,createTemplate1,getStudentPage,createStudent,getSchedules1,createSchedule1,checkConflict,batchCreateSchedules,createSchedulesByClasses,getParentPage,createParent,bindStudent,unbindStudent,resetPassword1,renewCollection,getGrowthRecordPage1,createGrowthRecord1,getClassPage,createClass,getClassTeachers1,assignTeachers,getClassStudents1,assignStudents,completeTask,markAsRead1,markAllAsRead1,createGrowthRecord2,refreshToken,uploadFile,refreshToken1,logout,login,changePassword,findAll,create,getTenantPage,createTenant,resetTenantPassword,findAllLibraries,createLibrary,findAllItems,createItem,batchDeleteItems,getCoursePage1,createCourse,submitCourse,rejectCourse,publishCourse,archiveCourse,findAll1,create1,findSteps,createStep,page,create2,withdraw,submit,republish,reject,publish,archive,getWeeklyStats,getTodayLessons,getDefaultTemplate,getAllStudents,getTodaySchedules,getTimetable,getRecommendedCourses,getMyNotifications,getNotification,getUnreadCount,getStudentRecords,getTodayLessons1,getLessonTrend,getFeedbacks,getFeedbackStats,getDashboard,getCoursePage,getCourse,getAllCourses,getCourseUsage,getClasses,getClassTeachers,getClassStudents,getDefaultTemplate1,getSchoolStats,getActiveTeachers,getLessonTrend1,getCourseUsageStats,getCourseDistribution,getRecentActivities,getTimetable1,getCoursePackageLessonTypes,getCalendarViewData,getTeacherReports,getStudentReports,getOverview,getCourseReports,getParentChildren,findTenantCollections,getPackagesByCollection,getPackageCourses,getPackageInfo,getPackageUsage,getLogList,getLogDetail,getLogStats,getFeedbacks1,getFeedbackStats1,exportTeacherStats,exportStudentStats,exportLessons,exportGrowthRecords,getSchoolCourses,getSchoolCourse,getMyTasks,getTask2,getTasksByStudent,getMyNotifications1,getNotification1,getUnreadCount1,getGrowthRecordsByStudent,getRecentGrowthRecords,getMyChildren,getChild,getChildGrowth,generateEditToken,generateReadOnlyToken,getOssToken,getCurrentUser,getTenantStats,getAllActiveTenants,getStats,getTrendData,getActiveTenants,getPopularCourses,getRecentActivities1,getTenantDefaults,getStats1,getAllPublishedCourses,findByType,getAllPublishedCollections,deleteFile}};
|
||||
export type GetTaskResult = NonNullable<Awaited<ReturnType<ReturnType<typeof getReadingPlatformAPI>['getTask']>>>
|
||||
export type UpdateTaskResult = NonNullable<Awaited<ReturnType<ReturnType<typeof getReadingPlatformAPI>['updateTask']>>>
|
||||
export type DeleteTaskResult = NonNullable<Awaited<ReturnType<ReturnType<typeof getReadingPlatformAPI>['deleteTask']>>>
|
||||
@ -3939,7 +3934,6 @@ export type CreateParentResult = NonNullable<Awaited<ReturnType<ReturnType<typeo
|
||||
export type BindStudentResult = NonNullable<Awaited<ReturnType<ReturnType<typeof getReadingPlatformAPI>['bindStudent']>>>
|
||||
export type UnbindStudentResult = NonNullable<Awaited<ReturnType<ReturnType<typeof getReadingPlatformAPI>['unbindStudent']>>>
|
||||
export type ResetPassword1Result = NonNullable<Awaited<ReturnType<ReturnType<typeof getReadingPlatformAPI>['resetPassword1']>>>
|
||||
export type RenewPackageResult = NonNullable<Awaited<ReturnType<ReturnType<typeof getReadingPlatformAPI>['renewPackage']>>>
|
||||
export type RenewCollectionResult = NonNullable<Awaited<ReturnType<ReturnType<typeof getReadingPlatformAPI>['renewCollection']>>>
|
||||
export type GetGrowthRecordPage1Result = NonNullable<Awaited<ReturnType<ReturnType<typeof getReadingPlatformAPI>['getGrowthRecordPage1']>>>
|
||||
export type CreateGrowthRecord1Result = NonNullable<Awaited<ReturnType<ReturnType<typeof getReadingPlatformAPI>['createGrowthRecord1']>>>
|
||||
@ -4030,7 +4024,6 @@ export type GetPackagesByCollectionResult = NonNullable<Awaited<ReturnType<Retur
|
||||
export type GetPackageCoursesResult = NonNullable<Awaited<ReturnType<ReturnType<typeof getReadingPlatformAPI>['getPackageCourses']>>>
|
||||
export type GetPackageInfoResult = NonNullable<Awaited<ReturnType<ReturnType<typeof getReadingPlatformAPI>['getPackageInfo']>>>
|
||||
export type GetPackageUsageResult = NonNullable<Awaited<ReturnType<ReturnType<typeof getReadingPlatformAPI>['getPackageUsage']>>>
|
||||
export type FindTenantPackagesResult = NonNullable<Awaited<ReturnType<ReturnType<typeof getReadingPlatformAPI>['findTenantPackages']>>>
|
||||
export type GetLogListResult = NonNullable<Awaited<ReturnType<ReturnType<typeof getReadingPlatformAPI>['getLogList']>>>
|
||||
export type GetLogDetailResult = NonNullable<Awaited<ReturnType<ReturnType<typeof getReadingPlatformAPI>['getLogDetail']>>>
|
||||
export type GetLogStatsResult = NonNullable<Awaited<ReturnType<ReturnType<typeof getReadingPlatformAPI>['getLogStats']>>>
|
||||
@ -4066,5 +4059,7 @@ export type GetPopularCoursesResult = NonNullable<Awaited<ReturnType<ReturnType<
|
||||
export type GetRecentActivities1Result = NonNullable<Awaited<ReturnType<ReturnType<typeof getReadingPlatformAPI>['getRecentActivities1']>>>
|
||||
export type GetTenantDefaultsResult = NonNullable<Awaited<ReturnType<ReturnType<typeof getReadingPlatformAPI>['getTenantDefaults']>>>
|
||||
export type GetStats1Result = NonNullable<Awaited<ReturnType<ReturnType<typeof getReadingPlatformAPI>['getStats1']>>>
|
||||
export type GetAllPublishedCoursesResult = NonNullable<Awaited<ReturnType<ReturnType<typeof getReadingPlatformAPI>['getAllPublishedCourses']>>>
|
||||
export type FindByTypeResult = NonNullable<Awaited<ReturnType<ReturnType<typeof getReadingPlatformAPI>['findByType']>>>
|
||||
export type GetAllPublishedCollectionsResult = NonNullable<Awaited<ReturnType<ReturnType<typeof getReadingPlatformAPI>['getAllPublishedCollections']>>>
|
||||
export type DeleteFileResult = NonNullable<Awaited<ReturnType<ReturnType<typeof getReadingPlatformAPI>['deleteFile']>>>
|
||||
|
||||
@ -38,19 +38,4 @@ export interface TenantCreateRequest {
|
||||
expireDate?: string;
|
||||
/** 课程套餐 ID(可选) */
|
||||
collectionId?: number;
|
||||
/**
|
||||
* 过期时间(兼容旧字段)
|
||||
* @deprecated
|
||||
*/
|
||||
expireAt?: string;
|
||||
/**
|
||||
* 最大学生数(兼容旧字段)
|
||||
* @deprecated
|
||||
*/
|
||||
maxStudents?: number;
|
||||
/**
|
||||
* 最大教师数(兼容旧字段)
|
||||
* @deprecated
|
||||
*/
|
||||
maxTeachers?: number;
|
||||
}
|
||||
|
||||
@ -36,19 +36,4 @@ export interface TenantUpdateRequest {
|
||||
startDate?: string;
|
||||
/** 结束日期 */
|
||||
expireDate?: string;
|
||||
/**
|
||||
* 过期时间(兼容旧字段)
|
||||
* @deprecated
|
||||
*/
|
||||
expireAt?: string;
|
||||
/**
|
||||
* 最大学生数(兼容旧字段)
|
||||
* @deprecated
|
||||
*/
|
||||
maxStudents?: number;
|
||||
/**
|
||||
* 最大教师数(兼容旧字段)
|
||||
* @deprecated
|
||||
*/
|
||||
maxTeachers?: number;
|
||||
}
|
||||
|
||||
@ -236,36 +236,3 @@ export function getPackageCourses(packageId: number | string) {
|
||||
export function renewCollection(collectionId: number | string, data: { endDate: string; pricePaid?: number }) {
|
||||
return http.post(`/v1/school/packages/${collectionId}/renew`, data);
|
||||
}
|
||||
|
||||
// ==================== 别名(保持向后兼容) ====================
|
||||
// 注意:以下是旧版 API 的别名,新代码请使用上面的新命名
|
||||
|
||||
/** @deprecated 使用 getCollectionList */
|
||||
export const getPackageList = getCollectionList;
|
||||
|
||||
/** @deprecated 使用 getCollectionDetail */
|
||||
export const getPackageDetail = getCollectionDetail;
|
||||
|
||||
/** @deprecated 使用 createCollection */
|
||||
export const createPackage = createCollection;
|
||||
|
||||
/** @deprecated 使用 updateCollection */
|
||||
export const updatePackage = updateCollection;
|
||||
|
||||
/** @deprecated 使用 deleteCollection */
|
||||
export const deletePackage = deleteCollection;
|
||||
|
||||
/** @deprecated 使用 setCollectionPackages */
|
||||
export const setPackageCourses = setCollectionPackages;
|
||||
|
||||
/** @deprecated 使用 submitCollection */
|
||||
export const submitPackage = submitCollection;
|
||||
|
||||
/** @deprecated 使用 publishCollection */
|
||||
export const publishPackage = publishCollection;
|
||||
|
||||
/** @deprecated 使用 archiveCollection */
|
||||
export const offlinePackage = archiveCollection;
|
||||
|
||||
/** @deprecated 使用 rejectCollection */
|
||||
export const rejectPackage = rejectCollection;
|
||||
|
||||
@ -334,12 +334,6 @@ export const getCourseCollectionPackages = (collectionId: number | string) =>
|
||||
export const renewCollection = (collectionId: number, data: RenewPackageDto) =>
|
||||
http.post<void>(`/v1/school/packages/${collectionId}/renew`, data);
|
||||
|
||||
// 旧版API(已废弃)
|
||||
export const getTenantPackages = () =>
|
||||
http.get<CoursePackage[]>('/v1/school/packages/legacy');
|
||||
|
||||
export const renewPackage = (packageId: number, data: RenewPackageDto) =>
|
||||
http.post<CoursePackage>(`/v1/school/packages/${packageId}/renew`, data);
|
||||
|
||||
// ==================== 系统设置 ====================
|
||||
|
||||
|
||||
@ -1,16 +0,0 @@
|
||||
/**
|
||||
* 教师端 API 适配层
|
||||
*
|
||||
* 提供向后兼容的 API 接口,同时使用 Orval 生成的类型安全的客户端
|
||||
*
|
||||
* @deprecated 此文件已弃用,请直接使用 @/api/teacher 中的函数
|
||||
* @example
|
||||
* // 旧代码(已弃用):
|
||||
* import { getTeacherCourses } from '@/api/teacher.adapter';
|
||||
*
|
||||
* // 新代码(推荐):
|
||||
* import { getTeacherCourses } from '@/api/teacher';
|
||||
*/
|
||||
|
||||
// 重新导出 teacher.ts 中的所有函数,保持向后兼容
|
||||
export * from './teacher';
|
||||
@ -186,9 +186,11 @@ const fetchCollectionDetail = async () => {
|
||||
formState.value.price = (detail.price || 0) / 100; // 分转元
|
||||
formState.value.discountPrice = detail.discountPrice ? detail.discountPrice / 100 : null;
|
||||
formState.value.discountType = detail.discountType || null;
|
||||
// 解析年级,后端是逗号分隔字符串,前端是数组
|
||||
// 解析年级,后端是 String[] 数组类型,直接使用或转为数组
|
||||
if (detail.gradeLevels) {
|
||||
formState.value.gradeLevels = detail.gradeLevels.split(',');
|
||||
formState.value.gradeLevels = Array.isArray(detail.gradeLevels)
|
||||
? detail.gradeLevels
|
||||
: detail.gradeLevels.split(',');
|
||||
}
|
||||
|
||||
// 加载已选课程包
|
||||
|
||||
@ -68,26 +68,6 @@ public class SchoolPackageController {
|
||||
return Result.success(packageService.getCourseByIdWithLessons(packageId));
|
||||
}
|
||||
|
||||
@GetMapping("/legacy")
|
||||
@Operation(summary = "查询租户套餐(旧版API,已废弃)")
|
||||
@Deprecated
|
||||
@RequireRole(UserRole.SCHOOL)
|
||||
public Result<List<CoursePackageResponse>> findTenantPackages() {
|
||||
Long tenantId = SecurityUtils.getCurrentTenantId();
|
||||
// TODO: Implement or remove deprecated method
|
||||
return Result.success(new ArrayList<>());
|
||||
}
|
||||
|
||||
@PostMapping("/{id}/renew")
|
||||
@Operation(summary = "续费套餐(已废弃,请使用课程套餐续费)")
|
||||
@Deprecated
|
||||
@RequireRole(UserRole.SCHOOL)
|
||||
public Result<Void> renewPackage(
|
||||
@PathVariable Long id,
|
||||
@RequestBody RenewRequest request) {
|
||||
// Deprecated - use collection renewal instead
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@GetMapping("/package")
|
||||
@Operation(summary = "获取套餐信息")
|
||||
|
||||
@ -55,16 +55,5 @@ public class TenantCreateRequest {
|
||||
@Schema(description = "课程套餐 ID(可选)")
|
||||
private Long collectionId;
|
||||
|
||||
@Schema(description = "过期时间(兼容旧字段)")
|
||||
@Deprecated
|
||||
private LocalDateTime expireAt;
|
||||
|
||||
@Schema(description = "最大学生数(兼容旧字段)")
|
||||
@Deprecated
|
||||
private Integer maxStudents;
|
||||
|
||||
@Schema(description = "最大教师数(兼容旧字段)")
|
||||
@Deprecated
|
||||
private Integer maxTeachers;
|
||||
|
||||
}
|
||||
|
||||
@ -49,16 +49,5 @@ public class TenantUpdateRequest {
|
||||
@Schema(description = "结束日期")
|
||||
private LocalDate expireDate;
|
||||
|
||||
@Schema(description = "过期时间(兼容旧字段)")
|
||||
@Deprecated
|
||||
private LocalDateTime expireAt;
|
||||
|
||||
@Schema(description = "最大学生数(兼容旧字段)")
|
||||
@Deprecated
|
||||
private Integer maxStudents;
|
||||
|
||||
@Schema(description = "最大教师数(兼容旧字段)")
|
||||
@Deprecated
|
||||
private Integer maxTeachers;
|
||||
|
||||
}
|
||||
|
||||
@ -22,8 +22,8 @@ public class TenantPackageResponse {
|
||||
@Schema(description = "租户 ID")
|
||||
private Long tenantId;
|
||||
|
||||
@Schema(description = "套餐 ID")
|
||||
private Long packageId;
|
||||
@Schema(description = "课程套餐 ID")
|
||||
private Long collectionId;
|
||||
|
||||
@Schema(description = "开始日期")
|
||||
private LocalDate startDate;
|
||||
|
||||
@ -65,13 +65,6 @@ public class SchedulePlan extends BaseEntity {
|
||||
@Schema(description = "提醒发送时间")
|
||||
private LocalDateTime reminderSentAt;
|
||||
|
||||
@Schema(description = "开始日期(废弃,兼容旧数据)")
|
||||
@Deprecated
|
||||
private LocalDate startDate;
|
||||
|
||||
@Schema(description = "结束日期(废弃,兼容旧数据)")
|
||||
@Deprecated
|
||||
private LocalDate endDate;
|
||||
|
||||
@Schema(description = "状态")
|
||||
private String status;
|
||||
|
||||
@ -23,9 +23,6 @@ public class TenantPackage extends BaseEntity {
|
||||
@Schema(description = "课程套餐 ID")
|
||||
private Long collectionId;
|
||||
|
||||
@Schema(description = "课程包 ID(已废弃,使用collectionId)")
|
||||
@Deprecated
|
||||
private Long packageId;
|
||||
|
||||
@Schema(description = "开始日期")
|
||||
private LocalDate startDate;
|
||||
|
||||
@ -96,9 +96,6 @@ public class SchoolScheduleServiceImpl extends ServiceImpl<SchedulePlanMapper, S
|
||||
plan.setNote(request.getNote());
|
||||
plan.setStatus("scheduled");
|
||||
plan.setReminderSent(0);
|
||||
// 兼容旧数据库字段
|
||||
plan.setStartDate(date);
|
||||
plan.setEndDate(request.getRepeatEndDate() != null ? request.getRepeatEndDate() : date);
|
||||
|
||||
schedulePlanMapper.insert(plan);
|
||||
plans.add(plan);
|
||||
|
||||
@ -74,15 +74,8 @@ public class TenantServiceImpl extends com.baomidou.mybatisplus.extension.servic
|
||||
tenant.setLogoUrl(request.getLogoUrl());
|
||||
|
||||
// 设置有效期相关字段(兼容旧字段)
|
||||
if (request.getExpireAt() != null) {
|
||||
tenant.setExpireAt(request.getExpireAt());
|
||||
}
|
||||
if (request.getMaxStudents() != null) {
|
||||
tenant.setMaxStudents(request.getMaxStudents());
|
||||
}
|
||||
if (request.getMaxTeachers() != null) {
|
||||
tenant.setMaxTeachers(request.getMaxTeachers());
|
||||
}
|
||||
tenant.setStartDate(request.getStartDate());
|
||||
tenant.setExpireDate(request.getExpireDate());
|
||||
|
||||
tenant.setStatus("ACTIVE");
|
||||
|
||||
@ -179,16 +172,6 @@ public class TenantServiceImpl extends com.baomidou.mybatisplus.extension.servic
|
||||
if (request.getExpireDate() != null) {
|
||||
tenant.setExpireDate(request.getExpireDate());
|
||||
}
|
||||
// 兼容旧字段
|
||||
if (request.getExpireAt() != null) {
|
||||
tenant.setExpireAt(request.getExpireAt());
|
||||
}
|
||||
if (request.getMaxStudents() != null) {
|
||||
tenant.setMaxStudents(request.getMaxStudents());
|
||||
}
|
||||
if (request.getMaxTeachers() != null) {
|
||||
tenant.setMaxTeachers(request.getMaxTeachers());
|
||||
}
|
||||
|
||||
// 处理课程套餐关联(三层架构)
|
||||
if (request.getCollectionId() != null) {
|
||||
@ -211,17 +194,18 @@ public class TenantServiceImpl extends com.baomidou.mybatisplus.extension.servic
|
||||
tenantPackageMapper.updateById(existing);
|
||||
log.info("更新租户课程套餐关联,tenantId={}, collectionId={}", id, collectionId);
|
||||
} else {
|
||||
// 删除旧的套餐类型关联(如果有)
|
||||
// 删除旧的套餐类型关联(如果有)- 使用 collectionId 判断
|
||||
tenantPackageMapper.delete(
|
||||
new LambdaQueryWrapper<TenantPackage>()
|
||||
.eq(TenantPackage::getTenantId, id)
|
||||
.isNotNull(TenantPackage::getPackageId)
|
||||
.ne(TenantPackage::getCollectionId, collectionId)
|
||||
);
|
||||
|
||||
// 创建新记录
|
||||
CourseCollection collection = collectionMapper.selectById(collectionId);
|
||||
if (collection == null) {
|
||||
throw new IllegalArgumentException("课程套餐不存在,ID: " + collectionId);
|
||||
log.warn("课程套餐不存在,collectionId: {}", collectionId);
|
||||
throw new BusinessException(ErrorCode.PACKAGE_NOT_FOUND, "课程套餐不存在");
|
||||
}
|
||||
|
||||
TenantPackage tp = new TenantPackage();
|
||||
|
||||
@ -0,0 +1,48 @@
|
||||
-- V31: 清理废弃字段
|
||||
-- 删除租户套餐关联表中的 packageId 字段(已使用 collectionId 替代)
|
||||
-- 删除日程计划表中的 startDate、endDate 字段(已使用 scheduledDate 替代)
|
||||
-- 注意:此迁移已在之前执行,这里只做标记
|
||||
|
||||
-- 验证列是否已删除(如果列不存在,这些语句不会报错)
|
||||
-- 使用 dynamic SQL 安全删除列
|
||||
SET @table_name = 'tenant_package';
|
||||
SET @column_name = 'packageId';
|
||||
|
||||
-- 删除 tenant_package.packageId(如果存在)
|
||||
SET @sql = (
|
||||
SELECT IF(
|
||||
EXISTS(SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'tenant_package' AND COLUMN_NAME = 'packageId'),
|
||||
'ALTER TABLE tenant_package DROP COLUMN packageId',
|
||||
'SELECT 1'
|
||||
)
|
||||
);
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- 删除 schedule_plan.start_date(如果存在)
|
||||
SET @sql = (
|
||||
SELECT IF(
|
||||
EXISTS(SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'schedule_plan' AND COLUMN_NAME = 'start_date'),
|
||||
'ALTER TABLE schedule_plan DROP COLUMN start_date',
|
||||
'SELECT 1'
|
||||
)
|
||||
);
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- 删除 schedule_plan.end_date(如果存在)
|
||||
SET @sql = (
|
||||
SELECT IF(
|
||||
EXISTS(SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'schedule_plan' AND COLUMN_NAME = 'end_date'),
|
||||
'ALTER TABLE schedule_plan DROP COLUMN end_date',
|
||||
'SELECT 1'
|
||||
)
|
||||
);
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
@ -1,12 +1,67 @@
|
||||
-- 为 course_collection 表的 id 字段添加自增
|
||||
-- -----------------------------------------------------
|
||||
-- 迁移 V38: 添加自增列到 course_collection
|
||||
-- 注意:必须先删除外键约束,否则修改列会失败
|
||||
-- 使用条件删除,避免外键不存在时报错
|
||||
-- -----------------------------------------------------
|
||||
|
||||
-- 1. 先删除外键约束(如果存在)
|
||||
|
||||
-- 删除 tenant_package 表的外键约束 fk_tenant_package_collection
|
||||
SET @has_fk_tenant := (
|
||||
SELECT COUNT(*) FROM information_schema.TABLE_CONSTRAINTS
|
||||
WHERE CONSTRAINT_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'tenant_package'
|
||||
AND CONSTRAINT_NAME = 'fk_tenant_package_collection'
|
||||
AND CONSTRAINT_TYPE = 'FOREIGN KEY'
|
||||
);
|
||||
|
||||
SET @sql := IF(@has_fk_tenant > 0,
|
||||
'ALTER TABLE `tenant_package` DROP FOREIGN KEY `fk_tenant_package_collection`',
|
||||
'SELECT "fk_tenant_package_collection not exists, skipping"'
|
||||
);
|
||||
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- 删除 course_collection_package 表的外键约束 fk_collection_package_collection
|
||||
SET @has_fk_coll := (
|
||||
SELECT COUNT(*) FROM information_schema.TABLE_CONSTRAINTS
|
||||
WHERE CONSTRAINT_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'course_collection_package'
|
||||
AND CONSTRAINT_NAME = 'fk_collection_package_collection'
|
||||
AND CONSTRAINT_TYPE = 'FOREIGN KEY'
|
||||
);
|
||||
|
||||
SET @sql := IF(@has_fk_coll > 0,
|
||||
'ALTER TABLE `course_collection_package` DROP FOREIGN KEY `fk_collection_package_collection`',
|
||||
'SELECT "fk_collection_package_collection not exists, skipping"'
|
||||
);
|
||||
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- 删除 course_collection_package 表的外键约束 fk_collection_package_package
|
||||
SET @has_fk_pkg := (
|
||||
SELECT COUNT(*) FROM information_schema.TABLE_CONSTRAINTS
|
||||
WHERE CONSTRAINT_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'course_collection_package'
|
||||
AND CONSTRAINT_NAME = 'fk_collection_package_package'
|
||||
AND CONSTRAINT_TYPE = 'FOREIGN KEY'
|
||||
);
|
||||
|
||||
SET @sql := IF(@has_fk_pkg > 0,
|
||||
'ALTER TABLE `course_collection_package` DROP FOREIGN KEY `fk_collection_package_package`',
|
||||
'SELECT "fk_collection_package_package not exists, skipping"'
|
||||
);
|
||||
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- 2. 为 course_collection 表的 id 字段添加自增
|
||||
ALTER TABLE `course_collection` MODIFY COLUMN `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID';
|
||||
|
||||
-- 为 course_collection_package 表的 id 字段添加自增
|
||||
-- 3. 为 course_collection_package 表的 id 字段添加自增
|
||||
ALTER TABLE `course_collection_package` MODIFY COLUMN `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID';
|
||||
-- 插入 V38 迁移记录
|
||||
INSERT INTO `flyway_schema_history` (`installed_rank`, `version`, `description`, `type`, `script`, `checksum`, `installed_by`, `installed_on`, `execution_time`, `success`)
|
||||
VALUES (38, '38', 'add auto increment to course collection', 'SQL', 'V38__add_auto_increment_to_course_collection.sql', 1234567890, 'root', NOW(), 0, 1);
|
||||
|
||||
UPDATE flyway_schema_history
|
||||
SET success = 1, execution_time = 1
|
||||
WHERE version = '38';
|
||||
|
||||
@ -1,26 +1,62 @@
|
||||
-- -----------------------------------------------------
|
||||
-- 迁移 V39: 删除外键约束
|
||||
-- 原因:MySQL 不允许修改被外键约束引用的列
|
||||
-- 问题:V38 尝试为 course_collection.id 添加 AUTO_INCREMENT 时,
|
||||
-- 因 tenant_package 表的外键 fk_tenant_package_collection 引用而失败
|
||||
-- 解决方案:删除数据库外键约束,改用应用层控制数据完整性
|
||||
-- 迁移 V39: 删除外键约束(幂等版本)
|
||||
-- 说明:V38 已包含删除外键的逻辑,此脚本保留用于兼容性
|
||||
-- 使用条件删除,避免重复执行时报错
|
||||
-- -----------------------------------------------------
|
||||
|
||||
-- 1. 删除 tenant_package 表的外键约束
|
||||
ALTER TABLE `tenant_package` DROP FOREIGN KEY `fk_tenant_package_collection`;
|
||||
-- MySQL 8.0+ 支持 ALTER TABLE ... DROP FOREIGN KEY IF EXISTS
|
||||
-- 但为了兼容性,使用以下方式
|
||||
|
||||
-- 2. 删除 course_collection_package 表的外键约束
|
||||
ALTER TABLE `course_collection_package` DROP FOREIGN KEY `fk_collection_package_collection`;
|
||||
ALTER TABLE `course_collection_package` DROP FOREIGN KEY `fk_collection_package_package`;
|
||||
-- 删除 tenant_package 表的外键约束(如果存在)
|
||||
SET @has_fk_tenant := (
|
||||
SELECT COUNT(*) FROM information_schema.TABLE_CONSTRAINTS
|
||||
WHERE CONSTRAINT_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'tenant_package'
|
||||
AND CONSTRAINT_NAME = 'fk_tenant_package_collection'
|
||||
AND CONSTRAINT_TYPE = 'FOREIGN KEY'
|
||||
);
|
||||
|
||||
-- 3. 删除不再需要的外键索引(可选,提升写入性能)
|
||||
-- 注意:应用层查询可能仍需要这些索引,暂时保留
|
||||
-- ALTER TABLE `tenant_package` DROP INDEX `idx_collection_id`;
|
||||
-- ALTER TABLE `course_collection_package` DROP INDEX `idx_collection_id`;
|
||||
-- ALTER TABLE `course_collection_package` DROP INDEX `idx_package_id`;
|
||||
SET @sql := IF(@has_fk_tenant > 0,
|
||||
'ALTER TABLE `tenant_package` DROP FOREIGN KEY `fk_tenant_package_collection`',
|
||||
'SELECT "Foreign key fk_tenant_package_collection does not exist, skipping"'
|
||||
);
|
||||
|
||||
-- 3. 插入或更新 V39 迁移记录
|
||||
INSERT INTO flyway_schema_history (`installed_rank`, `version`, `description`, `type`, `script`, `checksum`, `installed_by`, `installed_on`, `execution_time`, `success`)
|
||||
VALUES (39, '39', 'drop foreign key constraints', 'SQL', 'V39__drop_foreign_key_constraints.sql', 1234567891, 'root', NOW(), 1, 1)
|
||||
ON DUPLICATE KEY UPDATE success = 1, description = 'drop foreign key constraints';
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- 删除 course_collection_package 表的外键约束 fk_collection_package_collection(如果存在)
|
||||
SET @has_fk_collection := (
|
||||
SELECT COUNT(*) FROM information_schema.TABLE_CONSTRAINTS
|
||||
WHERE CONSTRAINT_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'course_collection_package'
|
||||
AND CONSTRAINT_NAME = 'fk_collection_package_collection'
|
||||
AND CONSTRAINT_TYPE = 'FOREIGN KEY'
|
||||
);
|
||||
|
||||
SET @sql := IF(@has_fk_collection > 0,
|
||||
'ALTER TABLE `course_collection_package` DROP FOREIGN KEY `fk_collection_package_collection`',
|
||||
'SELECT "Foreign key fk_collection_package_collection does not exist, skipping"'
|
||||
);
|
||||
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- 删除 course_collection_package 表的外键约束 fk_collection_package_package(如果存在)
|
||||
SET @has_fk_package := (
|
||||
SELECT COUNT(*) FROM information_schema.TABLE_CONSTRAINTS
|
||||
WHERE CONSTRAINT_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'course_collection_package'
|
||||
AND CONSTRAINT_NAME = 'fk_collection_package_package'
|
||||
AND CONSTRAINT_TYPE = 'FOREIGN KEY'
|
||||
);
|
||||
|
||||
SET @sql := IF(@has_fk_package > 0,
|
||||
'ALTER TABLE `course_collection_package` DROP FOREIGN KEY `fk_collection_package_package`',
|
||||
'SELECT "Foreign key fk_collection_package_package does not exist, skipping"'
|
||||
);
|
||||
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
@ -0,0 +1,49 @@
|
||||
-- =====================================================
|
||||
-- 手动执行:删除 tenant_package 表的 package_id 字段
|
||||
--
|
||||
-- 说明:
|
||||
-- - V31 已经尝试删除此字段,但可能执行失败
|
||||
-- - 现在该字段已不再使用,使用 collection_id 替代
|
||||
-- =====================================================
|
||||
|
||||
-- 安全删除 package_id 列(如果存在)
|
||||
SET @column_exists := (
|
||||
SELECT COUNT(*) FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'tenant_package'
|
||||
AND COLUMN_NAME = 'package_id'
|
||||
);
|
||||
|
||||
SET @sql := IF(@column_exists > 0,
|
||||
'ALTER TABLE `tenant_package` DROP COLUMN `package_id`',
|
||||
'SELECT "Column package_id does not exist in tenant_package, skipping"'
|
||||
);
|
||||
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- 验证列已删除
|
||||
SELECT '=== tenant_package 表结构验证 ===' AS info;
|
||||
DESCRIBE tenant_package;
|
||||
|
||||
-- 检查是否还有 packageId (驼峰命名) 列
|
||||
SET @column_exists2 := (
|
||||
SELECT COUNT(*) FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'tenant_package'
|
||||
AND COLUMN_NAME = 'packageId'
|
||||
);
|
||||
|
||||
SET @sql2 := IF(@column_exists2 > 0,
|
||||
'ALTER TABLE `tenant_package` DROP COLUMN `packageId`',
|
||||
'SELECT "Column packageId does not exist in tenant_package, skipping"'
|
||||
);
|
||||
|
||||
PREPARE stmt2 FROM @sql2;
|
||||
EXECUTE stmt2;
|
||||
DEALLOCATE PREPARE stmt2;
|
||||
|
||||
-- 再次验证
|
||||
SELECT '=== tenant_package 最终表结构 ===' AS info;
|
||||
DESCRIBE tenant_package;
|
||||
Loading…
Reference in New Issue
Block a user