From 6459f8bff3e568e65e6dc617f22c686cf5a8db44 Mon Sep 17 00:00:00 2001
From: zhouwx <1175765986@qq.com>
Date: 星期一, 15 七月 2024 16:35:06 +0800
Subject: [PATCH] 组卷

---
 src/views/onlineEducation/groupExams/components/examDialog.vue          |  140 +++++++--
 src/views/onlineEducation/classHourBatch/index.vue                      |    6 
 src/views/onlineEducation/offlineEducation/components/recordDialog.vue  |    1 
 src/views/onlineEducation/groupExams/components/examChooseStudent.vue   |  248 +++++++++++++++++
 package.json                                                            |    1 
 src/views/onlineEducation/groupExams/components/student.vue             |  184 +++++++++++++
 src/views/onlineEducation/systemManage/company/index.vue                |    9 
 src/views/onlineEducation/count/index.vue                               |   90 +++++-
 src/views/onlineEducation/groupExams/index.vue                          |   37 ++
 src/router/index.js                                                     |   13 
 src/api/onlineEducation/exam.js                                         |   82 ++--
 src/views/onlineEducation/classHourBatch/components/classHourChange.vue |   16 
 12 files changed, 711 insertions(+), 116 deletions(-)

diff --git a/package.json b/package.json
index ad42e19..296e942 100644
--- a/package.json
+++ b/package.json
@@ -30,6 +30,7 @@
     "js-base64": "^3.7.5",
     "js-cookie": "3.0.1",
     "jsencrypt": "3.3.1",
+    "moment": "^2.30.1",
     "nprogress": "0.2.0",
     "p-limit": "^5.0.0",
     "pinia": "2.0.22",
diff --git a/src/api/onlineEducation/exam.js b/src/api/onlineEducation/exam.js
index 3292d01..2eddade 100644
--- a/src/api/onlineEducation/exam.js
+++ b/src/api/onlineEducation/exam.js
@@ -41,47 +41,47 @@
     })
 }
 
-//批次与学员关系
-//批次下的学员列表(分页)
-// export function getBatchStudent(param) {
-//     return request({
-//         url: '/phase-student/list',
-//         method: 'get',
-//         params: param
-//     })
-// }
-// // 校验学员是否已存在
-// export function checkStudentUnique(data) {
-//     return request({
-//         url: '/phase-student/checkStudentUnique',
-//         method: 'post',
-//         data: data
-//     })
-// }
-// // 批量新增学员
-// export function batchAddStudent(data) {
-//     return request({
-//         url: '/phase-student/batchAdd',
-//         method: 'post',
-//         data: data
-//     })
-// }
-// // 批量删除学员
-// export function batchDelStudent(data) {
-//     return request({
-//         url: '/phase-student/batchDelete',
-//         method: 'delete',
-//         data: data
-//     })
-// }
-//
-// // 批量删除学员
-// export function delBatchStu(userId) {
-//     return request({
-//         url: '/phase-student/' + userId,
-//         method: 'delete'
-//     })
-// }
+//试卷与学员关系
+//试卷下的学员列表(分页)
+export function getExamStudent(param) {
+    return request({
+        url: '/paper-student/list',
+        method: 'get',
+        params: param
+    })
+}
+// 校验学员是否已存在
+export function checkExamStudentUnique(data) {
+    return request({
+        url: '/paper-student/checkStudentUnique',
+        method: 'post',
+        data: data
+    })
+}
+ // 批量新增学员
+export function examAddStudent(data) {
+    return request({
+        url: '/paper-student/batchAdd',
+        method: 'post',
+        data: data
+    })
+}
+ // 批量删除学员
+export function examDelStudent(data) {
+    return request({
+        url: '/paper-student/batchDelete',
+        method: 'delete',
+        data: data
+    })
+}
+
+ // 删除学员
+export function delExamStu(userId) {
+    return request({
+        url: '/paper-student/' + userId,
+        method: 'delete'
+    })
+}
 //
 // //企业课时变更记录列表(分页)
 // export function getCompanyPeriod(param) {
diff --git a/src/router/index.js b/src/router/index.js
index b5e29b4..0856c65 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -79,6 +79,19 @@
       }
     ]
   },
+  {
+    path: '/examStu',
+    component: Layout,
+    redirect: '/examStu',
+    children: [
+      {
+        path: '/examStu',
+        component: () => import('@/views/onlineEducation/groupExams/components/student.vue'),
+        name: 'ExamStu',
+        meta: { title: '考试学员',icon: 'form',  affix: true }
+      }
+    ]
+  },
   // {
   //   path: '',
   //   component: Layout,
diff --git a/src/views/onlineEducation/classHourBatch/components/classHourChange.vue b/src/views/onlineEducation/classHourBatch/components/classHourChange.vue
index 51d6e63..8d2c5fe 100644
--- a/src/views/onlineEducation/classHourBatch/components/classHourChange.vue
+++ b/src/views/onlineEducation/classHourBatch/components/classHourChange.vue
@@ -9,8 +9,8 @@
       <el-table v-loading="state.loading" :data="state.dataList" :border="true">
         <el-table-column label="创建时间" prop="createTime" align="center"  width="180" />
         <el-table-column label="变动来源" prop="origin" align="center"  />
-        <el-table-column label="变动情况" prop="modifyPeriod" align="center"  />
-        <el-table-column label="变动后剩余(分)" prop="remainPeriod" align="center"  />
+        <el-table-column label="变动情况" prop="modifyPeriodMin" align="center"  />
+        <el-table-column label="变动后剩余" prop="remainPeriodMin" align="center"  />
 <!--        <el-table-column label="操作" align="center" class-name="small-padding fixed-width"  width="180">-->
 <!--          <template #default="scope">-->
 <!--            <el-button link type="danger" @click="handleDelete(scope.row)">删除</el-button>-->
