12 KiB
Class Management V1 Implementation Plan
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: Implement the first working slice of the merged class-management requirements: administrative/teaching class types, school-wide class-name uniqueness, teaching-class membership, dependency-safe deletes, and teaching-class data initialization entry points.
Architecture: Keep the existing UserController endpoints compatible while adding small focused model objects and mapper methods. school_class remains the class master table and gains type/source fields; a new teaching_class_student table records many-to-many student membership/history for teaching classes. Frontend class management remains under the teacher end but is split into administrative and teaching tabs.
Tech Stack: Spring Boot, MyBatis XML mappers, JUnit 5 + Mockito, Vue 3, Element Plus, Vite.
File Structure
- Backend SQL:
- Create
docs/sql/2026-06-23-class-management-v1.sqlwith new columns and new mapping tables.
- Create
- Backend model:
- Modify
src/main/java/com/sztzjy/linkCommerce/entity/SchoolClass.javaforclassType,dataSource, andsourceClassIds. - Modify
src/main/java/com/sztzjy/linkCommerce/entity/SchoolClassExample.javafor class-type criteria. - Create
src/main/java/com/sztzjy/linkCommerce/entity/TeachingClassStudent.java. - Create
src/main/java/com/sztzjy/linkCommerce/entity/ExternalResourceMapping.java.
- Modify
- Backend mapper:
- Modify
src/main/java/com/sztzjy/linkCommerce/mapper/SchoolClassMapper.javaandsrc/main/resources/mappers/SchoolClassMapper.xml. - Create
src/main/java/com/sztzjy/linkCommerce/mapper/TeachingClassStudentMapper.java. - Create
src/main/resources/mappers/TeachingClassStudentMapper.xml. - Create
src/main/java/com/sztzjy/linkCommerce/mapper/ExternalResourceMappingMapper.java. - Create
src/main/resources/mappers/ExternalResourceMappingMapper.xml.
- Modify
- Backend service/controller:
- Modify
src/main/java/com/sztzjy/linkCommerce/controller/stu/UserController.javafor type-aware create/update/delete/list and initialization endpoints. - Reuse existing
/api/cptf/restartTrainingByAllfor current class initialization, and add user/controller endpoints that explicitly check teaching-class ownership before calling it in frontend.
- Modify
- Backend tests:
- Modify
src/test/java/com/sztzjy/linkCommerce/controller/stu/UserControllerTeacherAdminTest.java. - Create
src/test/java/com/sztzjy/linkCommerce/entity/TeachingClassStudentModelTest.java.
- Modify
- Frontend API:
- Modify
E:/workspace/dianshang/e-commerce-internet/src/api/teacher.js.
- Modify
- Frontend views:
- Modify
E:/workspace/dianshang/e-commerce-internet/src/views/teacherEnd/class/index.vue. - Modify
E:/workspace/dianshang/e-commerce-internet/src/views/teacherEnd/student/index.vue.
- Modify
Task 1: Backend Model And SQL
Files:
-
Create:
docs/sql/2026-06-23-class-management-v1.sql -
Modify:
src/main/java/com/sztzjy/linkCommerce/entity/SchoolClass.java -
Modify:
src/main/resources/mappers/SchoolClassMapper.xml -
Modify:
src/main/java/com/sztzjy/linkCommerce/entity/SchoolClassExample.java -
Create:
src/main/java/com/sztzjy/linkCommerce/entity/TeachingClassStudent.java -
Create:
src/main/java/com/sztzjy/linkCommerce/mapper/TeachingClassStudentMapper.java -
Create:
src/main/resources/mappers/TeachingClassStudentMapper.xml -
Create:
src/main/java/com/sztzjy/linkCommerce/entity/ExternalResourceMapping.java -
Create:
src/main/java/com/sztzjy/linkCommerce/mapper/ExternalResourceMappingMapper.java -
Create:
src/main/resources/mappers/ExternalResourceMappingMapper.xml -
Test:
src/test/java/com/sztzjy/linkCommerce/entity/TeachingClassStudentModelTest.java -
Step 1: Write failing model tests
Add tests asserting SchoolClass can store ADMIN/TEACHING class types and TeachingClassStudent stores member status.
Run: mvn -Dtest=TeachingClassStudentModelTest test
Expected before implementation: compilation fails because TeachingClassStudent does not exist and SchoolClass#getClassType does not exist.
- Step 2: Implement model fields and mapper XML
Add:
private String classType;
private String dataSource;
private String sourceClassIds;
to SchoolClass; map columns class_type, data_source, and source_class_ids.
Create TeachingClassStudent with fields:
private String id;
private String teachingClassId;
private String studentUserId;
private String adminClassId;
private String status;
private String joinReason;
private Date joinTime;
private Date exitTime;
private Date createTime;
Create mapper methods:
long countByTeachingClassId(String teachingClassId);
long countByStudentUserIdAndTeachingClassId(@Param("studentUserId") String studentUserId, @Param("teachingClassId") String teachingClassId);
int insertSelective(TeachingClassStudent record);
int deleteByTeachingClassId(String teachingClassId);
Create ExternalResourceMapping and mapper as the reserved foundation for Zhiyun duplicate external account mapping.
- Step 3: Run model tests
Run: mvn -Dtest=TeachingClassStudentModelTest test
Expected after implementation: tests pass.
Task 2: Backend Class Rules
Files:
-
Modify:
src/main/java/com/sztzjy/linkCommerce/controller/stu/UserController.java -
Modify:
src/test/java/com/sztzjy/linkCommerce/controller/stu/UserControllerTeacherAdminTest.java -
Step 1: Write failing controller tests
Add tests for:
addSchoolClassRejectsDuplicateNameInSameSchool()
addSchoolClassDefaultsToTeachingClassWhenTeacherCreatesIt()
deleteFacultyRejectsWhenMajorExists()
deleteMajorRejectsWhenClassExists()
deleteClassRejectsWhenStudentsExist()
Run: mvn -Dtest=UserControllerTeacherAdminTest test
Expected before implementation: duplicate-by-school and dependency-delete tests fail.
- Step 2: Implement class uniqueness and class type
Change addSchoolClass to accept optional classType; default to TEACHING when a teacher creates the class and to ADMIN when omitted by platform/admin contexts. Check duplicates by school_id + class_name, not by school_major_id + class_name.
Change updateSchoolClass to reject updates that would duplicate school_id + class_name on a different school_class_id.
- Step 3: Implement dependency delete checks
Before deleting:
deleteSchoolFaculty -> reject if SchoolMajor exists under faculty
deleteSchoolMajor -> reject if SchoolClass exists under major
deleteSchoolClass -> reject if Userinfo students exist in admin class or TeachingClassStudent members exist in teaching class
Expected error messages can be simple Chinese user-facing strings such as 院系下存在专业,不能删除.
- Step 4: Run controller tests
Run: mvn -Dtest=UserControllerTeacherAdminTest test
Expected after implementation: tests pass.
Task 3: Backend Teaching-Class Membership And Initialization
Files:
-
Modify:
src/main/java/com/sztzjy/linkCommerce/controller/stu/UserController.java -
Modify:
src/test/java/com/sztzjy/linkCommerce/controller/stu/UserControllerTeacherAdminTest.java -
Step 1: Write failing tests
Add tests for:
addStudentToTeachingClassCreatesMembershipInsteadOfChangingAdminClass()
teacherCannotInitializeTeachingClassCreatedByAnotherTeacher()
teacherCanInitializeSingleStudentOnlyInOwnedTeachingClass()
Run: mvn -Dtest=UserControllerTeacherAdminTest test
Expected before implementation: tests fail because membership mapper/initialization endpoints are missing.
- Step 2: Add membership creation
When adding a student to a teaching class, preserve the student schoolClassId as the administrative class and insert a TeachingClassStudent row linking student_user_id to teaching_class_id.
For compatibility, keep existing student account creation working for administrative classes.
- Step 3: Add initialization endpoints
Add:
@PostMapping("/initializeTeachingClassTrainingData")
ResultEntity initializeTeachingClassTrainingData(@RequestParam String teachingClassId, @RequestParam String operatorId)
@PostMapping("/initializeTeachingClassStudentTrainingData")
ResultEntity initializeTeachingClassStudentTrainingData(@RequestParam String teachingClassId, @RequestParam String studentUserId, @RequestParam String operatorId)
Both endpoints must check that the class is TEACHING and owned by operatorId. The first initializes all teaching-class members; the second initializes one member. In V1, return success after validation and keep the actual existing training cleanup call delegated to current module endpoints until training-data table ownership is mapped in a follow-up.
- Step 4: Run controller tests
Run: mvn -Dtest=UserControllerTeacherAdminTest test
Expected after implementation: tests pass.
Task 4: Frontend Class Tabs And Init Buttons
Files:
-
Modify:
E:/workspace/dianshang/e-commerce-internet/src/api/teacher.js -
Modify:
E:/workspace/dianshang/e-commerce-internet/src/views/teacherEnd/class/index.vue -
Step 1: Update API helpers
Add:
export function initializeTeachingClassTrainingData(params) {
return request({ url: "/api/user/initializeTeachingClassTrainingData", method: "POST", params });
}
Update class list requests to pass classType.
- Step 2: Split UI into tabs
Use el-tabs with ADMIN and TEACHING. Administrative tab hides data initialization. Teaching tab shows edit/delete/member/data-init actions according to ownership.
- Step 3: Verify build
Run: npm run build:prod
Expected: build exits 0.
Task 5: Frontend Student Teaching-Class Actions
Files:
-
Modify:
E:/workspace/dianshang/e-commerce-internet/src/api/teacher.js -
Modify:
E:/workspace/dianshang/e-commerce-internet/src/views/teacherEnd/student/index.vue -
Step 1: Update API helper
Add:
export function initializeTeachingClassStudentTrainingData(params) {
return request({ url: "/api/user/initializeTeachingClassStudentTrainingData", method: "POST", params });
}
- Step 2: Scope student initialization to teaching class
Require a teaching class selection before single-student data initialization. Send teachingClassId, studentUserId, and operatorId.
- Step 3: Verify build
Run: npm run build:prod
Expected: build exits 0.
Task 6: Full Verification And Restart
Files:
-
No new source files unless verification reveals failures.
-
Step 1: Run backend tests
Run: mvn test
Expected: all tests pass.
- Step 2: Run frontend build
Run: npm run build:prod
Expected: build exits 0.
- Step 3: Restart services
Stop listeners on ports 7548 and 147, then start backend and frontend dev server:
cd E:\workspace\dianshang\link_commerce
mvn spring-boot:run -Dspring-boot.run.profiles=dev
cd E:\workspace\dianshang\e-commerce-internet
npm run dev -- --host 0.0.0.0 --port 147
Expected: backend listens on 7548, frontend listens on 147.
Plan Self-Review
- Spec coverage in V1: class tabs, class type, school-wide class-name uniqueness, delete dependency checks, teaching-class membership foundation, student one-admin-class/many-teaching-class model, initialization entry points, and Zhiyun external mapping foundation.
- Deferred by design: full historical migration of existing student/class data, actual deletion of every training module table during initialization, complete Zhiyun pull/push synchronization policy, and score-center query rewrites across every report. These require a separate implementation plan after V1 lands because they touch many scoring/training modules.
- No placeholder tasks remain in this plan; every task has concrete files, commands, and expected results.