jinxia.mo 1 месяц назад
Родитель
Сommit
3ed5db7684
24 измененных файлов с 581 добавлено и 229 удалено
  1. 25 3
      back-ui/src/views/dz/agent/index.vue
  2. 7 7
      back-ui/src/views/dz/campus/index.vue
  3. 33 33
      back-ui/src/views/dz/classes/index.vue
  4. 21 21
      back-ui/src/views/dz/open/config/table.js
  5. 21 21
      back-ui/src/views/dz/school/index.vue
  6. 173 12
      back-ui/src/views/dz/teacher/index.vue
  7. 2 2
      back-ui/src/views/learn/student/statisticStudyRecord.vue
  8. 1 1
      back-ui/src/views/system/user/indexCard.vue
  9. 1 0
      ie-admin/src/main/java/com/ruoyi/web/controller/dz/DzAgentController.java
  10. 2 117
      ie-admin/src/main/java/com/ruoyi/web/controller/dz/DzTeacherClassController.java
  11. 30 1
      ie-admin/src/main/java/com/ruoyi/web/controller/dz/DzTeacherController.java
  12. 35 0
      ie-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java
  13. 13 1
      ie-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java
  14. 8 2
      ie-system/src/main/java/com/ruoyi/dz/domain/DzAgent.java
  15. 33 0
      ie-system/src/main/java/com/ruoyi/dz/domain/DzTeacher.java
  16. 8 0
      ie-system/src/main/java/com/ruoyi/dz/service/IDzTeacherClassService.java
  17. 129 0
      ie-system/src/main/java/com/ruoyi/dz/service/impl/DzTeacherClassServiceImpl.java
  18. 11 1
      ie-system/src/main/java/com/ruoyi/learn/dto/StudyRecordStatisticsDTO.java
  19. 1 0
      ie-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java
  20. 1 0
      ie-system/src/main/java/com/ruoyi/system/service/ISysUserService.java
  21. 8 0
      ie-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
  22. 6 5
      ie-system/src/main/resources/mapper/dz/DzCardsOpenMapper.xml
  23. 4 2
      ie-system/src/main/resources/mapper/learn/LearnStudentMapper.xml
  24. 8 0
      ie-system/src/main/resources/mapper/system/SysUserMapper.xml

+ 25 - 3
back-ui/src/views/dz/agent/index.vue

@@ -108,12 +108,22 @@
                           <!--      <el-table-column label="上级代理商ID" align="center" prop="parentId" />-->
 <!--                          <el-table-column label="学校/校区" align="center" prop="schools" />-->
 <!--                          <el-table-column label="学校/校区" align="center" prop="schoolName" />-->
-                          <!-- <el-table-column label="备注" align="center" prop="remark" /> -->
+                          <el-table-column label="用户ID" align="center" prop="userId" />
+                          <el-table-column label="禁用状态" align="center" key="status">
+                              <template #default="scope">
+                                  <el-switch
+                                      v-model="scope.row.status"
+                                      active-value="0"
+                                      inactive-value="1"
+                                      @change="handleStatusChange(scope.row)"
+                                  ></el-switch>
+                              </template>
+                          </el-table-column>
                           <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
                               <template #default="scope">
                                   <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['dz:agent:edit']">修改</el-button>
                                   <el-button link type="primary" icon="Plus" @click="handleAdd(scope.row)" v-hasPermi="['dz:agent:add']">新增</el-button>
-                                  <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['dz:agent:remove']">删除</el-button>
+                                  <!-- <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['dz:agent:remove']">删除</el-button> -->
                               </template>
                           </el-table-column>
                       </el-table>
@@ -178,7 +188,7 @@
 
 <script setup name="Agent">
 import { listAgent, getAgent, delAgent, addAgent, updateAgent } from "@/api/dz/agent"
-import { deptTreeSelect } from "@/api/system/user"
+import { deptTreeSelect, changeUserStatus } from "@/api/system/user"
 import useAppStore from '@/store/modules/app'
 import { Splitpanes, Pane } from "splitpanes"
 import "splitpanes/dist/splitpanes.css"
@@ -432,6 +442,18 @@ function handleExport() {
   }, `agent_${new Date().getTime()}.xlsx`)
 }
 