@@ -54,7 +54,8 @@
   dataList: [],
   queryParams: {
     pageNum: 1,
-    pageSize: 10
+    pageSize: 10,
+    companyId: null
   },
   total: 0,
   title: ''
@@ -63,13 +64,20 @@
 const openDialog = async (value) => {
   state.title = '课时余量变动明细'
   dialogVisible.value = true;
+  state.queryParams.companyId = value
   await getList()
 }
 const getList = async () => {
   state.loading = true
   const res = await getCompanyPeriod(state.queryParams)
   if(res.code == 200){
-    state.dataList = res.data.list
+    state.dataList = res.data.list.map(item => {
+      return {
+        ...item,
+        modifyPeriodMin: item.modifyPeriod ? (item.modifyPeriod /60).toFixed(2).replace(/\.00$/, '')+'分钟' : '',
+        remainPeriodMin: item.remainPeriod ? (item.remainPeriod  /60).toFixed(2).replace(/\.00$/, '')+'分钟' : ''
+      }
+    })
     state.total = res.data.total
   }else{
     ElMessage.warning(res.message)
diff --git a/src/views/onlineEducation/classHourBatch/index.vue b/src/views/onlineEducation/classHourBatch/index.vue
index af6dc53..13380d4 100644
--- a/src/views/onlineEducation/classHourBatch/index.vue
+++ b/src/views/onlineEducation/classHourBatch/index.vue
@@ -74,7 +74,8 @@
   dataList: [],
   isAdmin: false,
   companyName: '',
-  remainPeriod: null
+  remainPeriod: null,
+  companyId: null
 
 });
 
@@ -89,6 +90,7 @@
     data.remainPeriod = userInfo.remainPeriod ? (userInfo.remainPeriod /60).toFixed(2).replace(/\.00$/, ''):''
     data.isAdmin = false;
     data.companyName = userInfo.companyName
+    data.companyId = userInfo.companyId
   }
   await getList()
 })
@@ -146,6 +148,6 @@
 }
 
 const openDetail = () => {
-  classHourRef.value.openDialog()
+  classHourRef.value.openDialog(data.companyId)
 }
 </script>
diff --git a/src/views/onlineEducation/count/index.vue b/src/views/onlineEducation/count/index.vue
index 3146e79..31bc89f 100644
--- a/src/views/onlineEducation/count/index.vue
+++ b/src/views/onlineEducation/count/index.vue
@@ -1,8 +1,8 @@
 <template>
   <div class="app-container">
     <div style="margin-bottom: 10px">
-      <el-form style="display: flex">
-        <el-form-item label="企业:">
+      <el-form style="display: flex;flex-wrap: wrap">
+        <el-form-item label="企业:" v-if="state.isAdmin">
           <el-select
               v-model="state.queryParams.companyId"
               style="width: 100%"
@@ -27,7 +27,7 @@
               range-separator="至"
               start-placeholder="开始日期"
               end-placeholder="结束日期"
-              value-format="YYYY-MM-DD 00:00:00"
+              format="YYYY-MM-DD"
           />
         </el-form-item>
         <el-form-item  style="margin-left: 50px">
@@ -47,15 +47,31 @@
     <!-- 表格数据 -->
     <el-table v-loading="loading" :data="state.dataList" :border="true" row-key="id">
       <el-table-column label="序号" type="index" align="center" width="80" />
-      <el-table-column label="企业名称" prop="sort" align="center" />
-      <el-table-column label="企业编号" prop="sort" align="center" width="80" />
-      <el-table-column label="总批次/人数" prop="sort" align="center" width="80" />
-      <el-table-column label="三级" prop="sort" align="center" width="80" />
-      <el-table-column label="二级" prop="sort" align="center" width="80" />
-      <el-table-column label="一级" prop="sort" align="center" width="80" />
-      <el-table-column label="考试人次" prop="sort" align="center" width="80" />
-      <el-table-column label="合格人次" prop="sort" align="center" width="80" />
-      <el-table-column label="考试合格率" prop="sort" align="center" width="80" />
+      <el-table-column label="企业名称" prop="companyName" align="center" />
+      <el-table-column label="企业编号" prop="companyCode" align="center" />
+      <el-table-column label="总批次/人数" prop="sort" align="center"  >
+        <template #default="scope">
+          <span>{{scope.row.phaseStudentCount && scope.row.phaseCount ? scope.row.phaseCount + '/' +scope.row.phaseStudentCount:''}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="三级" prop="sort" align="center" >
+        <template #default="scope">
+          <span>{{scope.row.level3StudentCount && scope.row.level3PhaseCount ? scope.row.level3PhaseCount+ '/' +scope.row.level3StudentCount:''}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="二级" prop="sort" align="center" >
+        <template #default="scope">
+          <span>{{scope.row.level2StudentCount && scope.row.level2PhaseCount ? scope.row.level2PhaseCount+ '/' +scope.row.level2StudentCount:''}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="一级" prop="sort" align="center"  >
+        <template #default="scope">
+          <span>{{scope.row.level1StudentCount && scope.row.level1PhaseCount ? scope.row.level1PhaseCount+ '/' +scope.row.level1StudentCount:''}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="考试人次" prop="paperStudentCount" align="center"  />
+      <el-table-column label="合格人次" prop="passStudentCount" align="center"  />
+      <el-table-column label="合格率" prop="passRate" align="center"  />
     </el-table>
     <pagination
         v-show="state.total > 0"
@@ -71,10 +87,12 @@
 <script setup>
 import {getCurrentInstance, onMounted, reactive, ref, toRefs} from "vue";
 import {ElMessage, ElMessageBox} from "element-plus";
+import moment from "moment";
 
 import {delClassification, getClassification} from "@/api/onlineEducation/courseClass";
 import {getCompany} from "@/api/onlineEducation/company";
 import {getCompanyCount} from "@/api/onlineEducation/count";
+import Cookies from "js-cookie";
 const { proxy } = getCurrentInstance();
 const loading = ref(false);
 const areaRef = ref();
@@ -94,11 +112,19 @@
   companyList: [],
   pageNum: 1,
   pageSize: 10,
+  isAdmin: false
 });
 
 //页面加载
 onMounted(() => {
-  getCompanyList();
+  setDate();
+  const userInfo = JSON.parse(Cookies.get('userInfo'))
+  console.log("userInfo",userInfo)
+  state.isAdmin = userInfo.userType === 0;
+  if(state.isAdmin){
+    getCompanyList();
+  }
+
   getList();
 
 });
@@ -106,7 +132,14 @@
   loading.value = true;
   const res = await getCompanyCount(state.queryParams);
   if(res.code === 200){
-    state.dataList = res.data
+    state.dataList = res.data.list.map(item => {
+      return {
+        ...item,
+        passRate: item.passStudentCount!=null && item.paperStudentCount!=null ? (item.passStudentCount / item.paperStudentCount).toFixed(2) *100 + '%': ''
+
+      }
+    })
+    state.total = res.data.total
   }else{
     ElMessage.warning(res.message)
   }
@@ -150,23 +183,44 @@
     getCompanyList('')
   }, 500)
 }
