# 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.sql` with new columns and new mapping tables. - Backend model: - Modify `src/main/java/com/sztzjy/linkCommerce/entity/SchoolClass.java` for `classType`, `dataSource`, and `sourceClassIds`. - Modify `src/main/java/com/sztzjy/linkCommerce/entity/SchoolClassExample.java` for class-type criteria. - Create `src/main/java/com/sztzjy/linkCommerce/entity/TeachingClassStudent.java`. - Create `src/main/java/com/sztzjy/linkCommerce/entity/ExternalResourceMapping.java`. - Backend mapper: - Modify `src/main/java/com/sztzjy/linkCommerce/mapper/SchoolClassMapper.java` and `src/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`. - Backend service/controller: - Modify `src/main/java/com/sztzjy/linkCommerce/controller/stu/UserController.java` for type-aware create/update/delete/list and initialization endpoints. - Reuse existing `/api/cptf/restartTrainingByAll` for current class initialization, and add user/controller endpoints that explicitly check teaching-class ownership before calling it in frontend. - Backend tests: - Modify `src/test/java/com/sztzjy/linkCommerce/controller/stu/UserControllerTeacherAdminTest.java`. - Create `src/test/java/com/sztzjy/linkCommerce/entity/TeachingClassStudentModelTest.java`. - Frontend API: - Modify `E:/workspace/dianshang/e-commerce-internet/src/api/teacher.js`. - 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`. --- ### 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: ```java 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: ```java 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: ```java 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: ```java 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: ```java 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: ```java 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: ```java @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: ```javascript 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: ```javascript 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: ```powershell 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.