+/** 用户状态修改  */
+function handleStatusChange(row) {
+  let text = row.status === "0" ? "启用" : "禁用"
+  proxy.$modal.confirm('确认要"' + text + '""' + row.name + '"用户吗?').then(function () {
+    return changeUserStatus(row.userId, row.status)
+  }).then(() => {
+    proxy.$modal.msgSuccess(text + "成功")
+  }).catch(function () {
+    row.status = row.status === "0" ? "1" : "0"
+  })
+}
+
 // getList()
 
 onMounted(() => {

+ 7 - 7
back-ui/src/views/dz/campus/index.vue

@@ -54,7 +54,7 @@
                   <el-option v-for="dict in bool_values" :key="dict.value" :label="dict.label" :value="dict.value" />
                 </el-select>
               </el-form-item> -->
-              
+
               <el-form-item>
                 <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
                 <el-button icon="Refresh" @click="resetQuery">重置</el-button>
@@ -94,17 +94,17 @@
               <!--              <el-table-column label="市" align="center" prop="city" />-->
               <!--              <el-table-column label="区" align="center" prop="area" />-->
               <!-- <el-table-column label="所属地区" align="center" prop="proCityAreaName" /> -->
-              <el-table-column label="状态" align="center" prop="status">
-                <template #default="scope">
-                  <dict-tag :options="bool_values" :value="scope.row.status" />
-                </template>
-              </el-table-column>
+<!--              <el-table-column label="状态" align="center" prop="status">-->
+<!--                <template #default="scope">-->
+<!--                  <dict-tag :options="bool_values" :value="scope.row.status" />-->
+<!--                </template>-->
+<!--              </el-table-column>-->
               <!-- <el-table-column label="学校类型" align="center" prop="examTypes">
                 <template #default="scope">
                   <span>{{ formatExamTypes(scope.row.examTypes) }}</span>
                 </template>
               </el-table-column> -->
-              <el-table-column label="备注" align="center" prop="remark" />
+<!--              <el-table-column label="备注" align="center" prop="remark" />-->
               <el-table-column label="班级管理" align="center" width="120">
                 <template #default="scope">
                   <el-button link type="primary" @click="handleViewClasses(scope.row)">点击查看</el-button>

+ 33 - 33
back-ui/src/views/dz/classes/index.vue

@@ -42,16 +42,16 @@
                 @keyup.enter="handleQuery"
         />
       </el-form-item>
-      <el-form-item label="是否线上" prop="online">
-        <el-select v-model="queryParams.online" placeholder="请选择是否线上" clearable style="width: 170px;">
-          <el-option
-                  v-for="dict in bool_values"
-                  :key="dict.value"
-                  :label="dict.label"
-                  :value="dict.value"
-          />
-        </el-select>
-      </el-form-item>
+<!--      <el-form-item label="是否线上" prop="online">-->
+<!--        <el-select v-model="queryParams.online" placeholder="请选择是否线上" clearable style="width: 170px;">-->
+<!--          <el-option-->
+<!--                  v-for="dict in bool_values"-->
+<!--                  :key="dict.value"-->
+<!--                  :label="dict.label"-->
+<!--                  :value="dict.value"-->
+<!--          />-->
+<!--        </el-select>-->
+<!--      </el-form-item>-->
       <!-- <el-form-item label="状态" prop="status">
         <el-input
                 v-model="queryParams.status"
@@ -111,21 +111,21 @@
     <el-table v-loading="loading" :data="classesList" @selection-change="handleSelectionChange">
       <el-table-column type="selection" width="55" align="center" />
       <el-table-column label="ID" align="center" prop="classId" />
-      <el-table-column label="名称" align="center" prop="name" />
+      <el-table-column label="班级名称" align="center" prop="name" />
 <!--      <el-table-column label="学校" align="center" prop="schoolId" />-->
       <el-table-column label="学校" align="center" prop="school.name" />
       <el-table-column label="毕业年份" align="center" prop="year" />
-      <el-table-column label="是否线上" align="center" prop="online">
-        <template #default="scope">
-          <dict-tag :options="bool_values" :value="scope.row.online"/>
-        </template>
-      </el-table-column>
+<!--      <el-table-column label="是否线上" align="center" prop="online">-->
+<!--        <template #default="scope">-->
+<!--          <dict-tag :options="bool_values" :value="scope.row.online"/>-->
+<!--        </template>-->
+<!--      </el-table-column>-->
       <!-- <el-table-column label="状态" align="center" prop="status">
         <template #default="scope">
           <dict-tag :options="bool_values" :value="scope.row.status"/>
         </template>
       </el-table-column> -->
-      <el-table-column label="统计数据" align="center" prop="stats" />
+<!--      <el-table-column label="统计数据" align="center" prop="stats" />-->
       <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
         <template #default="scope">
           <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['dz:classes:edit']">修改</el-button>
@@ -148,11 +148,11 @@
 <!--        <el-form-item label="学校" prop="schoolId">-->
 <!--          <el-input v-model="form.schoolId" placeholder="请输入学校" />-->
 <!--        </el-form-item>-->
-        
+
         <el-form-item label="学校校区" prop="schoolId">
-          <el-select 
-                  v-model="form.schoolId" 
-                  placeholder="请选择学校校区" 
+          <el-select
+                  v-model="form.schoolId"
+                  placeholder="请选择学校校区"
                   style="width: 100%"
                   :disabled="isExternalSchoolIdSet || form.classId != null"
           >
@@ -171,16 +171,16 @@
           <el-input v-model="form.year" placeholder="请输入毕业年份" />
         </el-form-item>
 
-        <el-form-item label="是否线上" prop="online">
-          <el-select v-model="form.online" placeholder="请选择是否线上">
-            <el-option
-                    v-for="dict in bool_values"
-                    :key="dict.value"
-                    :label="dict.label"
-                    :value="parseInt(dict.value)"
-            ></el-option>
-          </el-select>
-        </el-form-item>
+<!--        <el-form-item label="是否线上" prop="online">-->
+<!--          <el-select v-model="form.online" placeholder="请选择是否线上">-->
+<!--            <el-option-->
+<!--                    v-for="dict in bool_values"-->
+<!--                    :key="dict.value"-->
+<!--                    :label="dict.label"-->
+<!--                    :value="parseInt(dict.value)"-->
+<!--            ></el-option>-->
+<!--          </el-select>-->
+<!--        </el-form-item>-->
         <!-- <el-form-item label="状态" prop="status">
           <el-input v-model="form.status" placeholder="请输入状态" />
         </el-form-item> -->
@@ -257,7 +257,7 @@
       return
     }
     // 使用Promise.all并行校验所有名称
-    const checkPromises = nameArray.map(name => 
+    const checkPromises = nameArray.map(name =>
       checkClassName(schoolId, name, classId).then(response => ({
         name,
         isUnique: response.data
@@ -298,7 +298,7 @@
     const nameArray = name.split(',').map(n => n.trim()).filter(n => n)
     if (nameArray.length === 0) return
     // 使用Promise.all并行校验所有名称
-    const checkPromises = nameArray.map(n => 
+    const checkPromises = nameArray.map(n =>
       checkClassName(schoolId, n, classId).then(response => ({
         name: n,
         isUnique: response.data

+ 21 - 21
back-ui/src/views/dz/open/config/table.js

@@ -55,16 +55,16 @@ const tableConfig = {
       align: "center",
       minWidth: 120,
     },
-    
-    
-    {
-      label: "申请状态",
-      prop: "status",
-      align: "center",
-      width: 100,
-      type: "slot",
-      slotName: "status",
-    },
+
+
+    // {
+    //   label: "申请状态",
+    //   prop: "status",
+    //   align: "center",
+    //   width: 100,
+    //   type: "slot",
+    //   slotName: "status",
+    // },
     // {
     //   label: "原因",
     //   prop: "auditDesc",
@@ -73,7 +73,7 @@ const tableConfig = {
     //   type: "slot",
     //   slotName: "auditDesc",
     // },
-    
+
     {
       label: "重新开卡",
       prop: "isReopen",
@@ -93,16 +93,16 @@ const tableConfig = {
   ],
 
   // 操作按钮配置
-  actions: [
-    {
-      key: "review",
-      label: "审核",
-      type: "primary",
-      link: true,
-      permission: ["dz:open:review"],
-      condition: (row) => row.status === 1, // 只有待审核状态才显示审核按钮
-    },
-  ],
+  // actions: [
+  //   {
+  //     key: "review",
+  //     label: "审核",
+  //     type: "primary",
+  //     link: true,
+  //     permission: ["dz:open:review"],
+  //     condition: (row) => row.status === 1, // 只有待审核状态才显示审核按钮
+  //   },
+  // ],
 
   // 表格属性配置
   tableProps: {

+ 21 - 21
back-ui/src/views/dz/school/index.vue

@@ -40,7 +40,7 @@
 <!--                        @keyup.enter="handleQuery"-->
 <!--                />-->
 <!--              </el-form-item>-->
-              
+
 
               <!-- <el-form-item label="状态" prop="status">
                 <el-select v-model="queryParams.status" placeholder="请选择状态" clearable style="width: 170px">
@@ -120,17 +120,17 @@
 <!--              <el-table-column label="归属机构" align="center" key="deptName" prop="dept.deptName" :show-overflow-tooltip="true" />-->
 <!--              <el-table-column label="省份" align="center" prop="location" />-->
               <el-table-column label="所属地区" align="center" prop="proCityAreaName" />
-              <el-table-column label="状态" align="center" prop="status">
-                <template #default="scope">
-                  <dict-tag :options="bool_values" :value="scope.row.status"/>
-                </template>
-              </el-table-column>
+<!--              <el-table-column label="状态" align="center" prop="status">-->
+<!--                <template #default="scope">-->
+<!--                  <dict-tag :options="bool_values" :value="scope.row.status"/>-->
+<!--                </template>-->
+<!--              </el-table-column>-->
               <el-table-column label="学校类型" align="center" prop="examTypes">
                 <template #default="scope">
                   <span>{{ formatExamTypes(scope.row.examTypes) }}</span>
                 </template>
               </el-table-column>
-              <el-table-column label="备注" align="center" prop="remark" />
+<!--              <el-table-column label="备注" align="center" prop="remark" />-->
               <el-table-column label="班级管理" align="center" width="120">
                 <template #default="scope">
                   <el-button link type="primary" @click="handleViewClasses(scope.row)">点击查看</el-button>
@@ -176,7 +176,7 @@
         <el-form-item label="省市区" prop="areaIds">
           <AddressSelect v-model="formAreaIds" style="width: 100%" />
         </el-form-item>
-        
+
         <el-form-item label="学校类型" prop="examTypes">
           <el-select v-model="form.examTypes" placeholder="请选择学校类型" multiple>
             <el-option
@@ -187,19 +187,19 @@
             ></el-option>
           </el-select>
         </el-form-item>
-        <el-form-item label="状态" prop="status">
-          <el-select v-model="form.status" placeholder="请选择状态">
-            <el-option
-                    v-for="dict in bool_values"
-                    :key="dict.value"
-                    :label="dict.label"
-                    :value="parseInt(dict.value)"
-            ></el-option>
-          </el-select>
-        </el-form-item>
-        <el-form-item label="备注" prop="remark">
-          <el-input v-model="form.remark" placeholder="请输入备注" />
-        </el-form-item>
+<!--        <el-form-item label="状态" prop="status">-->
+<!--          <el-select v-model="form.status" placeholder="请选择状态">-->
+<!--            <el-option-->
+<!--                    v-for="dict in bool_values"-->
+<!--                    :key="dict.value"-->
+<!--                    :label="dict.label"-->
+<!--                    :value="parseInt(dict.value)"-->
+<!--            ></el-option>-->
+<!--          </el-select>-->
+<!--        </el-form-item>-->
+<!--        <el-form-item label="备注" prop="remark">-->
+<!--          <el-input v-model="form.remark" placeholder="请输入备注" />-->
+<!--        </el-form-item>-->
       </el-form>
       <template #footer>
         <div class="dialog-footer">

+ 173 - 12
back-ui/src/views/dz/teacher/index.vue

@@ -77,7 +77,7 @@
           v-hasPermi="['dz:teacher:edit']"
         >修改</el-button>
       </el-col>
-      <el-col :span="1.5">
+      <!-- <el-col :span="1.5">
         <el-button
           type="danger"
           plain
@@ -86,7 +86,7 @@
           @click="handleDelete"
           v-hasPermi="['dz:teacher:remove']"
         >删除</el-button>
-      </el-col>
+      </el-col> -->
       <el-col :span="1.5">
         <el-button
           type="warning"
@@ -110,7 +110,7 @@
       <el-table-column label="培训校区班级" align="center" prop="campusClass" />
       <el-table-column label="所在机构" align="center" prop="deptName" />
       <el-table-column label="用户ID" align="center" prop="userId" />
-      <el-table-column label="状态" align="center" key="status">
+      <el-table-column label="禁用状态" align="center" key="status">
         <template #default="scope">
           <el-switch
             v-model="scope.row.status"
@@ -125,7 +125,7 @@
           <el-button link type="primary" icon="" @click="handleUpdateTeacherClass(scope.row)" v-hasPermi="['dz:teacher:edit']">学校班级</el-button>
           <el-button link type="primary" icon="" @click="handleUpdateCampusClass(scope.row)" v-hasPermi="['dz:teacher:edit']">校区班级</el-button>
           <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['dz:teacher:edit']">修改</el-button>
-          <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['dz:teacher:remove']">删除</el-button>
+          <!-- <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['dz:teacher:remove']">删除</el-button> -->
         </template>
       </el-table-column>
     </el-table>
@@ -148,7 +148,7 @@
           <el-input v-model="form.name" placeholder="请输入教师姓名" />
         </el-form-item>
         <el-form-item label="所在学校" prop="schoolId">
-          <el-select v-model="form.schoolId" placeholder="请选择所在学校" style="width: 100%">
+          <el-select v-model="form.schoolId" placeholder="请选择所在学校" style="width: 100%" @change="handleSchoolChange">
             <el-option
                     v-for="item in schoolOptions"
                     :key="item.id"
@@ -157,8 +157,18 @@
             />
           </el-select>
         </el-form-item>
+        <el-form-item label="学校班级" prop="schoolClassIds">
+          <el-select v-model="form.schoolClassIds" multiple placeholder="请选择学校班级" style="width: 100%" :disabled="!form.schoolId">
+            <el-option
+                    v-for="item in schoolClassOptions"
+                    :key="item.classId"
+                    :label="item.name"
+                    :value="item.classId"
+            />
+          </el-select>
+        </el-form-item>
         <el-form-item label="培训校区" prop="campusId">
-          <el-select v-model="form.campusId" placeholder="请选择培训校区" style="width: 100%">
+          <el-select v-model="form.campusId" placeholder="请选择培训校区" style="width: 100%" @change="handleCampusChange">
             <el-option
                     v-for="item in campusOptions"
                     :key="item.id"
@@ -167,6 +177,17 @@
             />
           </el-select>
         </el-form-item>
+        
+        <el-form-item label="校区班级" prop="campusClassIds">
+          <el-select v-model="form.campusClassIds" multiple placeholder="请选择校区班级" style="width: 100%" :disabled="!form.campusId">
+            <el-option
+                    v-for="item in campusClassOptions"
+                    :key="item.classId"
+                    :label="item.name"
+                    :value="item.classId"
+            />
+          </el-select>
+        </el-form-item>
       </el-form>
       <template #footer>
         <div class="dialog-footer">
@@ -218,7 +239,7 @@
                           v-model="formCampusClass.campusId" 
                           placeholder="请选择培训校区" 
                           style="width: 100%"
-                          @change="handleCampusChange"
+                          @change="handleCampusClassChange"
                   >
                       <el-option
                               v-for="item in campusOptions"
@@ -259,7 +280,7 @@
 import { listTeacher, getTeacher, delTeacher, addTeacher, updateTeacher } from "@/api/dz/teacher"
 import {listAllSchool} from "@/api/dz/school"
 import {listCampus} from "@/api/dz/campus"
-import { listAllClass } from "@/api/dz/classes"
+import { listAllClass, getClassesBySchoolId } from "@/api/dz/classes"
 import { batchBindTeacherClass,listAllTeacherClass } from "@/api/dz/teacherclass"
 import {getCampusSchoolList} from "@/api/dz/cards.js";
 import { changeUserStatus } from "@/api/system/user"
@@ -271,6 +292,7 @@ const schoolOptions = ref([])
 const campusOptions = ref([])
 const classOptions = ref([])
 const campusClassOptions = ref([])
+const schoolClassOptions = ref([])
 const open = ref(false)
 const openTeacherClass = ref(false)
 const openCampusClass = ref(false)
@@ -375,8 +397,12 @@ function reset() {
     userId: null,
     schoolId: null,
     campusId: null,
-    name: null
+    name: null,
+    schoolClassIds: [],
+    campusClassIds: []
   }
+  schoolClassOptions.value = []
+  campusClassOptions.value = []
   proxy.resetForm("teacherRef")
 }
 
@@ -421,6 +447,8 @@ function handleSelectionChange(selection) {
 /** 新增按钮操作 */
 function handleAdd() {
   reset()
+  getSchoolList()
+  getCampusList()
   open.value = true
   title.value = "添加老师"
 }
@@ -428,14 +456,147 @@ function handleAdd() {
 /** 修改按钮操作 */
 function handleUpdate(row) {
   reset()
+  getSchoolList()
+  getCampusList()
   const _teacherId = row.teacherId || ids.value
   getTeacher(_teacherId).then(response => {
     form.value = response.data
+    // 初始化班级ID数组
+    form.value.schoolClassIds = []
+    form.value.campusClassIds = []
+    
+    // 先加载班级列表,然后获取已关联的班级并回显
+    const loadPromises = []
+    
+    if (form.value.schoolId) {
+      loadPromises.push(
+        getClassesBySchoolId({ schoolId: form.value.schoolId }).then(response => {
+          schoolClassOptions.value = response.data || []
+        })
+      )
+    }
+    
+    if (form.value.campusId) {
+      loadPromises.push(
+        getClassesBySchoolId({ campusId: form.value.campusId }).then(response => {
+          campusClassOptions.value = response.data || []
+        })
+      )
+    }
+    
+    // 获取该老师已关联的所有班级
+    Promise.all([
+      ...loadPromises,
+      listAllTeacherClass({ teacherId: _teacherId })
+    ]).then((results) => {
+      const teacherClassResponse = results[results.length - 1]
+      const teacherClasses = teacherClassResponse.data || []
+      
+      // 根据班级所属的学校/校区,分别设置到对应的数组中
+      teacherClasses.forEach(tc => {
+        if (tc.classId) {
+          // 检查该班级是否属于学校
+          const schoolClass = schoolClassOptions.value.find(c => c.classId === tc.classId)
+          if (schoolClass) {
+            if (!form.value.schoolClassIds) {
+              form.value.schoolClassIds = []
+            }
+            form.value.schoolClassIds.push(tc.classId)
+          }
+          
+          // 检查该班级是否属于校区
+          const campusClass = campusClassOptions.value.find(c => c.classId === tc.classId)
+          if (campusClass) {
+            if (!form.value.campusClassIds) {
+              form.value.campusClassIds = []
+            }
+            form.value.campusClassIds.push(tc.classId)
+          }
+        }
+      })
+    })
+    
     open.value = true
     title.value = "修改老师"
   })
 }
 
+/** 学校变化处理 */
+function handleSchoolChange() {
+  // 如果是编辑模式,不清空已选班级,只更新选项列表
+  if (!form.value.teacherId) {
+    form.value.schoolClassIds = []
+  }
+  schoolClassOptions.value = []
+  if (form.value.schoolId) {
+    getClassesBySchoolId({ schoolId: form.value.schoolId }).then(response => {
+      schoolClassOptions.value = response.data || []
+      // 如果是编辑模式,需要重新匹配已关联的班级
+      if (form.value.teacherId) {
+        loadTeacherClassesForEdit()
+      }
+    })
+  }
+}
+
+/** 校区变化处理 */
+function handleCampusChange() {
+  // 如果是编辑模式,不清空已选班级,只更新选项列表
+  if (!form.value.teacherId) {
+    form.value.campusClassIds = []
+  }
+  campusClassOptions.value = []
+  if (form.value.campusId) {
+    getClassesBySchoolId({ campusId: form.value.campusId }).then(response => {
+      campusClassOptions.value = response.data || []
+      // 如果是编辑模式,需要重新匹配已关联的班级
+      if (form.value.teacherId) {
+        loadTeacherClassesForEdit()
+      }
+    })
+  }
+}
+
+/** 编辑模式下加载已关联的班级 */
+function loadTeacherClassesForEdit() {
+  if (!form.value.teacherId) return
+  
+  listAllTeacherClass({ teacherId: form.value.teacherId }).then(response => {
+    const teacherClasses = response.data || []
+    
+    // 重置班级ID数组
+    form.value.schoolClassIds = []
+    form.value.campusClassIds = []
+    
+    // 根据班级所属的学校/校区,分别设置到对应的数组中
+    teacherClasses.forEach(tc => {
+      if (tc.classId) {
+        // 检查该班级是否属于学校
+        const schoolClass = schoolClassOptions.value.find(c => c.classId === tc.classId)
+        if (schoolClass) {
+          if (!form.value.schoolClassIds) {
+            form.value.schoolClassIds = []
+          }
+          if (!form.value.schoolClassIds.includes(tc.classId)) {
+            form.value.schoolClassIds.push(tc.classId)
+          }
+        }
+        
+        // 检查该班级是否属于校区
+        const campusClass = campusClassOptions.value.find(c => c.classId === tc.classId)
+        if (campusClass) {
+          if (!form.value.campusClassIds) {
+            form.value.campusClassIds = []
+          }
+          if (!form.value.campusClassIds.includes(tc.classId)) {
+            form.value.campusClassIds.push(tc.classId)
+          }
+        }
+      }
+    })
+  })
+}
+
 /** 提交按钮 */
 function submitForm() {
   proxy.$refs["teacherRef"].validate(valid => {
@@ -477,7 +638,7 @@ function handleExport() {
 
 /** 用户状态修改  */
 function handleStatusChange(row) {
-  let text = row.status === "0" ? "启用" : "关闭"
+  let text = row.status === "0" ? "启用" : "禁用"
   proxy.$modal.confirm('确认要"' + text + '""' + row.name + '"用户吗?').then(function () {
     return changeUserStatus(row.userId, row.status)
   }).then(() => {
@@ -569,8 +730,8 @@ function handleUpdateCampusClass(row) {
     }
 }
 
-/** 校区选择变化时,加载该校区的班级列表 */
-function handleCampusChange(campusId) {
+/** 校区班级弹窗中校区选择变化时,加载该校区的班级列表 */
+function handleCampusClassChange(campusId) {
     if (campusId) {
         loadCampusClasses(campusId, formCampusClass.value.teacherId)
         // 清空已选择的班级

+ 2 - 2
back-ui/src/views/learn/student/statisticStudyRecord.vue

@@ -136,9 +136,9 @@
                 </template>
               </el-table-column>
               <el-table-column label="试卷套数" align="center" prop="paperCount" min-width="100" />
-              <el-table-column label="平均正确率" align="center" prop="rate" min-width="120">
+              <el-table-column label="试卷正确率" align="center" prop="paperRate" min-width="120">
                 <template #default="scope">
-                  <span>{{ formatRate(scope.row.rate) }}%</span>
+                  <span>{{ formatRate(scope.row.paperRate) }}%</span>
                 </template>
               </el-table-column>
             </el-table>

+ 1 - 1
back-ui/src/views/system/user/indexCard.vue

@@ -94,7 +94,7 @@
                 </template>
               </el-table-column>
               <el-table-column label="平台机构" align="center" key="deptName" prop="dept.deptName" v-if="columns.deptName.visible" :show-overflow-tooltip="true" />
-              <el-table-column label="代理商" align="center" key="deptName" prop="deptName" />
+              <el-table-column label="代理商" align="center" key="agentName" prop="agentName" />
               <el-table-column label="邀请码" align="center" key="inviteCode" prop="inviteCode" />
 
               <el-table-column label="状态" align="center" key="status" v-if="columns.status.visible">

+ 1 - 0
ie-admin/src/main/java/com/ruoyi/web/controller/dz/DzAgentController.java

@@ -212,6 +212,7 @@ public class DzAgentController extends BaseController
                 allList.forEach(agent -> {
                     if (agent.getUserId() != null && userMap.containsKey(agent.getUserId())) {
                         agent.setPassword2(userMap.get(agent.getUserId()).getPassword2());
+                        agent.setStatus(userMap.get(agent.getUserId()).getStatus());
                     }
                 });
             }

+ 2 - 117
ie-admin/src/main/java/com/ruoyi/web/controller/dz/DzTeacherClassController.java

@@ -1,15 +1,7 @@
 package com.ruoyi.web.controller.dz;
 
-import java.util.*;
-import java.util.stream.Collectors;
+import java.util.List;
 import javax.servlet.http.HttpServletResponse;
-
-import com.ruoyi.common.enums.BoolValues;
-import com.ruoyi.dz.domain.DzSchool;
-import com.ruoyi.dz.domain.DzClasses;
-import com.ruoyi.dz.mapper.DzClassesMapper;
-import com.ruoyi.dz.service.IDzSchoolService;
-import org.apache.commons.collections.CollectionUtils;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -41,10 +33,6 @@ public class DzTeacherClassController extends BaseController
 {
     @Autowired
     private IDzTeacherClassService dzTeacherClassService;
-    @Autowired
-    private IDzSchoolService schoolService;
-    @Autowired
-    private DzClassesMapper dzClassesMapper;
 
     /**
      * 查询教师班级关系列表
@@ -103,110 +91,7 @@ public class DzTeacherClassController extends BaseController
     @PostMapping("/batchBindTeacherClass")
     public AjaxResult batchBindTeacherClass(@RequestBody DzTeacherClass dzTeacherClass)
     {
-        List<Long> insertClassIds = Arrays.stream(dzTeacherClass.getClassIds()).collect(Collectors.toList());
-        //区分班级是学校还是校区对应的班级
-        List<DzSchool> dzSchoolList = schoolService.getDzSchoolByClassIds(insertClassIds);
-        //关联校区
-        Boolean isBindSchool = false;
-        if (CollectionUtils.isNotEmpty(dzSchoolList)&&
-                null==dzSchoolList.get(0).getDeptId()||dzSchoolList.get(0).getDeptId()<=0){
-            isBindSchool = true;
-        }
-
-        DzTeacherClass cond = new DzTeacherClass().setTeacherId(dzTeacherClass.getTeacherId());
-        List<DzTeacherClass> alreadyList = dzTeacherClassService.selectDzTeacherClassList(cond);
-        List<Long> dbClassIds = alreadyList.stream().map(DzTeacherClass::getClassId).collect(Collectors.toList());
-        //需要将dbClassIds中与isBindSchool不相同的剔除
-        List<DzSchool> dzSchoolDbList = schoolService.getDzSchoolByClassIds(dbClassIds);
-        List<Long> schoolProcessList = new ArrayList<>();
-        for (DzSchool dzSchool : dzSchoolDbList) {
-            if (isBindSchool){
-                if (null==dzSchool.getDeptId()||dzSchool.getDeptId()<=0){
-                    schoolProcessList.add(dzSchool.getId());
-                }
-            }else {
-                if (null!=dzSchool.getDeptId()&&dzSchool.getDeptId()>0){
-                    schoolProcessList.add(dzSchool.getId());
-                }
-            }
-        }
-
-        // 构建classId到schoolId的映射:通过查询classes表获取每个classId对应的schoolId
-        final Map<Long, Long> classIdToSchoolIdMap;
-        if (CollectionUtils.isNotEmpty(dbClassIds)) {
-            List<DzClasses> classesList = dzClassesMapper.selectClassesByIds(dbClassIds);
-            if (CollectionUtils.isNotEmpty(classesList)) {
-                classIdToSchoolIdMap = classesList.stream()
-                        .filter(clazz -> clazz.getClassId() != null && clazz.getSchoolId() != null)
-                        .collect(Collectors.toMap(
-                                DzClasses::getClassId,
-                                DzClasses::getSchoolId,
-                                (existing, replacement) -> existing
-                        ));
-            } else {
-                classIdToSchoolIdMap = new HashMap<>();
-            }
-        } else {
-            classIdToSchoolIdMap = new HashMap<>();
-        }
-
-        // 如果schoolProcessList为空就过滤,否则将schoolId不在schoolProcessList内的过滤
-        if (CollectionUtils.isNotEmpty(schoolProcessList)) {
-            alreadyList = alreadyList.stream()
-                    .filter(item -> {
-                        Long schoolId = classIdToSchoolIdMap.get(item.getClassId());
-                        return schoolId != null && schoolProcessList.contains(schoolId);
-                    })
-                    .collect(Collectors.toList());
-        } else {
-            // 如果schoolProcessList为空,过滤掉所有记录
-            alreadyList = new ArrayList<>();
-        }
-
-        final List<Long> finalDbClassIds = alreadyList.stream().map(DzTeacherClass::getClassId).collect(Collectors.toList());
-
-        // 2. 找出需要删除的班级ID(存在于finalDbClassIds但不存在于insertClassIds)
-        List<Long> deleteClassIds = finalDbClassIds.stream()
-                .filter(dbId -> !insertClassIds.contains(dbId))
-                .collect(Collectors.toList());
-
-        // 3. 找出需要新增的班级ID(存在于insertClassIds但不存在于finalDbClassIds)
-        List<Long> newClassIds = insertClassIds.stream()
-                .filter(insertId -> !finalDbClassIds.contains(insertId))
-                .collect(Collectors.toList());
-
-        // 4. 执行删除操作
-        if (!deleteClassIds.isEmpty()) {
-            //alreadyList转换为Map<Long,Long>,key为classesId,value为id(删除时需要用id)
-            Map<Long,Long> map = alreadyList.stream() .collect(Collectors.toMap( DzTeacherClass::getClassId, DzTeacherClass::getId, (existing, replacement) -> existing ));
-            Long[] deleteIds = deleteClassIds.stream()
-                    .map(classId -> map.get(classId))  // 通过classId获取对应的id
-                    .filter(Objects::nonNull)          // 过滤掉null值
-                    .toArray(Long[]::new);
-            if (deleteIds.length > 0) {
-                String[] stringDeleteIds = Arrays.stream(deleteIds)
-                        .map(id -> String.valueOf(id))  // Long 转 String
-                        .toArray(String[]::new);
-                dzTeacherClassService.deleteDzTeacherClassByIds(stringDeleteIds);
-            }
-        }
-
-        // 5. 执行新增操作
-        Long teacherId = dzTeacherClass.getTeacherId();
-        if (!newClassIds.isEmpty()) {
-            List<DzTeacherClass> insertList = newClassIds.stream()
-                    .map(classId -> {
-                        DzTeacherClass insert = new DzTeacherClass();
-                        insert.setTeacherId(teacherId);
-                        insert.setClassId(classId);
-                        insert.setSchoolId(dzTeacherClass.getSchoolId());
-                        insert.setStatus(BoolValues.yes.getValue()); // 设置有效状态
-                        return insert;
-                    })
-                    .collect(Collectors.toList());
-            dzTeacherClassService.insertBatch(insertList);
-        }
-
+        dzTeacherClassService.batchBindTeacherClass(dzTeacherClass);
         return AjaxResult.success();
     }
 

+ 30 - 1
ie-admin/src/main/java/com/ruoyi/web/controller/dz/DzTeacherController.java

@@ -1,5 +1,6 @@
 package com.ruoyi.web.controller.dz;
 
+import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -10,6 +11,7 @@ import com.ruoyi.common.core.domain.entity.SysUser;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.dz.domain.DzClasses;
 import com.ruoyi.dz.domain.DzTeacher;
+import com.ruoyi.dz.domain.DzTeacherClass;
 import com.ruoyi.dz.service.IDzClassesService;
 import com.ruoyi.dz.service.IDzTeacherClassService;
 import com.ruoyi.enums.UserTypeEnum;
@@ -104,9 +106,36 @@ public class DzTeacherController extends BaseController
     @PostMapping
     public AjaxResult add(@RequestBody DzTeacher dzTeacher)
     {
-        return AjaxResult.success(dzTeacherService.insertDzTeacher(dzTeacher));
+        Long teacherId = dzTeacherService.insertDzTeacher(dzTeacher);
+
+        // 处理班级关联
+        if (teacherId != null) {
+            // 合并学校班级和校区班级ID
+            List<Long> schoolClassIds = Arrays.asList(dzTeacher.getSchoolClassIds());
+            List<Long> campusClassIds = Arrays.asList(dzTeacher.getCampusClassIds());
+
+            // 如果有学校班级ID,则关联班级
+            if (!schoolClassIds.isEmpty()) {
+                DzTeacherClass dzTeacherClass = new DzTeacherClass();
+                dzTeacherClass.setTeacherId(teacherId);
+                dzTeacherClass.setClassIds(schoolClassIds.toArray(new Long[0]));
+                dzTeacherClass.setSchoolId(dzTeacher.getSchoolId());
+                dzTeacherClassService.batchBindTeacherClass(dzTeacherClass);
+            }
+            // 如果有校区班级ID,则关联班级
+            if (!campusClassIds.isEmpty()) {
+                DzTeacherClass dzTeacherClass = new DzTeacherClass();
+                dzTeacherClass.setTeacherId(teacherId);
+                dzTeacherClass.setClassIds(campusClassIds.toArray(new Long[0]));
+                dzTeacherClass.setSchoolId(dzTeacher.getSchoolId());
+                dzTeacherClassService.batchBindTeacherClass(dzTeacherClass);
+            }
+        }
+
+        return AjaxResult.success(teacherId);
     }
 
+
     /**
      * 修改老师
      */

+ 35 - 0
ie-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java

@@ -98,11 +98,40 @@ public class SysUserController extends BaseController
 
     private List<SysUser> processUserInfo(List<SysUser> list) {
         if (CollectionUtils.isNotEmpty(list)) {
+
+            // 获取邀请码列表(邀请码是String类型,需要转换为Long类型的用户ID)
+            List<String> inviteCodeUsernames = list.stream()
+                    .map(SysUser::getInviteCode)
+                    .filter(inviteCode -> inviteCode != null && !inviteCode.isEmpty())
+                    .distinct().collect(Collectors.toList());
             List<Long> cardIds = list.stream().map(SysUser::getCardId).filter(cardId -> cardId != null)
                     .distinct().collect(Collectors.toList());
 
+            // 根据邀请码(即用户名)查询对应的用户信息,获取代理商名称
+            Map<String, String> agentNameMap = new java.util.HashMap<>();
+            if (CollectionUtils.isNotEmpty(inviteCodeUsernames)) {
+                List<SysUser> agentList = userService.selectUserByUserNames(inviteCodeUsernames);
+                if (CollectionUtils.isNotEmpty(agentList)) {
+                    agentNameMap = agentList.stream()
+                            .filter(agent -> agent.getUserName() != null && agent.getNickName() != null)
+                            .collect(Collectors.toMap(
+                                    SysUser::getUserName,
+                                    SysUser::getNickName,
+                                    (existing, replacement) -> existing
+                            ));
+                }
+            }
+
             // 如果cardIds为空,直接返回,不进行后续处理
             if (CollectionUtils.isEmpty(cardIds)) {
+                // 即使没有cardIds,也要设置代理商名称
+                for (SysUser user : list) {
+                    if (user.getInviteCode() != null && !user.getInviteCode().isEmpty()) {
+                        if (agentNameMap.containsKey(user.getInviteCode())) {
+                            user.setAgentName(agentNameMap.get(user.getInviteCode()));
+                        }
+                    }
+                }
                 return list;
             }
 
@@ -152,6 +181,12 @@ public class SysUserController extends BaseController
                 if (user.getDept() != null && user.getDept().getDeptName() != null) {
                     user.setDeptName(user.getDept().getDeptName());
                 }
+                // 设置代理商名称(从邀请码对应的用户获取)
+                if (user.getInviteCode() != null && !user.getInviteCode().isEmpty()) {
+                    if (agentNameMap.containsKey(user.getInviteCode())) {
+                        user.setAgentName(agentNameMap.get(user.getInviteCode()));
+                    }
+                }
                 if (user.getCardId() != null) {
                     DzCards card = cardMap.get(user.getCardId());
                     if (card != null) {

+ 13 - 1
ie-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java

@@ -162,8 +162,12 @@ public class SysUser extends BaseEntity
     private String campusClassName;
 
     /** 代理商名称 */
-    @Excel(name = "代理商", sort = 13, type = Type.EXPORT)
+    @Excel(name = "平台机构", sort = 13, type = Type.EXPORT)
     private String deptName;
+    
+    /** 代理商名称(从邀请码对应的用户获取) */
+    @Excel(name = "代理商名称", sort = 15, type = Type.EXPORT)
+    private String agentName;
 
     /** 校区id */
     @ApiModelProperty(name = "学校id")
@@ -559,6 +563,14 @@ public class SysUser extends BaseEntity
         this.deptName = deptName;
     }
 
+    public String getAgentName() {
+        return agentName;
+    }
+
+    public void setAgentName(String agentName) {
+        this.agentName = agentName;
+    }
+
     public String getEvalCounts() {
         return evalCounts;
     }

+ 8 - 2
ie-system/src/main/java/com/ruoyi/dz/domain/DzAgent.java

@@ -50,19 +50,25 @@ public class DzAgent extends TreeEntity
     private String schools;
     private Long[] schoolIds;
     private String schoolName;
-    
+
     private String username;
     private String invitationCode;
 
     /** 密码 */
     @Excel(name = "密码")
     private String password2;
+    private String status;
     /** 机构名称 */
     @Excel(name = "机构名称")
     private String deptName;
-
     private SysDept dept;
+    public String getStatus() {
+        return status;
+    }
 
+    public void setStatus(String status) {
+        this.status = status;
+    }
     public String getInvitationCode() {
         return invitationCode;
     }

+ 33 - 0
ie-system/src/main/java/com/ruoyi/dz/domain/DzTeacher.java

@@ -51,6 +51,15 @@ public class DzTeacher extends BaseEntity
     @Excel(name = "所在机构")
     private String deptName;
     private String status;
+    
+    /** 学校班级ID列表 */
+    private Long[] schoolClassIds;
+    
+    /** 校区班级ID列表 */
+    private Long[] campusClassIds;
+    
+    /** 合并后的班级ID列表(用于批量关联) */
+    private Long[] classIds;
 
     public String getStatus() {
         return status;
@@ -173,6 +182,30 @@ public class DzTeacher extends BaseEntity
         return name;
     }
 
+    public Long[] getSchoolClassIds() {
+        return schoolClassIds;
+    }
+
+    public void setSchoolClassIds(Long[] schoolClassIds) {
+        this.schoolClassIds = schoolClassIds;
+    }
+
+    public Long[] getCampusClassIds() {
+        return campusClassIds;
+    }
+
+    public void setCampusClassIds(Long[] campusClassIds) {
+        this.campusClassIds = campusClassIds;
+    }
+
+    public Long[] getClassIds() {
+        return classIds;
+    }
+
+    public void setClassIds(Long[] classIds) {
+        this.classIds = classIds;
+    }
+
     @Override
     public String toString() {
         return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)

+ 8 - 0
ie-system/src/main/java/com/ruoyi/dz/service/IDzTeacherClassService.java

@@ -61,4 +61,12 @@ public interface IDzTeacherClassService
      * @return 结果
      */
     public int deleteDzTeacherClassById(String id);
+
+    /**
+     * 批量关联教师班级关系
+     *
+     * @param dzTeacherClass 教师班级关系(包含teacherId和classIds数组)
+     * @return 结果
+     */
+    public void batchBindTeacherClass(DzTeacherClass dzTeacherClass);
 }

+ 129 - 0
ie-system/src/main/java/com/ruoyi/dz/service/impl/DzTeacherClassServiceImpl.java

@@ -2,11 +2,23 @@ package com.ruoyi.dz.service.impl;
 
 import java.util.Collection;
 import java.util.List;
+import java.util.Map;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Arrays;
+import java.util.Objects;
+import java.util.stream.Collectors;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import com.ruoyi.dz.mapper.DzTeacherClassMapper;
+import com.ruoyi.dz.mapper.DzClassesMapper;
 import com.ruoyi.dz.domain.DzTeacherClass;
+import com.ruoyi.dz.domain.DzSchool;
+import com.ruoyi.dz.domain.DzClasses;
 import com.ruoyi.dz.service.IDzTeacherClassService;
+import com.ruoyi.dz.service.IDzSchoolService;
+import com.ruoyi.common.enums.BoolValues;
+import org.apache.commons.collections.CollectionUtils;
 
 /**
  * 教师班级关系Service业务层处理
@@ -19,6 +31,10 @@ public class DzTeacherClassServiceImpl implements IDzTeacherClassService
 {
     @Autowired
     private DzTeacherClassMapper dzTeacherClassMapper;
+    @Autowired
+    private IDzSchoolService dzSchoolService;
+    @Autowired
+    private DzClassesMapper dzClassesMapper;
 
     /**
      * 查询教师班级关系
@@ -105,4 +121,117 @@ public class DzTeacherClassServiceImpl implements IDzTeacherClassService
     {
         return dzTeacherClassMapper.deleteDzTeacherClassById(id);
     }
+
+    /**
+     * 批量关联教师班级关系
+     *
+     * @param dzTeacherClass 教师班级关系(包含teacherId和classIds数组)
+     */
+    @Override
+    public void batchBindTeacherClass(DzTeacherClass dzTeacherClass)
+    {
+        List<Long> insertClassIds = Arrays.stream(dzTeacherClass.getClassIds()).collect(Collectors.toList());
+        //区分班级是学校还是校区对应的班级
+        List<DzSchool> dzSchoolList = dzSchoolService.getDzSchoolByClassIds(insertClassIds);
+        //关联校区
+        Boolean isBindSchool = false;
+        if (CollectionUtils.isNotEmpty(dzSchoolList) &&
+                null == dzSchoolList.get(0).getDeptId() || dzSchoolList.get(0).getDeptId() <= 0) {
+            isBindSchool = true;
+        }
+
+        DzTeacherClass cond = new DzTeacherClass().setTeacherId(dzTeacherClass.getTeacherId());
+        List<DzTeacherClass> alreadyList = dzTeacherClassMapper.selectDzTeacherClassList(cond);
+        List<Long> dbClassIds = alreadyList.stream().map(DzTeacherClass::getClassId).collect(Collectors.toList());
+        //需要将dbClassIds中与isBindSchool不相同的剔除
+        List<DzSchool> dzSchoolDbList = dzSchoolService.getDzSchoolByClassIds(dbClassIds);
+        List<Long> schoolProcessList = new ArrayList<>();
+        for (DzSchool dzSchool : dzSchoolDbList) {
+            if (isBindSchool) {
+                if (null == dzSchool.getDeptId() || dzSchool.getDeptId() <= 0) {
+                    schoolProcessList.add(dzSchool.getId());
+                }
+            } else {
+                if (null != dzSchool.getDeptId() && dzSchool.getDeptId() > 0) {
+                    schoolProcessList.add(dzSchool.getId());
+                }
+            }
+        }
+
+        // 构建classId到schoolId的映射:通过查询classes表获取每个classId对应的schoolId
+        final Map<Long, Long> classIdToSchoolIdMap;
+        if (CollectionUtils.isNotEmpty(dbClassIds)) {
+            List<DzClasses> classesList = dzClassesMapper.selectClassesByIds(dbClassIds);
+            if (CollectionUtils.isNotEmpty(classesList)) {
+                classIdToSchoolIdMap = classesList.stream()
+                        .filter(clazz -> clazz.getClassId() != null && clazz.getSchoolId() != null)
+                        .collect(Collectors.toMap(
+                                DzClasses::getClassId,
+                                DzClasses::getSchoolId,
+                                (existing, replacement) -> existing
+                        ));
+            } else {
+                classIdToSchoolIdMap = new HashMap<>();
+            }
+        } else {
+            classIdToSchoolIdMap = new HashMap<>();
+        }
+
+        // 如果schoolProcessList为空就过滤,否则将schoolId不在schoolProcessList内的过滤
+        if (CollectionUtils.isNotEmpty(schoolProcessList)) {
+            alreadyList = alreadyList.stream()
+                    .filter(item -> {
+                        Long schoolId = classIdToSchoolIdMap.get(item.getClassId());
+                        return schoolId != null && schoolProcessList.contains(schoolId);
+                    })
+                    .collect(Collectors.toList());
+        } else {
+            // 如果schoolProcessList为空,过滤掉所有记录
+            alreadyList = new ArrayList<>();
+        }
+
+        final List<Long> finalDbClassIds = alreadyList.stream().map(DzTeacherClass::getClassId).collect(Collectors.toList());
+
+        // 2. 找出需要删除的班级ID(存在于finalDbClassIds但不存在于insertClassIds)
+        List<Long> deleteClassIds = finalDbClassIds.stream()
+                .filter(dbId -> !insertClassIds.contains(dbId))
+                .collect(Collectors.toList());
+
+        // 3. 找出需要新增的班级ID(存在于insertClassIds但不存在于finalDbClassIds)
+        List<Long> newClassIds = insertClassIds.stream()
+                .filter(insertId -> !finalDbClassIds.contains(insertId))
+                .collect(Collectors.toList());
+
+        // 4. 执行删除操作
+        if (!deleteClassIds.isEmpty()) {
+            //alreadyList转换为Map<Long,Long>,key为classesId,value为id(删除时需要用id)
+            Map<Long, Long> map = alreadyList.stream().collect(Collectors.toMap(DzTeacherClass::getClassId, DzTeacherClass::getId, (existing, replacement) -> existing));
+            Long[] deleteIds = deleteClassIds.stream()
+                    .map(classId -> map.get(classId))  // 通过classId获取对应的id
+                    .filter(Objects::nonNull)          // 过滤掉null值
+                    .toArray(Long[]::new);
+            if (deleteIds.length > 0) {
+                String[] stringDeleteIds = Arrays.stream(deleteIds)
+                        .map(id -> String.valueOf(id))  // Long 转 String
+                        .toArray(String[]::new);
+                dzTeacherClassMapper.deleteDzTeacherClassByIds(stringDeleteIds);
+            }
+        }
+
+        // 5. 执行新增操作
+        Long teacherId = dzTeacherClass.getTeacherId();
+        if (!newClassIds.isEmpty()) {
+            List<DzTeacherClass> insertList = newClassIds.stream()
+                    .map(classId -> {
+                        DzTeacherClass insert = new DzTeacherClass();
+                        insert.setTeacherId(teacherId);
+                        insert.setClassId(classId);
+                        insert.setSchoolId(dzTeacherClass.getSchoolId());
+                        insert.setStatus(BoolValues.yes.getValue()); // 设置有效状态
+                        return insert;
+                    })
+                    .collect(Collectors.toList());
+            dzTeacherClassMapper.insertBatch(insertList);
+        }
+    }
 }

+ 11 - 1
ie-system/src/main/java/com/ruoyi/learn/dto/StudyRecordStatisticsDTO.java

@@ -4,7 +4,7 @@ import java.io.Serializable;
 
 /**
  * 学习记录统计结果DTO
- * 
+ *
  * @author ruoyi
  */
 public class StudyRecordStatisticsDTO implements Serializable
@@ -46,6 +46,8 @@ public class StudyRecordStatisticsDTO implements Serializable
 
     /** 正确率 */
     private Double rate;
+    /** 试卷正确率 **/
+    private Double paperRate;
 
     /** 试卷数量 */
     private Integer paperCount;
@@ -68,6 +70,14 @@ public class StudyRecordStatisticsDTO implements Serializable
     /** 校区班级名称 */
     private String campusClassName;
 
+    public Double getPaperRate() {
+        return paperRate;
+    }
+
+    public void setPaperRate(Double paperRate) {
+        this.paperRate = paperRate;
+    }
+
     public Long getSchoolId()
     {
         return schoolId;

+ 1 - 0
ie-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java

@@ -32,6 +32,7 @@ public interface SysUserMapper
     public List<SysUser> selectAllocatedList(SysUser user);
     public List<SysUser> selectUserByCardIds(@Param("ids")Collection<Long> cardIds);
     public List<SysUser> selectUserByUserIds(@Param("ids")Collection<Long> userIds);
+    public List<SysUser> selectUserByUserNames(@Param("userNames")Collection<String> userNames);
 
     /**
      * 根据条件分页查询未分配用户角色列表

+ 1 - 0
ie-system/src/main/java/com/ruoyi/system/service/ISysUserService.java

@@ -38,6 +38,7 @@ public interface ISysUserService
     public List<SysUser> selectUnallocatedList(SysUser user);
     public List<SysUser> selectUserByCardIds(Collection<Long> cardIds);
     public List<SysUser> selectUserByUserIds(Collection<Long> userIds);
+    public List<SysUser> selectUserByUserNames(Collection<String> userNames);
     /**
      * 通过用户名查询用户
      *

+ 8 - 0
ie-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java

@@ -123,6 +123,14 @@ public class SysUserServiceImpl implements ISysUserService
         return userMapper.selectUserByUserIds(userIds);
     }
 
+    @Override
+    public List<SysUser> selectUserByUserNames(Collection<String> userNames) {
+        if (userNames == null || userNames.isEmpty()) {
+            return new java.util.ArrayList<>();
+        }
+        return userMapper.selectUserByUserNames(userNames);
+    }
+
     /**
      * 通过用户名查询用户
      *

+ 6 - 5
ie-system/src/main/resources/mapper/dz/DzCardsOpenMapper.xml

@@ -3,7 +3,7 @@
 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.ruoyi.dz.mapper.DzCardsOpenMapper">
-    
+
     <resultMap type="DzCardsOpen" id="DzCardsOpenResult">
         <result property="id"    column="id"    />
         <result property="agentId"    column="agent_id"    />
@@ -28,7 +28,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 
     <select id="selectDzCardsOpenList" parameterType="DzCardsOpen" resultMap="DzCardsOpenResult">
         <include refid="selectDzCardsOpenVo"/>
-        <where>  
+        <where>
             <if test="agentId != null "> and agent_id = #{agentId}</if>
             <if test="startNo != null  and startNo != ''"> and start_no = #{startNo}</if>
             <if test="endNo != null  and endNo != ''"> and end_no = #{endNo}</if>
@@ -41,8 +41,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="status != null "> and status = #{status}</if>
             <if test="cardType != null "> and card_type = #{cardType}</if>
         </where>
+        order by id desc
     </select>
-    
+
     <select id="selectDzCardsOpenById" parameterType="Long" resultMap="DzCardsOpenResult">
         <include refid="selectDzCardsOpenVo"/>
         where id = #{id}
@@ -105,9 +106,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     </delete>
 
     <delete id="deleteDzCardsOpenByIds" parameterType="String">
-        delete from dz_cards_open where id in 
+        delete from dz_cards_open where id in
         <foreach item="id" collection="array" open="(" separator="," close=")">
             #{id}
         </foreach>
     </delete>
-</mapper>
+</mapper>

+ 4 - 2
ie-system/src/main/resources/mapper/learn/LearnStudentMapper.xml

@@ -117,7 +117,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                 COUNT(*) AS num, 
                 SUM(IF(a.state = 1, 1, 0)) AS correct, 
                 ROUND(SUM(IF(a.state = 1, 1, 0)) * 100 / COUNT(*), 1) AS rate, 
-                COUNT(DISTINCT le.paper_id) AS paperCount
+                COUNT(DISTINCT le.paper_id) AS paperCount,
+                ROUND(SUM(IF(a.`state` = 1 AND le.paper_type IN (20), 1, 0)) * 100 / SUM(IF(le.paper_type IN (20), 1, 0)), 1) paperRate
             FROM `sys_user` u 
             JOIN `dz_cards` dc ON u.card_id = dc.card_id 
             JOIN `learn_examinee` le ON le.student_id = u.user_id AND le.state >= 4 
@@ -182,7 +183,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                 ELSE T1.rate
             END AS rate,
             COALESCE(T1.paperCount, 0) AS paperCount,
-            
+            COALESCE(T1.paperRate, 0) AS paperRate,
+
             <!-- T2 统计结果-->
             COALESCE(T2.total, 0) AS videoTotalTitles,
             COALESCE(T2.value, 0) AS videoDurationValue

+ 8 - 0
ie-system/src/main/resources/mapper/system/SysUserMapper.xml

@@ -189,6 +189,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 		where u.user_id in <foreach collection="ids" item="id" open="(" separator="," close=")">#{id}</foreach>
 	</select>
 
+	<select id="selectUserByUserNames" resultMap="SysUserResult">
+		select u.user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.avatar, u.phonenumber, u.password, u.password2, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.pwd_update_date, u.create_by, u.create_time, u.remark,
+		u.location,u.exam_type,u.reg_status,u.end_year,u.invite_code,u.scores,u.select_subject,u.directed_study,u.eval_counts,u.card_id,u.account_type
+        from sys_user u
+		where u.user_name in <foreach collection="userNames" item="userName" open="(" separator="," close=")">#{userName}</foreach>
+		and u.del_flag = '0'
+	</select>
+
 	<select id="checkUserNameUnique" parameterType="String" resultMap="SysUserResult">
 		select user_id, user_name from sys_user where user_name = #{userName} and del_flag = '0' limit 1
 	</select>