+const setDate = () => {
+  let isDate = new Date()
+  let sTime = `${isDate.getFullYear()}-${isDate.getMonth() + 1}-${isDate.getDate()-7}`
+  let eTime = `${isDate.getFullYear()}-${isDate.getMonth() + 1}-${isDate.getDate()}`
+  sTime = `${sTime}`
+  eTime = `${eTime}`
+  searchTime.value = [sTime,eTime];
+  state.queryParams.startTime = searchTime.value[0]+' 00:00:00'
+  state.queryParams.endTime = searchTime.value[1]+' 00:00:00'
+}
 const changeTime=(value)=>{
+  console.log('11',searchTime.value)
   if(!value){
     state.queryParams.endTime = ""
     state.queryParams.startTime = ""
   }
+  searchTime.value[0]=moment(searchTime.value[0]).format('YYYY-MM-DD')
+  searchTime.value[1]=moment(searchTime.value[1]).format('YYYY-MM-DD')
 }
 const searchClick = () => {
   if(searchTime.value && searchTime.value.length>0){
-    state.queryParams.startTime = searchTime.value[0]
-    state.queryParams.endTime = searchTime.value[1]
+    state.queryParams.startTime = searchTime.value[0] + ' 00:00:00'
+    state.queryParams.endTime = searchTime.value[1] + ' 00:00:00'
   }
   getList();
 }
+
 /** 重置新增的表单以及其他数据  */
 function reset() {
-  data.queryParams.name = '';
-  data.queryParams.pageNum = 1;
+  state.queryParams = {
+    companyId: '',
+    type: null,
+    endTime: '',
+    startTime: '',
+    pageNum: 1,
+    pageSize: 10,
+  }
+  searchTime.value = [];
   getList();
 }
 
diff --git a/src/views/onlineEducation/groupExams/components/examChooseStudent.vue b/src/views/onlineEducation/groupExams/components/examChooseStudent.vue
new file mode 100644
index 0000000..698b1c6
--- /dev/null
+++ b/src/views/onlineEducation/groupExams/components/examChooseStudent.vue
@@ -0,0 +1,248 @@
+<template>
+  <div class="notice">
+    <el-dialog
+        v-model="dialogVisible"
+        :title="title"
+        width="50%"
+        :before-close="handleClose"
+    >
+      <div style="margin-bottom: 20px">
+        <el-checkbox v-model="state.bindBatchStu" @change="changeBind">绑定批次人员</el-checkbox>
+        <el-select
+            v-if="state.bindBatchStu"
+            multiple
+            collapse-tags
+            collapse-tags-tooltip
+            v-model="state.form.phaseIds"
+            style="width: 160px;margin: 0 20px"
+            v-loadMoreNew:[reselectExam]="handleScroll"
+            :popper-class="reselectExam.name"
+            class="item-width"
+            placeholder="请选择批次"
+        >
+          <el-option
+              v-for="item in state.batchList"
+              :key="item.id"
+              :label="item.name"
+              :value="item.id"
+          />
+        </el-select>
+      </div>
+
+      <!-- 表格数据 -->
+      <el-table
+          ref="tableRef"
+          v-loading="loading"
+          :data="state.dataList"
+          :border="true"
+          :row-key="getRowKey"
+          @selection-change="handleSelectionChange"
+          v-model="state.selectRowKeys"
+      >
+        <el-table-column type="selection" :reserve-selection="true" width="55" align="center" />
+<!--        <el-table-column label="序号" type="index" align="center" width="80" />-->
+        <el-table-column label="工号" prop="empno" align="center" width="60"  />
+        <el-table-column label="姓名" prop="name" align="center"  />
+        <el-table-column label="性别" prop="sex" align="center" >
+          <template #default="scope">
+            <span>{{scope.row.sex == 0 ? '男':'女'}}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="手机号" prop="phone" align="center" width="130"/>
+        <el-table-column label="身份证" prop="idNo" align="center" width="200" :show-overflow-tooltip="true"/>
+<!--        <el-table-column label="创建人" prop="createBy" align="center"/>-->
+        <el-table-column label="工作岗位" prop="post" align="center"/>
+        <el-table-column label="职务" prop="duty" align="center"/>
+<!--        <el-table-column label="一人一档" prop="duty" align="center" width="120">-->
+<!--          <template #default="scope">-->
+<!--            <el-button link type="primary">培训考试记录</el-button>-->
+<!--          </template>-->
+<!--        </el-table-column>-->
+      </el-table>
+
+      <pagination
+          v-show="state.total> 0"
+          :total="state.total"
+          v-model:page="state.queryParams.pageNum"
+          v-model:limit="state.queryParams.pageSize"
+          @pagination="getList"
+      />
+      <template #footer>
+        <span class="dialog-footer">
+            <el-button @click="handleClose" size="default">取 消</el-button>
+            <el-button type="primary"  @click="onSubmit" size="default" v-preReClick>确认</el-button>
+        </span>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+<script setup>
+import {nextTick, reactive, ref, toRefs} from 'vue'
+import {ElMessage} from "element-plus";
+import Cookies from "js-cookie";
+import {
+  addQuestionBank,
+  checkQuestionBankName,
+  editQuestionBank,
+  getQuestionBank
+} from "@/api/onlineEducation/questionBank";
+import {getStudent} from "@/api/onlineEducation/student";
+import {batchAddStudent, getBatch} from "@/api/onlineEducation/batch";
+import {examAddStudent} from "@/api/onlineEducation/exam";
+
+const dialogVisible = ref(false);
+const title = ref("");
+const tableRef = ref();
+const length = ref()
+const emit = defineEmits(["getList"]);
+const startUsername = ref('');
+const classifyRef = ref(null)
+const state = reactive({
+  form: {
+    paperId: null,
+    phaseIds: [],
+    studentIds: []
+  },
+  isAdmin: false,
+  total: 0,
+  queryParams: {
+    pageNum: 1,
+    pageSize: 10
+  },
+  dataList: [],
+  totalItems: 0, // 总数据条数,从后端接口获取
+  phaseId: null,
+  chooseStu: [],
+  companyId: null,
+  selectRowKeys: [],
+  batchList: [],
+  batchPageNum: 1, // 当前页码
+  batchPageSize: 10, // 每页显示的数量
+  hasMoreItemsBatch: null, // 是否还有更多选项
+  bindBatchStu: false
+
+})
+const loading = ref(false);
+
+const reselectExam = reactive({
+  name: 'ExamBatch'
+})
+const getRowKey = (row) => {
+  return row.id
+}
+const openDialog = async (data) => {
+  // state.selectRowKeys = [10,11]
+
+  state.form.paperId = data.queryParams.paperId
+  title.value = '学员选择';
+  dialogVisible.value = true;
+  await getList()
+  await loadMoreBatchData()
+}
+
+const getList = async () => {
+  loading.value = true
+  const res = await getStudent(state.queryParams)
+  if(res.code == 200){
+    state.dataList = res.data.list
+    state.total = res.data.total
+    // await nextTick(() => {
+    //   const currentIds = state.dataList.map(row => row.id)
+    //   const selectIds = state.selectRowKeys.filter(id => currentIds.includes(id))
+    //   state.dataList.forEach(row => {
+    //     if (selectIds.includes(row.id)) {
+    //       tableRef.value.toggleRowSelection(row, true);
+    //     }
+    //   })
+    // });
+  }else{
+    ElMessage.warning(res.message)
+  }
+  loading.value = false
+}
+
+const onSubmit = async () => {
+    const res = await examAddStudent(state.form)
+    if(res.code === 200){
+      ElMessage({
+        type: 'success',
+        message: '新增成功'
+      });
+    }else{
+      ElMessage.warning(res.message)
+    }
+    emit("getList")
+    reset();
+    dialogVisible.value = false;
+}
+
+const handleClose = () => {
+  reset();
+  dialogVisible.value = false;
+  emit("getList")
+}
+const reset = () => {
+  state.form = {
+    paperId: null,
+    phaseIds: [],
+    studentIds: []
+  }
+  state.bindBatchStu = false;
+  state.batchList = [];
+  state.batchPageNum = 1;
+  state.batchPageSize = 10;
+  state.hasMoreItemsBatch = null;
+  tableRef.value.clearSelection();
+  state.dataList = []
+  state.total = 0
+  state.queryParams ={
+    pageNum: 1,
+    pageSize: 10
+  }
+}
+const handleSelectionChange = (val) => {
+  state.form.studentIds = val.map(item => item.id)
+  console.log("选中的行",  state.form.studentIds)
+}
+
+const handleScroll = () => {
+  if(state.batchPageNum >= state.hasMoreItemsBatch) return
+  state.batchPageNum++;
+  loadMoreBatchData()
+}
+const loadMoreBatchData = async () => {
+  console.log(' Bank');
+  const queryParams = {
+    pageNum: state.batchPageNum,
+    pageSize: state.batchPageSize,
+  }
+  const res = await getBatch(queryParams)
+  if (res.code == 200) {
+    state.hasMoreItemsBatch = res.data.totalPage
+    const data = res.data
+    state.batchList = state.batchList.concat(data.list)
+  }else{
+    ElMessage.warning(res.message)
+  }
+}
+const changeBind = (val) => {
+  console.log('vv',val)
+}
+defineExpose({
+  openDialog
+});
+
+</script>
+
+<style scoped lang="scss">
+.notice{
+  :deep(.el-form .el-form-item__label) {
+    font-size: 15px;
+  }
+  .file {
+    display: flex;
+    flex-direction: column;
+    align-items: flex-start;
+  }
+}
+</style>
diff --git a/src/views/onlineEducation/groupExams/components/examDialog.vue b/src/views/onlineEducation/groupExams/components/examDialog.vue
index e2ec21c..6f12c6d 100644
--- a/src/views/onlineEducation/groupExams/components/examDialog.vue
+++ b/src/views/onlineEducation/groupExams/components/examDialog.vue
@@ -4,6 +4,7 @@
         v-model="dialogVisible"
         width="800px"
         :before-close="handleClose"
+        destroy-on-close
     >
       <el-form :model="state.form" size="default" ref="busRef" :rules="state.formRules" label-width="150px" >
           <span style="font-size: 20px;font-weight: 800;margin-left: 20px">考试配置</span>
@@ -28,15 +29,18 @@
         <div  style="display: flex">
           <div class="group">
             <div>
-              单选:<el-input style="max-width: 40px"></el-input>&nbsp;题
+              单选:<el-input style="max-width: 40px" v-model.trim="state.form.singleNum"></el-input>&nbsp;题
             </div>
             <div style="margin-left: 20px">
-              每题:<el-input style="max-width: 40px"></el-input>&nbsp;分
+              每题:<el-input style="max-width: 40px" v-model.trim="state.form.singleScore"></el-input>&nbsp;分
             </div>
           </div>
           <div class="group" >
            <div>
-             共&nbsp;<span style="max-width: 30px">xxx</span>&nbsp;分
+             共&nbsp;
+             <span style="max-width: 30px" v-show="state.form.singleNum && state.form.singleScore">{{state.form.singleNum * state.form.singleScore}}</span>
+<!--             <span v-else></span>-->
+             &nbsp;分
            </div>
             <el-select
                 clearable
@@ -54,33 +58,36 @@
                   :value="item.id"
               />
             </el-select>
-          <el-radio-group v-model="radio"  >
+          <el-radio-group v-model="state.form.singleMethod"  >
             <el-radio :label="1" style="max-width: 30px">随机</el-radio>
-            <el-radio :label="2">默认</el-radio>
+            <el-radio :label="2">顺序</el-radio>
           </el-radio-group>
           </div>
         </div>
         <div  style="display: flex">
           <div class="group">
             <div>
-              多选:<el-input style="max-width: 40px"></el-input>&nbsp;题
+              多选:<el-input style="max-width: 40px" v-model="state.form.multiNum"></el-input>&nbsp;题
             </div>
             <div style="margin-left: 20px">
-              每题:<el-input style="max-width: 40px"></el-input>&nbsp;分
+              每题:<el-input style="max-width: 40px" v-model="state.form.multiScore"></el-input>&nbsp;分
             </div>
           </div>
           <div class="group" >
-            <div>
-              共&nbsp;<span style="max-width: 30px">xxx</span>&nbsp;分
+            <div >
+              共&nbsp;
+              <span style="max-width: 30px" v-show="state.form.multiNum && state.form.multiScore">{{state.form.multiNum * state.form.multiScore}}</span>
+<!--              <span v-else></span>-->
+              &nbsp;分
             </div>
             <el-select
                 clearable
-                v-model="state.form.singleBankId"
+                v-model="state.form.multiBankId"
                 style="width: 160px;margin: 0 20px"
                 v-loadMoreNew:[reselectSingle]="handleScroll"
                 :popper-class="reselectSingle.name"
                 class="item-width"
-                placeholder="请选择单选题题库"
+                placeholder="请选择多选题题库"
             >
               <el-option
                   v-for="item in state.bankListSingle"
@@ -89,33 +96,36 @@
                   :value="item.id"
               />
             </el-select>
-            <el-radio-group v-model="radio"  >
+            <el-radio-group v-model="state.form.multiMethod"  >
               <el-radio :label="1" style="max-width: 30px">随机</el-radio>
-              <el-radio :label="2">默认</el-radio>
+              <el-radio :label="2">顺序</el-radio>
             </el-radio-group>
           </div>
         </div>
         <div  style="display: flex">
           <div class="group">
             <div>
-              判断:<el-input style="max-width: 40px"></el-input>&nbsp;题
+              判断:<el-input style="max-width: 40px" v-model="state.form.judgeNum"></el-input>&nbsp;题
             </div>
             <div style="margin-left: 20px">
-              每题:<el-input style="max-width: 40px"></el-input>&nbsp;分
+              每题:<el-input style="max-width: 40px" v-model="state.form.judgeScore"></el-input>&nbsp;分
             </div>
           </div>
           <div class="group" >
             <div>
-              共&nbsp;<span style="max-width: 30px">xxx</span>&nbsp;分
+              共&nbsp;
+              <span style="max-width: 30px" v-show="state.form.judgeNum && state.form.judgeScore">{{state.form.judgeNum * state.form.judgeScore}}</span>
+<!--              <span v-else></span>-->
+              &nbsp;分
             </div>
             <el-select
                 clearable
-                v-model="state.form.singleBankId"
+                v-model="state.form.judgeBankId"
                 style="width: 160px;margin: 0 20px"
                 v-loadMoreNew:[reselectSingle]="handleScroll"
                 :popper-class="reselectSingle.name"
                 class="item-width"
-                placeholder="请选择单选题题库"
+                placeholder="请选择判断题题库"
             >
               <el-option
                   v-for="item in state.bankListSingle"
@@ -124,24 +134,32 @@
                   :value="item.id"
               />
             </el-select>
-            <el-radio-group v-model="radio"  >
+            <el-radio-group v-model="state.form.judgeMethod"  >
               <el-radio :label="1" style="max-width: 30px">随机</el-radio>
-              <el-radio :label="2">默认</el-radio>
+              <el-radio :label="2">顺序</el-radio>
             </el-radio-group>
           </div>
         </div>
-        <span class="group" style="margin-bottom: 10px">共计:xxx分</span>
+        <span class="group" style="margin-bottom: 20px">共计:
+          {{state.form.judgeNum * state.form.judgeScore+state.form.multiNum * state.form.multiScore+state.form.singleNum * state.form.singleScore}}
+          &nbsp;分</span>
         <div style="display: flex;justify-content: space-between;align-items: center">
-          <el-form-item label="合格分数:" prop="">
-            <el-input-number v-model="num" :min="1" :max="10" style="margin-right: 10px" /> (大于等于)
+          <el-form-item label="合格分数:" prop="passScore">
+            <el-input-number v-model="state.form.passScore" :min="1" :max="1000" style="margin-right: 10px" /> (大于等于)
           </el-form-item>
-          <el-form-item label="限制时长:" prop="">
-            <el-input v-model="num1" style="max-width: 200px" >
+          <el-form-item label="限制时长:" prop="limitTime">
+            <el-input v-model="state.form.limitTime" style="max-width: 200px"  :disabled="state.form.limited === 0">
               <template #append>分钟</template>
             </el-input>
           </el-form-item>
-        </div>
 
+        </div>
+        <el-form-item label="是否限制考试时长:" prop="limited" style="margin-left: 60px">
+          <el-radio-group v-model="state.form.limited" @change="changeLimit" >
+            <el-radio :label="0" style="max-width: 30px">否</el-radio>
+            <el-radio :label="1">是</el-radio>
+          </el-radio-group>
+        </el-form-item>
       </el-form>
       <template #footer>
         <span class="dialog-footer">
@@ -169,7 +187,7 @@
   editQuestionBank,
   getQuestionBank
 } from "@/api/onlineEducation/questionBank";
-import {checkExamName} from "@/api/onlineEducation/exam";
+import {addExam, checkExamName, editExam} from "@/api/onlineEducation/exam";
 
 const dialogVisible = ref(false);
 const title = ref("");
@@ -214,11 +232,30 @@
     name: '',
     categoryId: null,
     companyName: '',
-    companyId: null
+    companyId: null,
+    judgeBankId: null,
+    judgeMethod: 1,
+    judgeNum: null,
+    judgeScore: null,
+    multiBankId: null,
+    multiMethod: 1,
+    multiNum: null,
+    multiScore: null,
+    singleBankId: null,
+    singleMethod: 1,
+    singleNum: null,
+    singleScore: null,
+    limited: 1,
+    limitTime: null,
+    passScore: null
+
   },
   formRules: {
     name: [{required: true, trigger: "blur", validator: validateName}],
     categoryId: [{required: true, message: '请选择课程分类', trigger: 'blur'}],
+    limited: [{required: true, message: '请选择课程分类', trigger: 'blur'}],
+    limitTime: [{required: true, message: '请选择课程分类', trigger: 'blur'}],
+    passScore: [{required: true, message: '请选择课程分类', trigger: 'blur'}]
   },
   classifyList: [],
   isAdmin: false,
@@ -247,9 +284,7 @@
   }
   title.value = type === 'addFirst' || type === 'add' ? '新增' : type ==='edit' ? '编辑' : '' ;
   if(type === 'edit') {
-    state.form.id = value.id
-    state.form.name = value.name
-    state.form.categoryId = value.categoryId
+    state.form = value
     startUsername.value = value.name;
   }else if(type === 'add' && value ){
     state.form.parentId = value.id
@@ -258,18 +293,18 @@
 }
 
 const onSubmit = async () => {
-  if(state.isAdmin){
-    ElMessage({
-      type: 'warning',
-      message: '管理员暂无权限'
-    });
-    return;
-  }
+  // if(state.isAdmin){
+  //   ElMessage({
+  //     type: 'warning',
+  //     message: '管理员暂无权限'
+  //   });
+  //   return;
+  // }
   const valid = await busRef.value.validate();
   if(valid){
     if(title.value === '新增'){
       const {id, ...data} = JSON.parse(JSON.stringify(state.form))
-      const res = await addQuestionBank(data)
+      const res = await addExam(data)
       if(res.code === 200){
         ElMessage({
           type: 'success',
@@ -284,7 +319,7 @@
       dialogVisible.value = false;
     }else if(title.value === '编辑'){
       const {...data} = JSON.parse(JSON.stringify(state.form))
-      const res = await editQuestionBank(data)
+      const res = await editExam(data)
       if(res.code === 200){
         ElMessage({
           type: 'success',
@@ -348,7 +383,22 @@
     name: '',
     categoryId: null,
     companyName: '',
-    companyId: null
+    companyId: null,
+    judgeBankId: null,
+    judgeMethod: 1,
+    judgeNum: null,
+    judgeScore: null,
+    multiBankId: null,
+    multiMethod: 1,
+    multiNum: null,
+    multiScore: null,
+    singleBankId: null,
+    singleMethod: 1,
+    singleNum: null,
+    singleScore: null,
+    limited: 0,
+    limitTime: null,
+    passScore: null
   }
 }
 const handleScroll = () => {
@@ -372,6 +422,14 @@
     ElMessage.warning(res.message)
   }
 }
+
+const changeLimit = (val) => {
+  state.form.limitTime = null
+  if(val === 0) {
+    state.form.limitTime = 0
+  }
+
+}
 defineExpose({
   openDialog
 });
diff --git a/src/views/onlineEducation/groupExams/components/student.vue b/src/views/onlineEducation/groupExams/components/student.vue
new file mode 100644
index 0000000..63b6e46
--- /dev/null
+++ b/src/views/onlineEducation/groupExams/components/student.vue
@@ -0,0 +1,184 @@
+<template>
+  <div class="app-container">
+    <div style="margin-bottom: 10px;display: flex;align-items: center;justify-content: space-between">
+      <el-button
+          type="primary"
+          plain
+          icon="Plus"
+          @click="openDialog()"
+      >选择学员</el-button>
+      <el-button
+          type="danger"
+          plain
+          icon="Delete"
+          @click="handleDeleteBatch"
+      >批量删除</el-button>
+    </div>
+    <!-- 表格数据 -->
+    <el-table ref="tableRef" v-loading="loading" :data="dataList" :border="true" :row-key="getRowKey"  @selection-change="handleSelectionChange">
+      <el-table-column type="selection" :reserve-selection="true" width="55" align="center" />
+      <el-table-column label="序号" type="index" align="center" width="80" />
+      <el-table-column label="试卷名称" align="center" >
+        <template #default="scope">
+          <span>{{scope.row.examPaper.name}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="学员名称" prop="studentName" align="center" >
+        <template #default="scope">
+          <span>{{scope.row.student.name}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="手机号" prop="studentPhone" align="center" >
+        <template #default="scope">
+          <span>{{scope.row.student.phone}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="成绩" prop="score" align="center"  />
+      <el-table-column label="是否合格" prop="passed" align="center"  >
+        <template #default="scope">
+          <span>{{scope.row.passed === 0 ? '不合格' : '合格'}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width"  width="180">
+        <template #default="scope">
+          <el-button link type="danger" @click="handleDelete(scope.row)">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+        v-show="total > 0"
+        :total="total"
+        v-model:page="queryParams.pageNum"
+        v-model:limit="queryParams.pageSize"
+        @pagination="getList"
+    />
+
+    <exam-choose-student ref="dialogRef" @getList=getList></exam-choose-student>
+  </div>
+</template>
+
+<script setup>
+import {getCurrentInstance, onMounted, onUnmounted, reactive, ref, toRefs} from "vue";
+import {ElMessage, ElMessageBox} from "element-plus";
+import Cookies from "js-cookie";
+import {delQuestionBank, getQuestionBank} from "@/api/onlineEducation/questionBank";
+import {batchDelStudent, delBatchStu, getBatchStudent} from "@/api/onlineEducation/batch";
+import {useRoute} from 'vue-router'
+import {delExamStu, examDelStudent, getExamStudent} from "@/api/onlineEducation/exam";
+import ExamChooseStudent from "@/views/onlineEducation/groupExams/components/examChooseStudent.vue";
+const route = useRoute()
+
+
+const { proxy } = getCurrentInstance();
+const loading = ref(false);
+const dialogRef = ref();
+const tableRef = ref();
+const data = reactive({
+  queryParams: {
+    paperId: null,
+    pageNum: 1,
+    pageSize: 10,
+  },
+  total: 0,
+  dataList: [],
+  isAdmin: false,
+  chooseStu: []
+
+});
+
+const { queryParams, total, dataList } = toRefs(data);
+
+onMounted(async ()=>{
+  const userInfo = JSON.parse(Cookies.get('userInfo'))
+  console.log("userInfo",userInfo)
+  if(userInfo.userType === 0){
+    data.isAdmin = true;
+  }else {
+    data.isAdmin = false;
+  }
+  const val = JSON.parse(route.query.val)
+  // data.queryParams.pageId = val.id
+  data.queryParams.paperId = val.id
+  await getList()
+})
+onUnmounted(()=>{
+
+})
+
+const getRowKey = (row) => {
+  return row.id
+}
+const getList = async () => {
+  loading.value = true
+  const res = await getExamStudent(data.queryParams)
+  if(res.code == 200){
+    data.dataList = res.data.list
+    data.total = res.data.total
+  }else{
+    ElMessage.warning(res.message)
+  }
+  loading.value = false
+}
+
+const openDialog = () => {
+  dialogRef.value.openDialog(data);
+}
+
+/** 重置新增的表单以及其他数据  */
+function reset() {
+  proxy.resetForm("roleRef");
+}
+const handleSelectionChange = (val) => {
+
+  console.log("选中的行", val)
+  data.chooseStu = val.map(item => item.id)
+}
+const handleDelete = (val) => {
+  ElMessageBox.confirm(
+      '确定删除此条数据?',
+      '提示',
+      {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning',
+      })
+      .then( async() => {
+        const res = await delExamStu(val.id)
+        if(res.code == 200){
+          ElMessage.success('数据删除成功')
+          await getList()
+          tableRef.value.clearSelection();
+        }else{
+          ElMessage.warning(res.message)
+        }
+      })
+}
+const handleDeleteBatch = () => {
+  if(data.chooseStu && data.chooseStu.length <=0){
+    ElMessage.warning('请选择要删除的学员');
+    return false;
+  }
+  ElMessageBox.confirm(
+      '确定删除选择的所有数据?',
+      '提示',
+      {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning',
+      })
+      .then( async() => {
+        // const param = {
+        //   phaseStudentIds: data.chooseStu
+        // }
+        const res = await examDelStudent(data.chooseStu)
+        if(res.code == 200){
+          ElMessage.success('数据删除成功')
+          await getList()
+        }else{
+          ElMessage.warning(res.message)
+        }
+      })
+}
+
+</script>
diff --git a/src/views/onlineEducation/groupExams/index.vue b/src/views/onlineEducation/groupExams/index.vue
index 03fca18..3a305d3 100644
--- a/src/views/onlineEducation/groupExams/index.vue
+++ b/src/views/onlineEducation/groupExams/index.vue
@@ -14,11 +14,28 @@
       <el-table-column label="企业名称" prop="companyName" align="center"  />
       <el-table-column label="创建账户" prop="createBy" align="center"  />
       <el-table-column label="科目/类别" prop="categoryName" align="center"  />
-      <el-table-column label="考生人数" prop="" align="center"  />
-      <el-table-column label="合格人数" prop="" align="center"  />
-      <el-table-column label="平均分数" prop="" align="center"  />
-      <el-table-column label="合格率" prop="" align="center"  />
-      <el-table-column label="限制时长" prop="limitTime" align="center"  />
+      <el-table-column label="考生人数" prop="" align="center">
+        <template #default="scope">
+          <span>{{scope.row.paperStudentInfoVO.studentCount}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="合格人数" prop="" align="center">
+        <template #default="scope">
+          <span>{{scope.row.paperStudentInfoVO.passStudentCount}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="平均分数" prop="" align="center" >
+        <template #default="scope">
+          <span>{{scope.row.paperStudentInfoVO.avgScore}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="合格率" prop="passRate" align="center" />
+      <el-table-column label="限制时长" prop="limitTime" align="center"  >
+        <template #default="scope">
+          <span v-if="scope.row.limitTime == 0">不限时</span>
+          <span v-else>{{scope.row.limitTime}}</span>
+        </template>
+      </el-table-column>
       <el-table-column label="操作" align="center" class-name="small-padding fixed-width"  width="180">
         <template #default="scope">
           <el-button link type="primary" @click="toStuChoose(scope.row)">学生数据</el-button>
@@ -91,7 +108,13 @@
   loading.value = true
   const res = await getExam(data.queryParams)
   if(res.code == 200){
-    data.dataList = res.data.list
+    data.dataList = res.data.list.map(item => {
+      return {
+        ...item,
+        passRate: item.paperStudentInfoVO.passStudentCount ===0 && item.paperStudentInfoVO.studentCount ===0  ? '0%': (item.paperStudentInfoVO.passStudentCount / item.paperStudentInfoVO.studentCount).toFixed(2) *100 + '%'
+      }
+    })
+
     data.total = res.data.total
   }else{
     ElMessage.warning(res.message)
@@ -128,7 +151,7 @@
 }
 const toStuChoose = (val) => {
   const v = JSON.stringify(val)
-  router.push({ path: "/chooseStu", query: { val: v } });
+  router.push({ path: "/examStu", query: { val: v } });
 }
 
 const openDetail = () => {
diff --git a/src/views/onlineEducation/offlineEducation/components/recordDialog.vue b/src/views/onlineEducation/offlineEducation/components/recordDialog.vue
index 692fe97..3dc57a0 100644
--- a/src/views/onlineEducation/offlineEducation/components/recordDialog.vue
+++ b/src/views/onlineEducation/offlineEducation/components/recordDialog.vue
@@ -82,7 +82,6 @@
 </template>
 <script setup>
 import {reactive, ref, toRefs, defineEmits, nextTick, onMounted} from 'vue'
-import InfiniteList from 'vue3-infinite-list';
 import { View } from "@element-plus/icons-vue";
 import scorllSelect from '@/components/scrollSelect/index.vue'
 import {ElMessage, ElMessageBox} from "element-plus";
diff --git a/src/views/onlineEducation/systemManage/company/index.vue b/src/views/onlineEducation/systemManage/company/index.vue
index cbb5355..13f6aaf 100644
--- a/src/views/onlineEducation/systemManage/company/index.vue
+++ b/src/views/onlineEducation/systemManage/company/index.vue
@@ -20,7 +20,7 @@
       <el-table-column label="总课时(分)" prop="totalPeriodMin" align="center"/>
       <el-table-column label="课时变动详情" align="center" class-name="small-padding fixed-width" >
         <template #default="scope">
-          <el-button link type="primary">查看详情</el-button>
+          <el-button link type="primary" @click="openDetail(scope.row)">查看详情</el-button>
         </template>
       </el-table-column>
       <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="200" >
@@ -41,6 +41,7 @@
     />
 
     <company-dialog ref="dialogRef" @getList=getList></company-dialog>
+    <class-hour-change ref="classHourRef" @getList=getList></class-hour-change>
   </div>
 </template>
 
@@ -49,6 +50,7 @@
 import {ElMessage, ElMessageBox} from "element-plus";
 import {delCompany, getCompany} from "@/api/onlineEducation/company";
 import companyDialog from "./components/companyDialog.vue";
+import classHourChange from '@/views/onlineEducation/classHourBatch/components/classHourChange.vue'
 
 const { proxy } = getCurrentInstance();
 const loading = ref(false);
@@ -63,7 +65,7 @@
 });
 
 const { queryParams, total, dataList } = toRefs(data);
-
+const classHourRef = ref();
 onMounted(()=>{
   getList()
 })
@@ -119,4 +121,7 @@
       })
 }
 
+const openDetail = (val) => {
+  classHourRef.value.openDialog(val.id)
+}
 </script>

--
Gitblit v1.9.2