完成试卷管理模块;新增订单模块
This commit is contained in:
		
							
								
								
									
										33
									
								
								src/api/examination.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/api/examination.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| import service from '@/utils/request' | ||||
| const api = { | ||||
|   // 试卷 | ||||
|   getExaminationList : data => { | ||||
|     return service({ | ||||
|       url: '/exam/list', | ||||
|       method: 'get', | ||||
|       params:data | ||||
|     }) | ||||
|   }, | ||||
|   addExamination : data => { // 新增试卷 | ||||
|     return service({ | ||||
|       url: '/exam', | ||||
|       method: 'post', | ||||
|       data | ||||
|     }) | ||||
|   }, | ||||
|   editExamination : data => { // 更新试卷 | ||||
|     return service({ | ||||
|       url: '/exam/update', | ||||
|       method: 'post', | ||||
|       data | ||||
|     }) | ||||
|   }, | ||||
|   delExamination : data => { // 删除试卷 | ||||
|     return service({ | ||||
|       url: '/exam/delete', | ||||
|       method: 'post', | ||||
|       data | ||||
|     }) | ||||
|   } | ||||
| } | ||||
| export default api | ||||
| @@ -1,12 +1,26 @@ | ||||
| import service from '@/utils/request' | ||||
| const api = { | ||||
|   // 课程api | ||||
|   // 习题 | ||||
|   getExercisesList : data => { | ||||
|     return service({ | ||||
|       url: '/question', | ||||
|       method: 'get', | ||||
|       params:data | ||||
|     }) | ||||
|   }, | ||||
|   addExercises : data => { // 新增习题 | ||||
|     return service({ | ||||
|       url: '/question', | ||||
|       method: 'post', | ||||
|       data | ||||
|     }) | ||||
|   }, | ||||
|   delExercises : data => { // 删除习题 | ||||
|     return service({ | ||||
|       url: '/question/delete', | ||||
|       method: 'post', | ||||
|       data | ||||
|     }) | ||||
|   } | ||||
| } | ||||
| export default api | ||||
|   | ||||
							
								
								
									
										33
									
								
								src/api/order.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/api/order.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| import service from '@/utils/request' | ||||
| const api = { | ||||
|   // 订单 | ||||
|   getOrderList : data => { | ||||
|     return service({ | ||||
|       url: '/order/list', | ||||
|       method: 'get', | ||||
|       params:data | ||||
|     }) | ||||
|   }, | ||||
|   addOrder : data => { // 新增订单 | ||||
|     return service({ | ||||
|       url: '/exam', | ||||
|       method: 'post', | ||||
|       data | ||||
|     }) | ||||
|   }, | ||||
|   editOrder : data => { // 更新订单 | ||||
|     return service({ | ||||
|       url: '/exam/update', | ||||
|       method: 'post', | ||||
|       data | ||||
|     }) | ||||
|   }, | ||||
|   delOrder : data => { // 删除订单 | ||||
|     return service({ | ||||
|       url: '/exam/delete', | ||||
|       method: 'post', | ||||
|       data | ||||
|     }) | ||||
|   } | ||||
| } | ||||
| export default api | ||||
| @@ -8,6 +8,7 @@ export default { | ||||
| </script> | ||||
| <script setup> | ||||
| // 引入依赖 | ||||
| import _ from 'lodash' | ||||
| import api from '@/api/course' | ||||
| // import com_api from '@/api/common' | ||||
| // import custom from '@/utils/custom' | ||||
| @@ -21,19 +22,20 @@ import { useUserStore } from '@/pinia/modules/user' | ||||
| const userStore = useUserStore() | ||||
| import mediaCom from '../components/mediaPool.vue' | ||||
| import exercisesCom from '../components/exercisesPool.vue' | ||||
| import examCom from '../components/examinationPool.vue' | ||||
| const props = defineProps(['course_id','chapter_info']) | ||||
| const emit = defineEmits(['reload']) | ||||
| import UploadCommon from '@/components/upload/common.vue' | ||||
| // 变量 | ||||
| const dialogChapterVisible = ref(false) | ||||
| // const dialogChapterTitle = ref('') | ||||
| const chapterForm = ref({pid:0}) | ||||
| const chapterForm = ref({pid:0,sort:0}) | ||||
| const chapterRules = ref({ | ||||
|   name: [{ required: true, message: '请输入章节名称', trigger: 'blur' }] | ||||
| }) | ||||
| const chapter_data = ref([]) | ||||
| const dialogChapterChildVisible = ref(false) | ||||
| const chapterChildForm = ref({}) | ||||
| const chapterChildForm = ref({sort:0}) | ||||
| const chapterChildRules = ref({ | ||||
|   name: [{ required: true, message: '请输入章节名称', trigger: 'blur' }], | ||||
|   price: [{ required: true, message: '请输入章节价格', trigger: 'blur' }] | ||||
| @@ -54,12 +56,12 @@ watch(props,(old, newProps) => { | ||||
| }) | ||||
| // 方法 | ||||
| function addChapterFunc() { // 添加大章节 | ||||
|   chapterForm.value = {pid:0} | ||||
|   chapterForm.value = {pid:0,sort:0} | ||||
|   dialogChapterVisible.value = true | ||||
|   dialogChapterTitle.value = '添加大章节' | ||||
| } | ||||
| async function deleteChapterFunc(item) { //删除大章节 | ||||
|   delFunc(item.id) | ||||
|   delFunc(item.course_chapter_id) | ||||
| } | ||||
| function delFunc(id) { | ||||
|   ElMessageBox.confirm('此操作将永久删除该数据, 是否继续?', '提示', { | ||||
| @@ -91,21 +93,22 @@ function closeChapterDialog() { | ||||
| } | ||||
| function closeChapterChildDialog() { | ||||
|   dialogChapterChildVisible.value = false | ||||
|   chapterChildForm.value = {sort:0} | ||||
| } | ||||
| async function enterChapterDialog() { // 提交大章节 | ||||
|   // console.log(chapterForm.value) | ||||
|   // return | ||||
|   chapterForm.value.sort = parseInt(chapterForm.value.sort) | ||||
|  | ||||
|   const params = { | ||||
|     ...chapterForm.value | ||||
|   } | ||||
|   let func_name = '' | ||||
|   if(chapterForm.value.id) { // 编辑 | ||||
|   if(chapterForm.value.course_chapter_id) { // 编辑 | ||||
|     func_name = 'editChapter' | ||||
|   } | ||||
|   else{ // 新增 | ||||
|     func_name = 'addChapter' | ||||
|     params.course_id = props.course_id | ||||
|     params.course_id = parseInt(props.course_id) | ||||
|   } | ||||
|   const res = await api[func_name](params) | ||||
|   if(res.code === 0) { | ||||
| @@ -120,33 +123,34 @@ async function enterChapterDialog() { // 提交大章节 | ||||
| function addChapterchildFunc(item) { // 打开新增子章节窗口 | ||||
|   dialogChapterChildTitle.value = '新增子章节' | ||||
|   // current_chapter.value = item | ||||
|   console.log(item.course_chapter_id) | ||||
|   chapterChildForm.value = {pid:item.course_chapter_id} | ||||
|   chapterChildForm.value = {pid:item.course_chapter_id,sort:0} | ||||
|   dialogChapterChildVisible.value = true | ||||
| } | ||||
| function editChapterChildFunc(item,main_index) { // 打开编辑子章节窗口 | ||||
|   dialogChapterChildTitle.value = '编辑子章节' | ||||
|   // current_chapter.value = chapter_data.value[main_index] | ||||
|   chapterChildForm.value = item | ||||
|   item.exam_ids =item.exam_id?[item.exam_id]: [] | ||||
|   item.examination_id = item.exam_id | ||||
|   chapterChildForm.value = _.cloneDeep(item) | ||||
|   dialogChapterChildVisible.value = true | ||||
| } | ||||
| function deleteChapterChildFunc(item) { // 删除子章节 | ||||
|   delFunc(item.id) | ||||
|   delFunc(item.course_subsection_id) | ||||
| } | ||||
| async function enterChapterChildDialog() { // 提交小章节 | ||||
|   chapterChildForm.value.sort = parseInt(chapterChildForm.value.sort) | ||||
|   chapterChildForm.value.price = parseInt(chapterChildForm.value.price) | ||||
|   const params = { | ||||
|     ...chapterChildForm.value | ||||
|   } | ||||
|   let func_name = '' | ||||
|   // console.log(params) | ||||
|   // return | ||||
|   if(chapterChildForm.value.id){ // 编辑 | ||||
|   if(chapterChildForm.value.course_subsection_id){ // 编辑 | ||||
|     func_name = 'editChapter' | ||||
|   } | ||||
|   else{ // 新增 | ||||
|     func_name = 'addChapter' | ||||
|     params.course_id = props.course_id | ||||
|     params.course_id = parseInt(props.course_id) | ||||
|   } | ||||
|   const res = await api[func_name](params) | ||||
|   if(res.code === 0) { | ||||
| @@ -159,7 +163,6 @@ async function enterChapterChildDialog() { // 提交小章节 | ||||
|   } | ||||
| } | ||||
| function getFilePath(file) { // 获取上传文件之后的地址 | ||||
|   console.log(file) | ||||
|   chapterChildForm.value.url = file.url | ||||
|   chapterChildForm.value.url_name = file.url_name | ||||
| } | ||||
| @@ -168,6 +171,10 @@ function chooseChapterChildExercises() { // 打开选择习题窗口 | ||||
| } | ||||
| function openExercisesWinFunc() { // 打开媒体库 | ||||
|  | ||||
| } | ||||
| function addExamFunc(data) { | ||||
|   chapterChildForm.value.examination_id = data[0] | ||||
|   chapterChildForm.value.exam_ids = data | ||||
| } | ||||
| </script> | ||||
| <template> | ||||
| @@ -207,7 +214,7 @@ function openExercisesWinFunc() { // 打开媒体库 | ||||
|         <!--表格数据--> | ||||
|         <div class="lb-table-part" style="margin-bottom: 20px"> | ||||
|           <el-table :data="item.course_sub" > | ||||
|             <el-table-column align="left" label="ID" width="60" prop="course_chapter_id" /> | ||||
|             <el-table-column align="left" label="ID" width="60" prop="course_subsection_id" /> | ||||
|             <el-table-column align="left" label="子章节名称" min-width="60" prop="name" /> | ||||
|             <el-table-column align="left" label="课件名称" min-width="60" prop="url_name" /> | ||||
|  | ||||
| @@ -288,9 +295,9 @@ function openExercisesWinFunc() { // 打开媒体库 | ||||
|           <media-com @on-success="getFilePath" :url_name="chapterChildForm.url_name" /> | ||||
|           <!--          <el-button size="small" type="primary" @click="openExercisesWinFunc">点击上传</el-button>--> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="习题管理"> | ||||
|         <el-form-item label="试卷管理"> | ||||
|           <!--          <el-button size="small" @click="chooseChapterChildExercises">添加习题</el-button>--> | ||||
|           <exercises-com @on-success="getFilePath" :url_name="chapterChildForm.url_name" /> | ||||
|           <exam-com @addFunc="addExamFunc" :seleted_arr="chapterChildForm.exam_ids" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="章节价格" prop="price"> | ||||
|           <el-input type="number" v-model="chapterChildForm.price" placeholder="输入章节价格" autocomplete="off" /> | ||||
|   | ||||
							
								
								
									
										254
									
								
								src/view/course/components/examinationPool.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										254
									
								
								src/view/course/components/examinationPool.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,254 @@ | ||||
| <script setup> | ||||
| // 引入依赖 | ||||
| // import api from '@/api/course' | ||||
| // import com_api from '@/api/common' | ||||
| // import WarningBar from '@/components/warningBar/warningBar.vue' | ||||
| import api from '@/api/examination' | ||||
| import { ref, onMounted, watch, inject, nextTick } from 'vue' | ||||
| import { ElMessage, ElMessageBox } from 'element-plus' | ||||
| import { useRouter, useRoute } from 'vue-router' | ||||
| import {formatDate} from '@/utils/format' | ||||
| const router = useRouter() | ||||
| const route = useRoute() | ||||
| import { useUserStore } from '@/pinia/modules/user' | ||||
| const userStore = useUserStore() | ||||
| // import chapterCom from '../components/chapter.vue' | ||||
| const props = defineProps(['url_name','seleted_arr']) | ||||
| const emit = defineEmits(['addFunc']) | ||||
| // import { clients, getNowDate } from '@/utils' | ||||
| import custom from '@/utils/custom' | ||||
| // import { getToken } from '@/utils/auth' | ||||
| // 监听 | ||||
| watch(props,(val1,val2) => { | ||||
|   selected_exam_ids.value = val1.seleted_arr || [] | ||||
| }) | ||||
| // 变量 | ||||
| const selected_exam_ids = ref(props.seleted_arr || []) | ||||
|  | ||||
| // const headers = ref({ Authorization: 'Bearer ' + getToken() }) | ||||
| const drawer = ref(false) | ||||
| const queryParams =ref({ | ||||
|   page:1, | ||||
|   pageSize:10, | ||||
|   name:'', | ||||
|   // subject:'', | ||||
|   status:'', | ||||
| }) | ||||
| const typeList = custom.getExercisesTypeList() | ||||
| const tableData =ref([]) | ||||
| const total = ref(0) | ||||
| const exam_ids = ref([]) | ||||
| // 生命周期 | ||||
| const subjectList = inject('subjectList') | ||||
| // console.log(subjectList.value) | ||||
| // const current_subject_str = inject('current_subject') | ||||
| // const current_subject = ref(null) | ||||
| // watch(current_subject_str,(val1,val2) => { | ||||
| //   console.log(val1) | ||||
| //   queryParams.value.subject = getSubjectId(val1) | ||||
| //   console.log(queryParams.value.subject) | ||||
| // }) | ||||
| // queryParams.value.subject = current_subject | ||||
| onMounted(() => { | ||||
|   // console.log(headers.value) | ||||
|   // getExaminationList() | ||||
| }) | ||||
| // 方法 | ||||
| function getSubjectId(str) { | ||||
|   // console.log(str) | ||||
|   let s_id = null | ||||
|   for(let item of subjectList.value) { | ||||
|     if(item.name === str) { | ||||
|       s_id = item.id | ||||
|     } | ||||
|   } | ||||
|   return s_id | ||||
| } | ||||
| async function getExaminationList() { | ||||
|   const res = await api.getExaminationList(queryParams.value) | ||||
|   if(res.code === 0) { | ||||
|     tableData.value = res.data.records | ||||
|     total.value = res.data.total | ||||
|     await nextTick() | ||||
|     toggleSelection(tableData.value) | ||||
|   } | ||||
| } | ||||
| function chooseChapterChildExercises() { | ||||
|   drawer.value = true | ||||
|   // getExaminationList() | ||||
|   onSubmit() | ||||
| } | ||||
| function onSubmit() { | ||||
|   queryParams.value.page = 1 | ||||
|   getExaminationList() | ||||
| } | ||||
| function onReset() { | ||||
|   queryParams.value = { | ||||
|     page:1, | ||||
|     pageSize:10, | ||||
|     name:'', | ||||
|     subject:'', | ||||
|     status:'', | ||||
|   } | ||||
| } | ||||
| const handleSelectionChange = (val) => { | ||||
|   exam_ids.value = val | ||||
| } | ||||
| function handleCurrentChange(val) { | ||||
|   queryParams.value.page = val | ||||
|   getExaminationList() | ||||
| } | ||||
| function handleSizeChange(val) { | ||||
|   queryParams.value.pageSize = val | ||||
|   getExaminationList() | ||||
| } | ||||
| function addFunc() { | ||||
|   const list = exam_ids.value.map((item,i) => { | ||||
|     return item.exam.exam_id | ||||
|   }) | ||||
|   // console.log(list) | ||||
|   emit('addFunc',list) | ||||
|   drawer.value = false | ||||
| } | ||||
| const multipleTableRef = ref(null) | ||||
| const toggleSelection = (rows) => { // 判断是否被选中 | ||||
|   if (rows) { | ||||
|     rows.forEach((row) => { | ||||
|       if(selected_exam_ids.value.length>0 && selected_exam_ids.value.includes(row.exam.exam_id)) { | ||||
|         multipleTableRef.value.toggleRowSelection(row, true) | ||||
|       } | ||||
|       else{ | ||||
|         multipleTableRef.value.toggleRowSelection(row, false) | ||||
|       } | ||||
|     }) | ||||
|   } else { | ||||
|     multipleTableRef.value.clearSelection() | ||||
|   } | ||||
| } | ||||
|  | ||||
| function getStateName(state) { | ||||
|   let str = '' | ||||
|   switch (state){ | ||||
|     case 1: | ||||
|         str = '上架' | ||||
|       break; | ||||
|     case -1: | ||||
|         str = '下架' | ||||
|       break; | ||||
|   } | ||||
|   return str | ||||
| } | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     <el-button v-if="selected_exam_ids.length==0" size="small" @click="chooseChapterChildExercises">添加试卷</el-button> | ||||
|     <el-button v-else size="small" @click="chooseChapterChildExercises" type="plain">点击查看</el-button> | ||||
|     <div v-if="url_name">{{url_name}}</div> | ||||
|     <el-drawer v-model="drawer" title="试卷库" size="60%"> | ||||
|       <div class="drawer-section"> | ||||
|         <!--      搜索框--> | ||||
|         <div class="search-box gva-btn-list"> | ||||
|           <el-form ref="searchForm" :inline="true" :model="queryParams"> | ||||
|             <el-form-item label="试卷名称"> | ||||
|               <el-input v-model="queryParams.name" placeholder="根据试卷名称进行查询" /> | ||||
|             </el-form-item> | ||||
| <!--            <el-form-item label="试卷分类">--> | ||||
| <!--              <el-select v-model="queryParams.subject" clearable placeholder="请选择">--> | ||||
| <!--                <el-option--> | ||||
| <!--                  v-for="item in subjectList"--> | ||||
| <!--                  :key="item.id"--> | ||||
| <!--                  :label="item.name"--> | ||||
| <!--                  :value="item.name"--> | ||||
| <!--                />--> | ||||
| <!--              </el-select>--> | ||||
| <!--            </el-form-item>--> | ||||
|             <el-form-item> | ||||
|               <el-button size="small" type="primary" icon="search" @click="onSubmit">查询</el-button> | ||||
|               <el-button size="small" icon="refresh" @click="onReset">重置</el-button> | ||||
|             </el-form-item> | ||||
|           </el-form> | ||||
|         </div> | ||||
|         <!--      数据列表--> | ||||
|         <div class="list-box"> | ||||
|           <el-table ref="multipleTableRef" row-key="exam.exam_id" :data="tableData" @selection-change="handleSelectionChange"> | ||||
|             <el-table-column | ||||
|               type="selection" | ||||
|               width="55" | ||||
|               reserve-selection="true" | ||||
|             /> | ||||
|             <el-table-column align="center" label="ID" min-width="60" prop="exam.exam_id" sortable="custom" /> | ||||
|             <el-table-column align="center" label="试卷名称" min-width="150" prop="exam.name" /> | ||||
|             <el-table-column align="center" label="科目" min-width="150" prop="exam.subject" /> | ||||
|             <el-table-column align="center" label="封面" min-width="150" > | ||||
|               <template #default="scope"> | ||||
|                 <img class="e-img" :src="scope.row.exam.cover" alt=""> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|             <el-table-column align="center" label="状态" min-width="150" > | ||||
|               <template #default="scope"> | ||||
|                 <div>{{getStateName(scope.row.exam.status)}}</div> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|             <el-table-column label="销量"> | ||||
|               <template #default="scope"> | ||||
|                 <div>{{scope.row.exam.sale}}份</div> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|             <el-table-column align="center" label="组数" min-width="150" > | ||||
|               <template #default="scope"> | ||||
|                 <div>{{scope.row.exam_types.length}}组</div> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|             <el-table-column align="center" label="创建时间" min-width="150" > | ||||
|               <template #default="scope"> | ||||
|                 {{formatDate(scope.row.exam.CreatedAt)}} | ||||
|               </template> | ||||
|             </el-table-column> | ||||
| <!--            <el-table-column align="center" fixed="right" label="操作" width="200">--> | ||||
| <!--              <template #default="scope">--> | ||||
| <!--                <el-button--> | ||||
| <!--                  icon="edit"--> | ||||
| <!--                  size="small"--> | ||||
| <!--                  type="primary"--> | ||||
| <!--                  link--> | ||||
| <!--                  @click="editCourseFunc(scope.row)"--> | ||||
| <!--                >编辑</el-button>--> | ||||
| <!--                <el-button--> | ||||
| <!--                  icon="delete"--> | ||||
| <!--                  size="small"--> | ||||
| <!--                  type="danger"--> | ||||
| <!--                  link--> | ||||
| <!--                  @click="deleteExamFunc(scope.row)"--> | ||||
| <!--                >删除</el-button>--> | ||||
| <!--              </template>--> | ||||
| <!--            </el-table-column>--> | ||||
|           </el-table> | ||||
|           <div class="gva-pagination"> | ||||
|             <el-pagination | ||||
|               :current-page="queryParams.page" | ||||
|               :page-size="queryParams.pageSize" | ||||
|               :page-sizes="[10, 30, 50, 100]" | ||||
|               :total="total" | ||||
|               layout="total, sizes, prev, pager, next, jumper" | ||||
|               @current-change="handleCurrentChange" | ||||
|               @size-change="handleSizeChange" | ||||
|             /> | ||||
|           </div> | ||||
|         </div> | ||||
|         <!--  按钮--> | ||||
|         <div class="btn-box" style="text-align: right"> | ||||
|           <el-button size="small" type="primary" icon="plus" @click="addFunc">添加</el-button> | ||||
|         </div> | ||||
|       </div> | ||||
|     </el-drawer> | ||||
|   </div> | ||||
| </template> | ||||
| <style scoped> | ||||
|   .drawer-section{ | ||||
|     padding: 10px; | ||||
|   } | ||||
|   .e-img{ | ||||
|     width: 150px; | ||||
|     height: 100px; | ||||
|   } | ||||
| </style> | ||||
| @@ -2,9 +2,9 @@ | ||||
| // 引入依赖 | ||||
| // import api from '@/api/course' | ||||
| // import com_api from '@/api/common' | ||||
| // import custom from '@/utils/custom' | ||||
| // import WarningBar from '@/components/warningBar/warningBar.vue' | ||||
| import {ref,onMounted,watch,inject  } from 'vue' | ||||
| import api from '@/api/exercises' | ||||
| import { ref, onMounted, watch, inject, nextTick } from 'vue' | ||||
| import { ElMessage, ElMessageBox } from 'element-plus' | ||||
| import { useRouter, useRoute } from 'vue-router' | ||||
| const router = useRouter() | ||||
| @@ -12,52 +12,118 @@ const route = useRoute() | ||||
| import { useUserStore } from '@/pinia/modules/user' | ||||
| const userStore = useUserStore() | ||||
| // import chapterCom from '../components/chapter.vue' | ||||
| const props = defineProps(['url_name']) | ||||
| const emit = defineEmits(['on-success']) | ||||
| import { clients, getNowDate } from '@/utils' | ||||
| const props = defineProps(['url_name','seleted_arr']) | ||||
| const emit = defineEmits(['addFunc']) | ||||
| // import { clients, getNowDate } from '@/utils' | ||||
| import custom from '@/utils/custom' | ||||
| // import { getToken } from '@/utils/auth' | ||||
| // 监听 | ||||
| watch(props,(val1,val2) => { | ||||
|   selected_question_ids.value = val2.seleted_arr || [] | ||||
| }) | ||||
| // 变量 | ||||
| const selected_question_ids = ref(props.seleted_arr || []) | ||||
|  | ||||
| // const headers = ref({ Authorization: 'Bearer ' + getToken() }) | ||||
| const drawer = ref(false) | ||||
| const queryParams =ref({ | ||||
|   pageIndex:1, | ||||
|   page:1, | ||||
|   pageSize:10, | ||||
|   content:'', | ||||
|   subject:'', | ||||
|   subject_type:'' | ||||
|   type:'', | ||||
|   teacherId:0 | ||||
| }) | ||||
| const typeList = custom.getExercisesTypeList() | ||||
| const tableData =ref([]) | ||||
| const total = ref(0) | ||||
| const question_ids = ref([]) | ||||
| // 生命周期 | ||||
| const subjectList = inject('subjectList') | ||||
| const current_subject = inject('current_subject') | ||||
| queryParams.value.subject = current_subject | ||||
| onMounted(() => { | ||||
|   // console.log(headers.value) | ||||
|   // getExercisesList() | ||||
| }) | ||||
|  | ||||
| // 方法 | ||||
| async function getExercisesList() { | ||||
|   const res = await api.getExercisesList(queryParams.value) | ||||
|   if(res.code === 0) { | ||||
|     tableData.value = res.data.records | ||||
|     total.value = res.data.total | ||||
|     await nextTick() | ||||
|     toggleSelection(tableData.value) | ||||
|   } | ||||
| } | ||||
| function chooseChapterChildExercises() { | ||||
|   drawer.value = true | ||||
|   // getExercisesList() | ||||
|   onSubmit() | ||||
| } | ||||
| function onSubmit() { | ||||
|  | ||||
|   queryParams.value.page = 1 | ||||
|   getExercisesList() | ||||
| } | ||||
| function onReset() { | ||||
|   queryParams.value = { | ||||
|     pageIndex:1, | ||||
|     page:1, | ||||
|     pageSize:10, | ||||
|     name:'' | ||||
|     name:'', | ||||
|     type:'', | ||||
|     subject:'', | ||||
|     teacherId:0 | ||||
|   } | ||||
| } | ||||
| const handleSelectionChange = (val) => { | ||||
|   question_ids.value = val | ||||
| } | ||||
| function getExercisesName(row) { | ||||
|   // console.log(JSON.parse(row.question)) | ||||
|   return JSON.parse(row.question).title | ||||
| } | ||||
| function handleCurrentChange(val) { | ||||
|   queryParams.value.page = val | ||||
|   getExercisesList() | ||||
| } | ||||
| function handleSizeChange(val) { | ||||
|   queryParams.value.pageSize = val | ||||
|   getExercisesList() | ||||
| } | ||||
| function addFunc() { | ||||
|   // console.log(question_ids.value) | ||||
|   const list = question_ids.value.map((item,i) => { | ||||
|     return item.question_id | ||||
|   }) | ||||
|   // console.log(list) | ||||
|   emit('addFunc',list) | ||||
|   drawer.value = false | ||||
| } | ||||
| const multipleTableRef = ref(null) | ||||
|  | ||||
| const toggleSelection = (rows) => { // 判断是否被选中 | ||||
|   if (rows) { | ||||
|     rows.forEach((row) => { | ||||
|       if(selected_question_ids.value.includes(row.question_id)) { | ||||
|         multipleTableRef.value.toggleRowSelection(row, true) | ||||
|       }else{ | ||||
|         multipleTableRef.value.toggleRowSelection(row, false) | ||||
|       } | ||||
|     }) | ||||
|   } else { | ||||
|     multipleTableRef.value.clearSelection() | ||||
|   } | ||||
| } | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     <el-button size="small" @click="chooseChapterChildExercises">添加习题</el-button> | ||||
|     <el-button v-if="selected_question_ids.length==0" size="small" @click="chooseChapterChildExercises">添加习题</el-button> | ||||
|     <el-button v-else size="small" @click="chooseChapterChildExercises" type="plain">点击查看(已选{{selected_question_ids.length}}道题)</el-button> | ||||
|     <div v-if="url_name">{{url_name}}</div> | ||||
|     <el-drawer v-model="drawer" title="媒体库" size="60%"> | ||||
|     <el-drawer v-model="drawer" title="习题库" size="60%"> | ||||
|       <div class="drawer-section"> | ||||
|         <!--      搜索框--> | ||||
|         <div class="search-box"> | ||||
|         <div class="search-box gva-btn-list"> | ||||
|           <el-form ref="searchForm" :inline="true" :model="queryParams"> | ||||
|             <el-form-item label="题目"> | ||||
|               <el-input v-model="queryParams.content" placeholder="请输入" /> | ||||
| @@ -68,12 +134,12 @@ function onReset() { | ||||
|                   v-for="item in subjectList" | ||||
|                   :key="item.id" | ||||
|                   :label="item.name" | ||||
|                   :value="item.id" | ||||
|                   :value="item.name" | ||||
|                 /> | ||||
|               </el-select> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="题目类型"> | ||||
|               <el-select v-model="queryParams.subject_type" clearable placeholder="请选择"> | ||||
|               <el-select v-model="queryParams.type" clearable placeholder="请选择"> | ||||
|                 <el-option | ||||
|                   v-for="item in typeList" | ||||
|                   :key="item.value" | ||||
| @@ -90,7 +156,41 @@ function onReset() { | ||||
|         </div> | ||||
|         <!--      数据列表--> | ||||
|         <div class="list-box"> | ||||
|  | ||||
|           <el-table ref="multipleTableRef" row-key="question_id" :data="tableData" @selection-change="handleSelectionChange"> | ||||
|             <el-table-column | ||||
|               type="selection" | ||||
|               width="55" | ||||
|               reserve-selection="true" | ||||
|             /> | ||||
|             <el-table-column align="left" label="ID" min-width="60" prop="question_id" sortable="custom" /> | ||||
|             <el-table-column align="left" label="题型" min-width="150" prop="name" > | ||||
|               <template #default="scope"> | ||||
|                 {{custom.getExercisesTypeName(scope.row.type)}} | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|             <el-table-column align="left" label="科目" min-width="150" prop="subject" /> | ||||
|             <el-table-column align="left" label="题目" min-width="150" > | ||||
|               <template #default="scope"> | ||||
|                 <div v-html="getExercisesName(scope.row)"></div> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|             <el-table-column align="left" label="创建者" min-width="150" prop="teacher_id" /> | ||||
|           </el-table> | ||||
|           <div class="gva-pagination"> | ||||
|             <el-pagination | ||||
|               :current-page="queryParams.page" | ||||
|               :page-size="queryParams.pageSize" | ||||
|               :page-sizes="[10, 30, 50, 100]" | ||||
|               :total="total" | ||||
|               layout="total, sizes, prev, pager, next, jumper" | ||||
|               @current-change="handleCurrentChange" | ||||
|               @size-change="handleSizeChange" | ||||
|             /> | ||||
|           </div> | ||||
|         </div> | ||||
|         <!--  按钮--> | ||||
|         <div class="btn-box" style="text-align: right"> | ||||
|           <el-button size="small" type="primary" icon="plus" @click="addFunc">添加</el-button> | ||||
|         </div> | ||||
|       </div> | ||||
|     </el-drawer> | ||||
|   | ||||
							
								
								
									
										228
									
								
								src/view/examinationManage/components/coursePool.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										228
									
								
								src/view/examinationManage/components/coursePool.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,228 @@ | ||||
| <script setup> | ||||
| // 引入依赖 | ||||
| // import api from '@/api/course' | ||||
| // import com_api from '@/api/common' | ||||
| // import WarningBar from '@/components/warningBar/warningBar.vue' | ||||
| import api from '@/api/course' | ||||
| import { ref, onMounted, watch, inject, nextTick } from 'vue' | ||||
| import { ElMessage, ElMessageBox } from 'element-plus' | ||||
| import { useRouter, useRoute } from 'vue-router' | ||||
| const router = useRouter() | ||||
| const route = useRoute() | ||||
| import { useUserStore } from '@/pinia/modules/user' | ||||
| const userStore = useUserStore() | ||||
| // import chapterCom from '../components/chapter.vue' | ||||
| const props = defineProps(['url_name','seleted_arr']) | ||||
| const emit = defineEmits(['addFunc']) | ||||
| // import { clients, getNowDate } from '@/utils' | ||||
| import custom from '@/utils/custom' | ||||
| // import { getToken } from '@/utils/auth' | ||||
| // 监听 | ||||
| watch(props,(val1,val2) => { | ||||
|   selected_course_ids.value = val1.seleted_arr || [] | ||||
| }) | ||||
| // 变量 | ||||
| const selected_course_ids = ref(props.seleted_arr || []) | ||||
|  | ||||
| // const headers = ref({ Authorization: 'Bearer ' + getToken() }) | ||||
| const drawer = ref(false) | ||||
| const queryParams =ref({ | ||||
|   page:1, | ||||
|   pageSize:10, | ||||
|   name:'', | ||||
|   subject:'', | ||||
|   status:'', | ||||
| }) | ||||
| const typeList = custom.getExercisesTypeList() | ||||
| const tableData =ref([]) | ||||
| const total = ref(0) | ||||
| const course_ids = ref([]) | ||||
| // 生命周期 | ||||
| const subjectList = inject('subjectList') | ||||
| // console.log(subjectList.value) | ||||
| // const current_subject =getSubjectId(inject('current_subject')) | ||||
| const current_subject_str = inject('current_subject') | ||||
| const current_subject = ref(null) | ||||
| watch(current_subject_str,(val1,val2) => { | ||||
|   console.log(val1) | ||||
|   queryParams.value.subject = getSubjectId(val1) | ||||
|   console.log(queryParams.value.subject) | ||||
| }) | ||||
| // queryParams.value.subject = current_subject | ||||
| onMounted(() => { | ||||
|   // console.log(headers.value) | ||||
|   // getCourseList() | ||||
| }) | ||||
| // 方法 | ||||
| function getSubjectId(str) { | ||||
|   // console.log(str) | ||||
|   let s_id = null | ||||
|   for(let item of subjectList.value) { | ||||
|     if(item.name === str) { | ||||
|       s_id = item.id | ||||
|     } | ||||
|   } | ||||
|   return s_id | ||||
| } | ||||
| async function getCourseList() { | ||||
|   const res = await api.getCourseList(queryParams.value) | ||||
|   if(res.code === 0) { | ||||
|     tableData.value = res.data.records | ||||
|     total.value = res.data.total | ||||
|     await nextTick() | ||||
|     toggleSelection(tableData.value) | ||||
|   } | ||||
| } | ||||
| function chooseChapterChildExercises() { | ||||
|   drawer.value = true | ||||
|   // getCourseList() | ||||
|   onSubmit() | ||||
| } | ||||
| function onSubmit() { | ||||
|   queryParams.value.page = 1 | ||||
|   getCourseList() | ||||
| } | ||||
| function onReset() { | ||||
|   queryParams.value = { | ||||
|     page:1, | ||||
|     pageSize:10, | ||||
|     name:'', | ||||
|     subject:'', | ||||
|     status:'', | ||||
|   } | ||||
| } | ||||
| const handleSelectionChange = (val) => { | ||||
|   course_ids.value = val | ||||
| } | ||||
| function handleCurrentChange(val) { | ||||
|   queryParams.value.page = val | ||||
|   getCourseList() | ||||
| } | ||||
| function handleSizeChange(val) { | ||||
|   queryParams.value.pageSize = val | ||||
|   getCourseList() | ||||
| } | ||||
| function addFunc() { | ||||
|   const list = course_ids.value.map((item,i) => { | ||||
|     return item.course_id | ||||
|   }) | ||||
|   emit('addFunc',list) | ||||
|   drawer.value = false | ||||
| } | ||||
| const multipleTableRef = ref(null) | ||||
| const toggleSelection = (rows) => { // 判断是否被选中 | ||||
|   if (rows) { | ||||
|     rows.forEach((row) => { | ||||
|       if(selected_course_ids.value.length>0 && selected_course_ids.value.includes(row.course_id)) { | ||||
|         multipleTableRef.value.toggleRowSelection(row, true) | ||||
|       } | ||||
|       else{ | ||||
|         multipleTableRef.value.toggleRowSelection(row, false) | ||||
|       } | ||||
|     }) | ||||
|   } else { | ||||
|     multipleTableRef.value.clearSelection() | ||||
|   } | ||||
| } | ||||
| function viewCourseFunc(row) { // 查看课程 | ||||
|   router.push({name:'viewCourse',params:{course_id:row.course_id}}) | ||||
| } | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     <el-button v-if="selected_course_ids.length==0" size="small" @click="chooseChapterChildExercises">添加课程</el-button> | ||||
|     <el-button v-else size="small" @click="chooseChapterChildExercises" type="plain">点击查看(已选{{selected_course_ids.length}}门课程)</el-button> | ||||
|     <div v-if="url_name">{{url_name}}</div> | ||||
|     <el-drawer v-model="drawer" title="课程库" size="60%"> | ||||
|       <div class="drawer-section"> | ||||
|         <!--      搜索框--> | ||||
|         <div class="search-box gva-btn-list"> | ||||
|           <el-form ref="searchForm" :inline="true" :model="queryParams"> | ||||
|             <el-form-item label="课程名称"> | ||||
|               <el-input v-model="queryParams.name" placeholder="根据课程名称进行查询" /> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="课程分类"> | ||||
|               <el-select v-model="queryParams.subject" clearable placeholder="请选择"> | ||||
|                 <el-option | ||||
|                   v-for="item in subjectList" | ||||
|                   :key="item.id" | ||||
|                   :label="item.name" | ||||
|                   :value="item.id" | ||||
|                 /> | ||||
|               </el-select> | ||||
|             </el-form-item> | ||||
|             <el-form-item> | ||||
|               <el-button size="small" type="primary" icon="search" @click="onSubmit">查询</el-button> | ||||
|               <el-button size="small" icon="refresh" @click="onReset">重置</el-button> | ||||
|             </el-form-item> | ||||
|           </el-form> | ||||
|         </div> | ||||
|         <!--      数据列表--> | ||||
|         <div class="list-box"> | ||||
|           <el-table ref="multipleTableRef" row-key="course_id" :data="tableData" @selection-change="handleSelectionChange"> | ||||
|             <el-table-column | ||||
|               type="selection" | ||||
|               width="55" | ||||
|               reserve-selection="true" | ||||
|             /> | ||||
|             <el-table-column align="left" label="id" min-width="60" prop="course_id" sortable="custom" /> | ||||
|             <el-table-column align="left" label="名称" min-width="150" prop="name" /> | ||||
|             <el-table-column align="left" label="科目" min-width="150" prop="subject" /> | ||||
|             <el-table-column align="left" label="价格" min-width="150" prop="price" /> | ||||
|             <el-table-column align="left" label="状态" min-width="150" prop="status"> | ||||
|               <template #default="scope"> | ||||
|                 {{scope.row.status == 1?'上架':scope.row.status == 2?'待审核':scope.row.status == 3?'通过':scope.row.status == 4?'未通过':'下架'}} | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|             <el-table-column align="left" label="是否精品" min-width="150" prop="is_boutique" /> | ||||
|             <el-table-column align="left" fixed="right" label="操作" width="200"> | ||||
|               <template #default="scope"> | ||||
|                 <el-button | ||||
|                   icon="view" | ||||
|                   size="small" | ||||
|                   type="primary" | ||||
|                   link | ||||
|                   @click="viewCourseFunc(scope.row)" | ||||
|                 >查看</el-button> | ||||
| <!--                <el-button--> | ||||
| <!--                  icon="edit"--> | ||||
| <!--                  size="small"--> | ||||
| <!--                  type="primary"--> | ||||
| <!--                  link--> | ||||
| <!--                  @click="editCourseFunc(scope.row)"--> | ||||
| <!--                >编辑</el-button>--> | ||||
| <!--                <el-button--> | ||||
| <!--                  icon="delete"--> | ||||
| <!--                  size="small"--> | ||||
| <!--                  type="danger"--> | ||||
| <!--                  link--> | ||||
| <!--                  @click="deleteCourseFunc(scope.row)"--> | ||||
| <!--                >删除</el-button>--> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|           </el-table> | ||||
|           <div class="gva-pagination"> | ||||
|             <el-pagination | ||||
|               :current-page="queryParams.page" | ||||
|               :page-size="queryParams.pageSize" | ||||
|               :page-sizes="[10, 30, 50, 100]" | ||||
|               :total="total" | ||||
|               layout="total, sizes, prev, pager, next, jumper" | ||||
|               @current-change="handleCurrentChange" | ||||
|               @size-change="handleSizeChange" | ||||
|             /> | ||||
|           </div> | ||||
|         </div> | ||||
|         <!--  按钮--> | ||||
|         <div class="btn-box" style="text-align: right"> | ||||
|           <el-button size="small" type="primary" icon="plus" @click="addFunc">添加</el-button> | ||||
|         </div> | ||||
|       </div> | ||||
|     </el-drawer> | ||||
|   </div> | ||||
| </template> | ||||
| <style scoped> | ||||
|   .drawer-section{ | ||||
|     padding: 10px; | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										440
									
								
								src/view/examinationManage/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										440
									
								
								src/view/examinationManage/index.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,440 @@ | ||||
|  | ||||
| <script setup> | ||||
| // 引入依赖 | ||||
| import api from '@/api/examination' | ||||
| import capi from '@/api/course' | ||||
| import custom from '@/utils/custom' | ||||
| import {formatDate} from '@/utils/format' | ||||
| // import { toSQLLine } from '@/utils/stringFun' | ||||
| import WarningBar from '@/components/warningBar/warningBar.vue' | ||||
| // import ckEditor from '@/components/richText/ckEditor5.vue' | ||||
| import coursePool from './components/coursePool.vue' | ||||
| import exercisesPool from '@/view/course/components/exercisesPool.vue' | ||||
| import {ref,onMounted,provide } from 'vue' | ||||
| import { ElMessage, ElMessageBox } from 'element-plus' | ||||
| import { useRouter, useRoute } from 'vue-router' | ||||
| const router = useRouter() | ||||
| const route = useRoute() | ||||
| // store | ||||
| import { useUserStore } from '@/pinia/modules/user' | ||||
| const userStore = useUserStore() | ||||
| // 变量 | ||||
| const path = ref(import.meta.env.VITE_BASE_API) | ||||
| // const typeList = custom.getExercisesTypeList() | ||||
| const queryParams = ref({ | ||||
|   teacherId:0, | ||||
|   page:1, | ||||
|   pageSize:10, | ||||
|   name:'', | ||||
|   status:'', | ||||
|   subject:'' | ||||
| }) | ||||
| const subjectParams = ref({ | ||||
|     pageIndex:1, | ||||
|     pageSize:100, | ||||
| }) | ||||
| const tableData = ref([]) | ||||
| const subjectList = ref([]) | ||||
| const current_subject = ref('') | ||||
| const deleteVisible = ref(false) | ||||
| const question_ids = ref([]) | ||||
| const total = ref(0) | ||||
| const dialogFormVisible = ref(false) | ||||
| const dialogTitle = ref('') | ||||
| const form =ref({}) | ||||
| const rules = ref({ | ||||
|   name: [{ required: true, message: '请输入课程名称', trigger: 'blur' }] | ||||
| }) | ||||
| const question_id = ref(0) | ||||
| const content = ref(null) | ||||
| // const options = ref([]) // 答案选项数组 | ||||
| const exam_types = ref([]) | ||||
| const exam_ids = ref([]) | ||||
| // 生命周期 | ||||
| onMounted(() => { | ||||
|   getExaminationList() | ||||
|   getSubject() | ||||
| }) | ||||
| provide('subjectList', subjectList) | ||||
| provide('current_subject', current_subject) | ||||
| // 方法 | ||||
| async function getExaminationList() { | ||||
|   const res = await api.getExaminationList(queryParams.value) | ||||
|   if(res.code === 0) { | ||||
|     tableData.value = res.data.records | ||||
|     total.value = res.data.total | ||||
|   } | ||||
| } | ||||
| async function getSubject(){ // 获取课程分类 | ||||
|   const res = await capi.getSubjectList(subjectParams.value) | ||||
|   if(res.code === 0) { | ||||
|     subjectList.value = custom.getStdSubject(res.data.records) | ||||
|   } | ||||
| } | ||||
| function onSubmit() { | ||||
|   getExaminationList() | ||||
| } | ||||
| const onReset = () => { | ||||
|   queryParams.value = { | ||||
|     pageIndex:1, | ||||
|     pageSize:10, | ||||
|     name:'', | ||||
|     status:'', | ||||
|     subject:'' | ||||
|   } | ||||
| } | ||||
| function openDialog(type) { | ||||
|   // let params = {} | ||||
|   switch (type){ | ||||
|     case 'add': | ||||
|       dialogTitle.value = '新增试卷' | ||||
|         form.value = {} | ||||
|       break; | ||||
|     case 'edit': | ||||
|       // params.question_id = question_id.value | ||||
|       dialogTitle.value = '编辑试卷' | ||||
|       break; | ||||
|   } | ||||
|   dialogFormVisible.value = true | ||||
|   // router.push({name:'addCourse',params}) | ||||
| } | ||||
| async function onDelete() { | ||||
|   // console.log(question_ids.value) | ||||
|   const ids = exam_ids.value | ||||
|   const res = await api.delExamination({ exam_ids:ids }) | ||||
|   if (res.code === 0) { | ||||
|     ElMessage({ | ||||
|       type: 'success', | ||||
|       message: res.msg | ||||
|     }) | ||||
|     // if (tableData.value.length === ids.length && page.value > 1) { | ||||
|     //   page.value-- | ||||
|     // } | ||||
|     deleteVisible.value = false | ||||
|     getExaminationList() | ||||
|   } | ||||
| } | ||||
| const handleSelectionChange = (val) => { | ||||
|   // console.log(val) | ||||
|   exam_ids.value = val.map((item) => { | ||||
|       return item.exam.exam_id | ||||
|   }) | ||||
|   // console.log(exam_ids.value) | ||||
| } | ||||
| function editCourseFunc(row) { | ||||
|   row.exam.course_ids = JSON.parse(row.exam.course_ids) | ||||
|   row.exam.question_ids = JSON.parse(row.exam.question_ids) | ||||
|  | ||||
|   form.value = row.exam | ||||
|   exam_types.value = row.exam_types.map((item) => { | ||||
|     return item.persons | ||||
|   }) | ||||
|   // console.log(form.value) | ||||
|   current_subject.value = form.value.subject | ||||
|   openDialog('edit') | ||||
|   // console.log(JSON.parse(row.question)) | ||||
| } | ||||
| function deleteExamFunc(row) { | ||||
|   // console.log(row); return | ||||
|   ElMessageBox.confirm('此操作将永久删除该数据, 是否继续?', '提示', { | ||||
|     confirmButtonText: '确定', | ||||
|     cancelButtonText: '取消', | ||||
|     type: 'warning' | ||||
|   }) | ||||
|   .then(async() => { | ||||
|     const res = await api.delExamination({ | ||||
|           exam_ids:[row.exam_id] | ||||
|     }) | ||||
|     if (res.code === 0) { | ||||
|       ElMessage({ | ||||
|         type: 'success', | ||||
|         message: '删除成功!' | ||||
|       }) | ||||
|       getExaminationList() | ||||
|     } | ||||
|   },() => { | ||||
|   }) | ||||
| } | ||||
| function handleCurrentChange(val) { | ||||
|   queryParams.value.pageIndex = val | ||||
|   getExaminationList() | ||||
| } | ||||
| function handleSizeChange(val) { | ||||
|   queryParams.value.pageSize = val | ||||
|   getExaminationList() | ||||
| } | ||||
| function closeDialog(){ | ||||
|   dialogFormVisible.value = false | ||||
|   exam_types.value = [] | ||||
|   form.value = {} | ||||
| } | ||||
| async function enterDialog() { // 提交 | ||||
|   form.value.teacher_id = 0 | ||||
|   form.value.exam_type = exam_types.value.map((item) => { | ||||
|     return item = parseInt(item) | ||||
|   }) | ||||
|   form.value.duration = parseInt(form.value.duration) | ||||
|   // console.log(form.value,exam_types.value) | ||||
|   // return | ||||
|   const params = { | ||||
|     ...form.value | ||||
|   } | ||||
|   params.question_ids = JSON.stringify(form.value.question_ids) | ||||
|   params.course_ids = JSON.stringify(form.value.course_ids) | ||||
|   let func_name = 'addExamination' | ||||
|   if(form.value.exam_id) { // 编辑 | ||||
|     func_name = 'editExamination' | ||||
|   } | ||||
|   const res = await api[func_name](params) | ||||
|   if(res.code === 0) { | ||||
|     ElMessage({ | ||||
|       type: 'success', | ||||
|       message: res.msg | ||||
|     }) | ||||
|     closeDialog() | ||||
|     getExaminationList() | ||||
|   } | ||||
| } | ||||
| function viewCourseFunc(row) { // 查看课程 | ||||
|   router.push({name:'viewCourse',params:{question_id:row.question_id}}) | ||||
| } | ||||
| function getExercisesName(row) { | ||||
|   // console.log(JSON.parse(row.question)) | ||||
|   return JSON.parse(row.question).title | ||||
| } | ||||
| // const std_options_title = ref(['A','B','C','D','E','F']) | ||||
| function addOptionFunc() { | ||||
|   exam_types.value.push('') | ||||
| } | ||||
| function delet_func() { | ||||
|   exam_types.value.pop() | ||||
| } | ||||
| function getStateName(state) { | ||||
|   let str = '' | ||||
|   switch (state){ | ||||
|     case 1: | ||||
|         str = '上架' | ||||
|       break; | ||||
|     case -1: | ||||
|         str = '下架' | ||||
|       break; | ||||
|   } | ||||
|   return str | ||||
| } | ||||
| function handleAvatarSuccess(res) { | ||||
|   form.value.cover = res.data.file.url | ||||
|   // handlerChange() | ||||
| } | ||||
| function beforeAvatarUpload(file) { | ||||
|   const isLt05M = file.size / 1024 / 1024 < 20 | ||||
|   const isJPG = file.type.indexOf('image/') === -1 | ||||
|   if (isJPG) { | ||||
|     ElMessage.error('文件格式错误,请上传图片类型,如:JPG,PNG后缀的文件') | ||||
|   } | ||||
|   if (!isLt05M) { | ||||
|     ElMessage.error('上传头像图片大小不能超过 2M!') | ||||
|   } | ||||
|   return !isJPG && isLt05M | ||||
| } | ||||
| function changeSubjectFunc(e) { | ||||
|   current_subject.value = e | ||||
| } | ||||
| function addExercisesFunc(data) { | ||||
|   form.value.question_ids = data | ||||
| } | ||||
| function addCourseFunc(data) { | ||||
|   form.value.course_ids = data | ||||
| } | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     <!--    搜索框--> | ||||
|     <div class="gva-search-box"> | ||||
|       <el-form ref="searchForm" :inline="true" :model="queryParams"> | ||||
|         <el-form-item label="试卷名称"> | ||||
|           <el-input v-model="queryParams.name" placeholder="根据试卷名称进行查询" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="课程分类"> | ||||
|           <el-select v-model="queryParams.subject" clearable placeholder="请选择"> | ||||
|             <el-option | ||||
|               v-for="item in subjectList" | ||||
|               :key="item.id" | ||||
|               :label="item.name" | ||||
|               :value="item.name" | ||||
|             /> | ||||
|           </el-select> | ||||
|         </el-form-item> | ||||
|         <el-form-item> | ||||
|           <el-button size="small" type="primary" icon="search" @click="onSubmit">查询</el-button> | ||||
|           <el-button size="small" icon="refresh" @click="onReset">重置</el-button> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|     </div> | ||||
|     <!--    表格数据--> | ||||
|     <div class="gva-table-box"> | ||||
|       <!--      批量操作--> | ||||
|       <div class="gva-btn-list"> | ||||
|         <el-button size="small" type="primary" icon="plus" @click="openDialog('add')">新增</el-button> | ||||
|         <el-popover v-model="deleteVisible" placement="top" width="160"> | ||||
|           <p>确定要删除吗?</p> | ||||
|           <div style="text-align: right; margin-top: 8px;"> | ||||
|             <el-button size="small" type="primary" link @click="deleteVisible = false">取消</el-button> | ||||
|             <el-button size="small" type="primary" @click="onDelete">确定</el-button> | ||||
|           </div> | ||||
|           <template #reference> | ||||
|             <el-button icon="delete" size="small" type="danger" :disabled="!exam_ids.length" style="margin-left: 10px;" @click="deleteVisible = true">删除</el-button> | ||||
|           </template> | ||||
|         </el-popover> | ||||
|       </div> | ||||
|       <!--      数据列表--> | ||||
|       <el-table :data="tableData" @selection-change="handleSelectionChange"> | ||||
|         <el-table-column | ||||
|           type="selection" | ||||
|           width="55" | ||||
|         /> | ||||
|         <el-table-column align="center" label="ID" min-width="60" prop="exam.exam_id" sortable="custom" /> | ||||
|         <el-table-column align="center" label="试卷名称" min-width="150" prop="exam.name" /> | ||||
|         <el-table-column align="center" label="科目" min-width="150" prop="exam.subject" /> | ||||
|         <el-table-column align="center" label="封面" min-width="150" > | ||||
|           <template #default="scope"> | ||||
|             <img class="e-img" :src="scope.row.exam.cover" alt=""> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" label="状态" min-width="150" > | ||||
|           <template #default="scope"> | ||||
|             <div>{{getStateName(scope.row.exam.status)}}</div> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column label="销量"> | ||||
|           <template #default="scope"> | ||||
|             <div>{{scope.row.exam.sale}}份</div> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" label="组数" min-width="150" > | ||||
|           <template #default="scope"> | ||||
|             <div>{{scope.row.exam_types.length}}组</div> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" label="创建时间" min-width="150" > | ||||
|           <template #default="scope"> | ||||
|             {{formatDate(scope.row.exam.CreatedAt)}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" fixed="right" label="操作" width="200"> | ||||
|           <template #default="scope"> | ||||
|             <el-button | ||||
|               icon="edit" | ||||
|               size="small" | ||||
|               type="primary" | ||||
|               link | ||||
|               @click="editCourseFunc(scope.row)" | ||||
|             >编辑</el-button> | ||||
|             <el-button | ||||
|               icon="delete" | ||||
|               size="small" | ||||
|               type="danger" | ||||
|               link | ||||
|               @click="deleteExamFunc(scope.row)" | ||||
|             >删除</el-button> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|       </el-table> | ||||
|       <div class="gva-pagination"> | ||||
|         <el-pagination | ||||
|           :current-page="queryParams.page" | ||||
|           :page-size="queryParams.pageSize" | ||||
|           :page-sizes="[10, 30, 50, 100]" | ||||
|           :total="total" | ||||
|           layout="total, sizes, prev, pager, next, jumper" | ||||
|           @current-change="handleCurrentChange" | ||||
|           @size-change="handleSizeChange" | ||||
|         /> | ||||
|       </div> | ||||
|     </div> | ||||
|     <el-dialog v-model="dialogFormVisible" :before-close="closeDialog" :title="dialogTitle"> | ||||
|       <el-form ref="apiForm" :model="form" :rules="rules" label-width="80px"> | ||||
|         <el-form-item label="试卷名称" > | ||||
|           <el-input v-model="form.name" placeholder="请输入试卷名称" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="科目" prop="subject"> | ||||
|           <el-select v-model="form.subject" @change="changeSubjectFunc" clearable placeholder="请选择"> | ||||
|             <el-option | ||||
|               v-for="item in subjectList" | ||||
|               :key="item.id" | ||||
|               :label="item.name" | ||||
|               :value="item.name" | ||||
|             /> | ||||
|           </el-select> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="封面"> | ||||
|           <el-upload | ||||
|             class="avatar-uploader" | ||||
|             :action="`${path}/fileUploadAndDownload/upload`" | ||||
|             :headers="{ 'x-token': userStore.token }" | ||||
|             :show-file-list="false" | ||||
|             :on-success="handleAvatarSuccess" | ||||
|             :before-upload="beforeAvatarUpload" | ||||
|           > | ||||
|             <img v-if="form.cover" :src="form.cover" class="avatar" /> | ||||
|             <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon> | ||||
|           </el-upload> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="测试时长" > | ||||
|           <el-input type="number" v-model="form.duration" placeholder="请输入测试时长(分钟)" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="测试组别" > | ||||
|           <!--          <el-input v-model="form.score" placeholder="请输入分值" />--> | ||||
|           <view class="options-box"> | ||||
|             <view class="option-item" v-if="exam_types.length>0" v-for="(item,i) in exam_types"> | ||||
|               <view>{{i+1}}</view> | ||||
|               <el-input type="number" style="margin-left:5px" v-model="exam_types[i]" placeholder="请输入组别人数" /> | ||||
|               <el-icon style="margin-left: 5px;cursor: pointer" v-if="(i+1) == exam_types.length" @click="delet_func(item)"><Delete /></el-icon> | ||||
|             </view> | ||||
|             <el-button @click="addOptionFunc">添加组别</el-button> | ||||
|           </view> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="添加习题" > | ||||
|           <exercisesPool @addFunc="addExercisesFunc" :seleted_arr="form.question_ids" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="适用课程" > | ||||
|           <coursePool @addFunc="addCourseFunc" :seleted_arr="form.course_ids" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="受否上架" > | ||||
|           <el-switch | ||||
|             v-model="form.status" | ||||
|             active-text="上架" | ||||
|             inactive-text="下架" | ||||
|             :active-value="1" | ||||
|             :inactive-value="-1" | ||||
|           /> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|       <template #footer> | ||||
|         <div class="dialog-footer"> | ||||
|           <el-button size="small" @click="closeDialog">取 消</el-button> | ||||
|           <el-button size="small" type="primary" @click="enterDialog">确 定</el-button> | ||||
|         </div> | ||||
|       </template> | ||||
|     </el-dialog> | ||||
|   </div> | ||||
| </template> | ||||
| <style scoped lang="scss"> | ||||
|   .e-img{ | ||||
|     width: 150px; | ||||
|     height: 100px; | ||||
|   } | ||||
|   .option-item{ | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     margin-bottom: 10px; | ||||
|   } | ||||
|   .button-box { | ||||
|     padding: 10px 20px; | ||||
|     .el-button { | ||||
|       float: right; | ||||
|     } | ||||
|   } | ||||
|   .warning { | ||||
|     color: #dc143c; | ||||
|   } | ||||
| </style> | ||||
| @@ -4,6 +4,7 @@ | ||||
| import api from '@/api/exercises' | ||||
| import capi from '@/api/course' | ||||
| import custom from '@/utils/custom' | ||||
| import {formatDate} from '@/utils/format' | ||||
| // import { toSQLLine } from '@/utils/stringFun' | ||||
| import WarningBar from '@/components/warningBar/warningBar.vue' | ||||
| import ckEditor from '@/components/richText/ckEditor5.vue' | ||||
| @@ -23,13 +24,13 @@ const queryParams = ref({ | ||||
|   subject:'' | ||||
| }) | ||||
| const subjectParams = ref({ | ||||
|     pageIndex:1, | ||||
|     page:1, | ||||
|     pageSize:100, | ||||
| }) | ||||
| const tableData = ref([]) | ||||
| const subjectList = ref([]) | ||||
| const deleteVisible = ref(false) | ||||
| const course_ids = ref([]) | ||||
| const question_ids = ref([]) | ||||
| const total = ref(0) | ||||
| const dialogFormVisible = ref(false) | ||||
| const dialogTitle = ref('') | ||||
| @@ -37,19 +38,26 @@ const form =ref({}) | ||||
| const rules = ref({ | ||||
|   name: [{ required: true, message: '请输入课程名称', trigger: 'blur' }] | ||||
| }) | ||||
| const course_id = ref(0) | ||||
| const question_id = ref(0) | ||||
| const content = ref(null) | ||||
| const options = ref(null) | ||||
| const options = ref([]) // 答案选项数组 | ||||
| const question_form = ref({ | ||||
|   options:[], | ||||
|   answer:'', | ||||
|   title:'' | ||||
| }) | ||||
| // 生命周期 | ||||
| onMounted(() => { | ||||
|   getExercisesList() | ||||
|   getSubject() | ||||
|   // console.log(options.value.size) | ||||
| }) | ||||
| // 方法 | ||||
| async function getExercisesList() { | ||||
|   const res = await api.getExercisesList(queryParams.value) | ||||
|   if(res.code === 0) { | ||||
|     tableData.value = res.data.records | ||||
|     total.value = res.data.total | ||||
|   } | ||||
| } | ||||
| async function getSubject(){ // 获取课程分类 | ||||
| @@ -64,7 +72,7 @@ function onSubmit() { | ||||
| } | ||||
| const onReset = () => { | ||||
|   queryParams.value = { | ||||
|     pageIndex:1, | ||||
|     page:1, | ||||
|     pageSize:10, | ||||
|     name:'', | ||||
|     status:'', | ||||
| @@ -79,7 +87,7 @@ function openDialog(type) { | ||||
|         form.value = {} | ||||
|       break; | ||||
|     case 'edit': | ||||
|       // params.course_id = course_id.value | ||||
|       // params.question_id = question_id.value | ||||
|       dialogTitle.value = '编辑习题' | ||||
|       break; | ||||
|   } | ||||
| @@ -87,9 +95,9 @@ function openDialog(type) { | ||||
|   // router.push({name:'addCourse',params}) | ||||
| } | ||||
| async function onDelete() { | ||||
|   console.log(course_ids.value) | ||||
|   const ids = course_ids.value.map(item => item.course_id) | ||||
|   const res = await api.delCourse({ ids }) | ||||
|   // console.log(question_ids.value) | ||||
|   const ids = question_ids.value.map(item => item.question_id) | ||||
|   const res = await api.delExercises({ question_ids:ids }) | ||||
|   if (res.code === 0) { | ||||
|     ElMessage({ | ||||
|       type: 'success', | ||||
| @@ -104,42 +112,46 @@ async function onDelete() { | ||||
| } | ||||
| const handleSelectionChange = (val) => { | ||||
|   // console.log(val) | ||||
|   course_ids.value = val | ||||
|   question_ids.value = val | ||||
| } | ||||
| function editCourseFunc(row) { | ||||
|   course_id.value = row.course_id | ||||
|   question_id.value = row.question_id | ||||
|   form.value = row | ||||
|   // console.log(JSON.parse(row.question)) | ||||
|   content.value = JSON.parse(row.question).title | ||||
|   options.value =   JSON.parse(row.question).option | ||||
|   // if(JSON.parse(row.question).option) { | ||||
|   //   question_form.value.options =   JSON.parse(row.question).option | ||||
|   // } | ||||
|   // else{ | ||||
|   //   question_form.value.options = [] | ||||
|   // } | ||||
|   question_form.value =   JSON.parse(row.question) | ||||
|   openDialog('edit') | ||||
|   console.log(JSON.parse(row.question)) | ||||
| } | ||||
| function deleteCourseFunc(row) { | ||||
|   // console.log(row); return | ||||
|   ElMessageBox.confirm('此操作将永久删除该数据, 是否继续?', '提示', { | ||||
|     confirmButtonText: '确定', | ||||
|     cancelButtonText: '取消', | ||||
|     type: 'warning' | ||||
|   }) | ||||
|   .then(async() => { | ||||
|     const res = await api.delCourse({ | ||||
|           ids:[row.course_id] | ||||
|     const res = await api.delExercises({ | ||||
|           question_ids:[row.question_id] | ||||
|     }) | ||||
|     if (res.code === 0) { | ||||
|       ElMessage({ | ||||
|         type: 'success', | ||||
|         message: '删除成功!' | ||||
|       }) | ||||
|       // if (tableData.value.length === 1 && page.value > 1) { | ||||
|       //   page.value-- | ||||
|       // } | ||||
|       getExercisesList() | ||||
|     } | ||||
|   },() => { | ||||
|   }) | ||||
| } | ||||
| function handleCurrentChange(val) { | ||||
|   queryParams.value.pageIndex = val | ||||
|   queryParams.value.page = val | ||||
|   getExercisesList() | ||||
| } | ||||
| function handleSizeChange(val) { | ||||
| @@ -148,17 +160,69 @@ function handleSizeChange(val) { | ||||
| } | ||||
| function closeDialog(){ | ||||
|   dialogFormVisible.value = false | ||||
|   question_form.value = { | ||||
|     options:[], | ||||
|     answer:'', | ||||
|     title:'' | ||||
|   } | ||||
|   form.value = {} | ||||
| } | ||||
| function enterDialog() { | ||||
|   console.log(content.value) | ||||
| async function enterDialog() { // 提交 | ||||
|   form.value.score = parseInt(form.value.score) | ||||
|   form.value.teacher_id = 0 | ||||
|   form.value.question = JSON.stringify(question_form.value) | ||||
|   console.log(form.value) | ||||
|   const res = await api.addExercises(form.value) | ||||
|   if(res.code === 0) { | ||||
|     ElMessage({ | ||||
|       type: 'success', | ||||
|       message: res.msg | ||||
|     }) | ||||
|     // if (tableData.value.length === ids.length && page.value > 1) { | ||||
|     //   page.value-- | ||||
|     // } | ||||
|     // deleteVisible.value = false | ||||
|     closeDialog() | ||||
|     getExercisesList() | ||||
|   } | ||||
| } | ||||
| function viewCourseFunc(row) { // 查看课程 | ||||
|   router.push({name:'viewCourse',params:{course_id:row.course_id}}) | ||||
|   router.push({name:'viewCourse',params:{question_id:row.question_id}}) | ||||
| } | ||||
| function getExercisesName(row) { | ||||
|   // console.log(JSON.parse(row.question)) | ||||
|   return JSON.parse(row.question).title | ||||
| } | ||||
| const std_options_title = ref(['A','B','C','D','E','F']) | ||||
| function addOptionFunc() { | ||||
|   // for(let i=0 ;i<std_options_title.value.length;i++) { | ||||
|   //     if(!options.value.has(std_options_title.value[i])) { | ||||
|   //       options.value.set(std_options_title.value[i],'') | ||||
|   //       break; | ||||
|   //     } | ||||
|   // } | ||||
|  | ||||
|   // console.log(options.value) | ||||
|   for(let i=0 ;i<std_options_title.value.length;i++) { | ||||
|     let has_flag = false | ||||
|     for(let item of question_form.value.options){ | ||||
|       if(item.name === std_options_title.value[i]) { | ||||
|         has_flag = true | ||||
|       } | ||||
|     } | ||||
|     if(!has_flag) { | ||||
|       let data = { | ||||
|         name:std_options_title.value[i], | ||||
|         value: '' | ||||
|       } | ||||
|       question_form.value.options.push(data) | ||||
|       break | ||||
|     } | ||||
|   } | ||||
| } | ||||
| function delet_func(item) { | ||||
|   question_form.value.options.pop() | ||||
| } | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
| @@ -206,7 +270,7 @@ function getExercisesName(row) { | ||||
|             <el-button size="small" type="primary" @click="onDelete">确定</el-button> | ||||
|           </div> | ||||
|           <template #reference> | ||||
|             <el-button icon="delete" size="small" type="danger" :disabled="!course_ids.length" style="margin-left: 10px;" @click="deleteVisible = true">删除</el-button> | ||||
|             <el-button icon="delete" size="small" type="danger" :disabled="!question_ids.length" style="margin-left: 10px;" @click="deleteVisible = true">删除</el-button> | ||||
|           </template> | ||||
|         </el-popover> | ||||
|       </div> | ||||
| @@ -230,7 +294,11 @@ function getExercisesName(row) { | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="left" label="创建者" min-width="150" prop="teacher_id" /> | ||||
|         <el-table-column align="left" label="创建时间" min-width="150" prop="createdAt" /> | ||||
|         <el-table-column align="left" label="创建时间" min-width="150" > | ||||
|           <template #default="scope"> | ||||
|             {{formatDate(scope.row.CreatedAt)}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="left" fixed="right" label="操作" width="200"> | ||||
|           <template #default="scope"> | ||||
|             <!--            <el-button--> | ||||
| @@ -259,7 +327,7 @@ function getExercisesName(row) { | ||||
|       </el-table> | ||||
|       <div class="gva-pagination"> | ||||
|         <el-pagination | ||||
|           :current-page="queryParams.pageIndex" | ||||
|           :current-page="queryParams.page" | ||||
|           :page-size="queryParams.pageSize" | ||||
|           :page-sizes="[10, 30, 50, 100]" | ||||
|           :total="total" | ||||
| @@ -278,7 +346,7 @@ function getExercisesName(row) { | ||||
|               v-for="item in subjectList" | ||||
|               :key="item.id" | ||||
|               :label="item.name" | ||||
|               :value="item.id" | ||||
|               :value="item.name" | ||||
|             /> | ||||
|           </el-select> | ||||
|         </el-form-item> | ||||
| @@ -293,22 +361,29 @@ function getExercisesName(row) { | ||||
|           </el-select> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="题目内容" > | ||||
|           <ckEditor v-model="content" :content="content" /> | ||||
|           <ckEditor v-model="question_form.title" :content="question_form.title" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="分值" > | ||||
|           <el-input v-model="form.score" placeholder="请输入分值" /> | ||||
|           <el-input type="number" v-model="form.score" placeholder="请输入分值" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="答案" > | ||||
|           <!--          <el-input v-model="form.score" placeholder="请输入分值" />--> | ||||
|           <view class="options-box" v-if="options"> | ||||
|             <view class="option-item"> | ||||
|               <ckEditor v-model="content" :content="content" /> | ||||
|               <el-icon><Minus /></el-icon> | ||||
|           <view class="options-box"> | ||||
|             <view class="option-item" v-if="question_form.options.length>0" v-for="(item,i) in question_form.options"> | ||||
|               <view>{{item.name}}</view> | ||||
|               <ckEditor v-model="item.value" :content="item.value" style="margin-left:5px" /> | ||||
|               <el-icon style="margin-left: 5px;cursor: pointer" v-if="(i+1) == question_form.options.length" @click="delet_func(item)"><Delete /></el-icon> | ||||
|             </view> | ||||
|             <el-button @click="addOptionFunc">添加答案</el-button> | ||||
|           </view> | ||||
|           <el-button>添加答案</el-button> | ||||
|         </el-form-item> | ||||
|  | ||||
|         <el-form-item label="正确答案" > | ||||
|           <el-input v-model="question_form.answer" placeholder="请输入正确答案(如,选择题:A或A-B;填空题直接填值)" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="题目解析" > | ||||
| <!--          <el-input v-model="form.analysis" placeholder="请输入题目解析" />--> | ||||
|           <ckEditor v-model="form.resolve" :content="form.resolve"  /> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|       <template #footer> | ||||
|         <div class="dialog-footer"> | ||||
| @@ -320,6 +395,11 @@ function getExercisesName(row) { | ||||
|   </div> | ||||
| </template> | ||||
| <style scoped lang="scss"> | ||||
|   .option-item{ | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     margin-bottom: 10px; | ||||
|   } | ||||
|   .button-box { | ||||
|     padding: 10px 20px; | ||||
|     .el-button { | ||||
|   | ||||
							
								
								
									
										429
									
								
								src/view/orderManage/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										429
									
								
								src/view/orderManage/index.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,429 @@ | ||||
|  | ||||
| <script setup> | ||||
| // 引入依赖 | ||||
| import api from '@/api/order' | ||||
| import capi from '@/api/course' | ||||
| import custom from '@/utils/custom' | ||||
| import {formatDate} from '@/utils/format' | ||||
| // import { toSQLLine } from '@/utils/stringFun' | ||||
| // import WarningBar from '@/components/warningBar/warningBar.vue' | ||||
| // import coursePool from './components/coursePool.vue' | ||||
| // import exercisesPool from '@/view/course/components/exercisesPool.vue' | ||||
| import {ref,onMounted,provide } from 'vue' | ||||
| import { ElMessage, ElMessageBox } from 'element-plus' | ||||
| import { useRouter, useRoute } from 'vue-router' | ||||
| const router = useRouter() | ||||
| const route = useRoute() | ||||
| // store | ||||
| import { useUserStore } from '@/pinia/modules/user' | ||||
| const userStore = useUserStore() | ||||
| // 变量 | ||||
| const path = ref(import.meta.env.VITE_BASE_API) | ||||
| // const typeList = custom.getExercisesTypeList() | ||||
| const queryParams = ref({ | ||||
|   teacherId:0, | ||||
|   page:1, | ||||
|   pageSize:10, | ||||
|   orderType:0, | ||||
|   nickname:'', | ||||
|   status:0 | ||||
| }) | ||||
| const subjectParams = ref({ | ||||
|     pageIndex:1, | ||||
|     pageSize:100, | ||||
| }) | ||||
| const tableData = ref([]) | ||||
| const subjectList = ref([]) | ||||
| const current_subject = ref('') | ||||
| const deleteVisible = ref(false) | ||||
| const question_ids = ref([]) | ||||
| const total = ref(0) | ||||
| const dialogFormVisible = ref(false) | ||||
| const dialogTitle = ref('') | ||||
| const form =ref({}) | ||||
| const rules = ref({ | ||||
|   name: [{ required: true, message: '请输入课程名称', trigger: 'blur' }] | ||||
| }) | ||||
| const question_id = ref(0) | ||||
| const content = ref(null) | ||||
| // const options = ref([]) // 答案选项数组 | ||||
| const exam_types = ref([]) | ||||
| const exam_ids = ref([]) | ||||
| // 生命周期 | ||||
| onMounted(() => { | ||||
|   getOrderList() | ||||
|   getSubject() | ||||
| }) | ||||
| provide('subjectList', subjectList) | ||||
| provide('current_subject', current_subject) | ||||
| // 方法 | ||||
| async function getOrderList() { | ||||
|   const res = await api.getOrderList(queryParams.value) | ||||
|   if(res.code === 0) { | ||||
|     tableData.value = res.data.records | ||||
|     total.value = res.data.total | ||||
|   } | ||||
| } | ||||
| async function getSubject(){ // 获取课程分类 | ||||
|   const res = await capi.getSubjectList(subjectParams.value) | ||||
|   if(res.code === 0) { | ||||
|     subjectList.value = custom.getStdSubject(res.data.records) | ||||
|   } | ||||
| } | ||||
| function onSubmit() { | ||||
|   getOrderList() | ||||
| } | ||||
| const onReset = () => { | ||||
|   queryParams.value = { | ||||
|     pageIndex:1, | ||||
|     pageSize:10, | ||||
|     name:'', | ||||
|     status:'', | ||||
|     subject:'' | ||||
|   } | ||||
| } | ||||
| function openDialog(type) { | ||||
|   // let params = {} | ||||
|   switch (type){ | ||||
|     case 'add': | ||||
|       dialogTitle.value = '新增试卷' | ||||
|         form.value = {} | ||||
|       break; | ||||
|     case 'edit': | ||||
|       // params.question_id = question_id.value | ||||
|       dialogTitle.value = '编辑试卷' | ||||
|       break; | ||||
|   } | ||||
|   dialogFormVisible.value = true | ||||
|   // router.push({name:'addCourse',params}) | ||||
| } | ||||
| async function onDelete() { | ||||
|   // console.log(question_ids.value) | ||||
|   const ids = exam_ids.value | ||||
|   const res = await api.delExamination({ exam_ids:ids }) | ||||
|   if (res.code === 0) { | ||||
|     ElMessage({ | ||||
|       type: 'success', | ||||
|       message: res.msg | ||||
|     }) | ||||
|     // if (tableData.value.length === ids.length && page.value > 1) { | ||||
|     //   page.value-- | ||||
|     // } | ||||
|     deleteVisible.value = false | ||||
|     getOrderList() | ||||
|   } | ||||
| } | ||||
| const handleSelectionChange = (val) => { | ||||
|   // console.log(val) | ||||
|   exam_ids.value = val.map((item) => { | ||||
|       return item.exam_id | ||||
|   }) | ||||
|   // console.log(exam_ids.value) | ||||
| } | ||||
| function editCourseFunc(row) { | ||||
|   row.course_ids = JSON.parse(row.course_ids) | ||||
|   row.question_ids = JSON.parse(row.question_ids) | ||||
|  | ||||
|   form.value = row.exam | ||||
|   exam_types.value = row.exam_types.map((item) => { | ||||
|     return item.persons | ||||
|   }) | ||||
|   // console.log(form.value) | ||||
|   current_subject.value = form.value.subject | ||||
|   openDialog('edit') | ||||
|   // console.log(JSON.parse(row.question)) | ||||
| } | ||||
| function deleteExamFunc(row) { | ||||
|   // console.log(row); return | ||||
|   ElMessageBox.confirm('此操作将永久删除该数据, 是否继续?', '提示', { | ||||
|     confirmButtonText: '确定', | ||||
|     cancelButtonText: '取消', | ||||
|     type: 'warning' | ||||
|   }) | ||||
|   .then(async() => { | ||||
|     const res = await api.delExamination({ | ||||
|           exam_ids:[row.exam_id] | ||||
|     }) | ||||
|     if (res.code === 0) { | ||||
|       ElMessage({ | ||||
|         type: 'success', | ||||
|         message: '删除成功!' | ||||
|       }) | ||||
|       getOrderList() | ||||
|     } | ||||
|   },() => { | ||||
|   }) | ||||
| } | ||||
| function handleCurrentChange(val) { | ||||
|   queryParams.value.pageIndex = val | ||||
|   getOrderList() | ||||
| } | ||||
| function handleSizeChange(val) { | ||||
|   queryParams.value.pageSize = val | ||||
|   getOrderList() | ||||
| } | ||||
| function closeDialog(){ | ||||
|   dialogFormVisible.value = false | ||||
|   exam_types.value = [] | ||||
|   form.value = {} | ||||
| } | ||||
| async function enterDialog() { // 提交 | ||||
|   form.value.teacher_id = 0 | ||||
|   form.value.exam_type = exam_types.value.map((item) => { | ||||
|     return item = parseInt(item) | ||||
|   }) | ||||
|   form.value.duration = parseInt(form.value.duration) | ||||
|   // console.log(form.value,exam_types.value) | ||||
|   // return | ||||
|   const params = { | ||||
|     ...form.value | ||||
|   } | ||||
|   params.question_ids = JSON.stringify(form.value.question_ids) | ||||
|   params.course_ids = JSON.stringify(form.value.course_ids) | ||||
|   let func_name = 'addExamination' | ||||
|   if(form.value.exam_id) { // 编辑 | ||||
|     func_name = 'editExamination' | ||||
|   } | ||||
|   const res = await api[func_name](params) | ||||
|   if(res.code === 0) { | ||||
|     ElMessage({ | ||||
|       type: 'success', | ||||
|       message: res.msg | ||||
|     }) | ||||
|     closeDialog() | ||||
|     getOrderList() | ||||
|   } | ||||
| } | ||||
| function viewOrderFunc(row) { // 查看订单 | ||||
|   router.push({name:'viewOrder',params:{question_id:row.question_id}}) | ||||
| } | ||||
| function getExercisesName(row) { | ||||
|   // console.log(JSON.parse(row.question)) | ||||
|   return JSON.parse(row.question).title | ||||
| } | ||||
| // const std_options_title = ref(['A','B','C','D','E','F']) | ||||
| function addOptionFunc() { | ||||
|   exam_types.value.push('') | ||||
| } | ||||
| function delet_func() { | ||||
|   exam_types.value.pop() | ||||
| } | ||||
| function getStateName(state) { | ||||
|   let str = '' | ||||
|   switch (state){ | ||||
|     case 1: | ||||
|         str = '已完成' | ||||
|       break; | ||||
|     case -1: | ||||
|         str = '未付款' | ||||
|       break; | ||||
|   } | ||||
|   return str | ||||
| } | ||||
| function handleAvatarSuccess(res) { | ||||
|   form.value.cover = res.data.file.url | ||||
|   // handlerChange() | ||||
| } | ||||
| function beforeAvatarUpload(file) { | ||||
|   const isLt05M = file.size / 1024 / 1024 < 20 | ||||
|   const isJPG = file.type.indexOf('image/') === -1 | ||||
|   if (isJPG) { | ||||
|     ElMessage.error('文件格式错误,请上传图片类型,如:JPG,PNG后缀的文件') | ||||
|   } | ||||
|   if (!isLt05M) { | ||||
|     ElMessage.error('上传头像图片大小不能超过 2M!') | ||||
|   } | ||||
|   return !isJPG && isLt05M | ||||
| } | ||||
| function changeSubjectFunc(e) { | ||||
|   current_subject.value = e | ||||
| } | ||||
| function addExercisesFunc(data) { | ||||
|   form.value.question_ids = data | ||||
| } | ||||
| function addCourseFunc(data) { | ||||
|   form.value.course_ids = data | ||||
| } | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     <!--    搜索框--> | ||||
|     <div class="gva-search-box"> | ||||
|       <el-form ref="searchForm" :inline="true" :model="queryParams"> | ||||
|         <el-form-item label="试卷名称"> | ||||
|           <el-input v-model="queryParams.name" placeholder="根据试卷名称进行查询" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="课程分类"> | ||||
|           <el-select v-model="queryParams.subject" clearable placeholder="请选择"> | ||||
|             <el-option | ||||
|               v-for="item in subjectList" | ||||
|               :key="item.id" | ||||
|               :label="item.name" | ||||
|               :value="item.name" | ||||
|             /> | ||||
|           </el-select> | ||||
|         </el-form-item> | ||||
|         <el-form-item> | ||||
|           <el-button size="small" type="primary" icon="search" @click="onSubmit">查询</el-button> | ||||
|           <el-button size="small" icon="refresh" @click="onReset">重置</el-button> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|     </div> | ||||
|     <!--    表格数据--> | ||||
|     <div class="gva-table-box"> | ||||
|       <!--      批量操作--> | ||||
|       <div class="gva-btn-list"> | ||||
|         <el-button size="small" type="primary" icon="plus" @click="openDialog('add')">新增</el-button> | ||||
|         <el-popover v-model="deleteVisible" placement="top" width="160"> | ||||
|           <p>确定要删除吗?</p> | ||||
|           <div style="text-align: right; margin-top: 8px;"> | ||||
|             <el-button size="small" type="primary" link @click="deleteVisible = false">取消</el-button> | ||||
|             <el-button size="small" type="primary" @click="onDelete">确定</el-button> | ||||
|           </div> | ||||
|           <template #reference> | ||||
|             <el-button icon="delete" size="small" type="danger" :disabled="!exam_ids.length" style="margin-left: 10px;" @click="deleteVisible = true">删除</el-button> | ||||
|           </template> | ||||
|         </el-popover> | ||||
|       </div> | ||||
|       <!--      数据列表--> | ||||
|       <el-table :data="tableData" @selection-change="handleSelectionChange"> | ||||
|         <el-table-column | ||||
|           type="selection" | ||||
|           width="55" | ||||
|         /> | ||||
|         <el-table-column align="center" label="ID"  prop="order_id" sortable="custom" /> | ||||
|         <el-table-column align="center" label="用户昵称" min-width="150" prop="nickname" /> | ||||
|         <el-table-column align="center" label="用户ID" prop="user_id" /> | ||||
|         <el-table-column align="center" label="手机号" min-width="150" prop="phone" /> | ||||
|         <el-table-column align="center" label="类型" min-width="150" prop="order_type" /> | ||||
|         <el-table-column align="center" label="商品名称" min-width="150" prop="name" /> | ||||
|         <el-table-column align="center" label="订单金额" min-width="150" prop="price" /> | ||||
|         <el-table-column align="center" label="所属区域" min-width="150" prop="" /> | ||||
|         <el-table-column align="center" label="状态"  > | ||||
|           <template #default="scope"> | ||||
|             <div>{{getStateName(scope.row.status)}}</div> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" label="提交时间" min-width="150" > | ||||
|           <template #default="scope"> | ||||
|             {{formatDate(scope.row.CreatedAt)}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" fixed="right" label="操作" width="200"> | ||||
|           <template #default="scope"> | ||||
|             <el-button | ||||
|               icon="edit" | ||||
|               size="small" | ||||
|               type="primary" | ||||
|               link | ||||
|               @click="viewOrderFunc(scope.row)" | ||||
|             >查看</el-button> | ||||
|             <el-button | ||||
|               icon="delete" | ||||
|               size="small" | ||||
|               type="danger" | ||||
|               link | ||||
|               @click="deleteExamFunc(scope.row)" | ||||
|             >删除</el-button> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|       </el-table> | ||||
|       <div class="gva-pagination"> | ||||
|         <el-pagination | ||||
|           :current-page="queryParams.page" | ||||
|           :page-size="queryParams.pageSize" | ||||
|           :page-sizes="[10, 30, 50, 100]" | ||||
|           :total="total" | ||||
|           layout="total, sizes, prev, pager, next, jumper" | ||||
|           @current-change="handleCurrentChange" | ||||
|           @size-change="handleSizeChange" | ||||
|         /> | ||||
|       </div> | ||||
|     </div> | ||||
|     <el-dialog v-model="dialogFormVisible" :before-close="closeDialog" :title="dialogTitle"> | ||||
|       <el-form ref="apiForm" :model="form" :rules="rules" label-width="80px"> | ||||
|         <el-form-item label="试卷名称" > | ||||
|           <el-input v-model="form.name" placeholder="请输入试卷名称" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="科目" prop="subject"> | ||||
|           <el-select v-model="form.subject" @change="changeSubjectFunc" clearable placeholder="请选择"> | ||||
|             <el-option | ||||
|               v-for="item in subjectList" | ||||
|               :key="item.id" | ||||
|               :label="item.name" | ||||
|               :value="item.name" | ||||
|             /> | ||||
|           </el-select> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="封面"> | ||||
|           <el-upload | ||||
|             class="avatar-uploader" | ||||
|             :action="`${path}/fileUploadAndDownload/upload`" | ||||
|             :headers="{ 'x-token': userStore.token }" | ||||
|             :show-file-list="false" | ||||
|             :on-success="handleAvatarSuccess" | ||||
|             :before-upload="beforeAvatarUpload" | ||||
|           > | ||||
|             <img v-if="form.cover" :src="form.cover" class="avatar" /> | ||||
|             <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon> | ||||
|           </el-upload> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="测试时长" > | ||||
|           <el-input type="number" v-model="form.duration" placeholder="请输入测试时长(分钟)" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="测试组别" > | ||||
|           <!--          <el-input v-model="form.score" placeholder="请输入分值" />--> | ||||
|           <view class="options-box"> | ||||
|             <view class="option-item" v-if="exam_types.length>0" v-for="(item,i) in exam_types"> | ||||
|               <view>{{i+1}}</view> | ||||
|               <el-input type="number" style="margin-left:5px" v-model="exam_types[i]" placeholder="请输入组别人数" /> | ||||
|               <el-icon style="margin-left: 5px;cursor: pointer" v-if="(i+1) == exam_types.length" @click="delet_func(item)"><Delete /></el-icon> | ||||
|             </view> | ||||
|             <el-button @click="addOptionFunc">添加组别</el-button> | ||||
|           </view> | ||||
|         </el-form-item> | ||||
| <!--        <el-form-item label="添加习题" >--> | ||||
| <!--          <exercisesPool @addFunc="addExercisesFunc" :seleted_arr="form.question_ids" />--> | ||||
| <!--        </el-form-item>--> | ||||
| <!--        <el-form-item label="适用课程" >--> | ||||
| <!--          <coursePool @addFunc="addCourseFunc" :seleted_arr="form.course_ids" />--> | ||||
| <!--        </el-form-item>--> | ||||
|         <el-form-item label="受否上架" > | ||||
|           <el-switch | ||||
|             v-model="form.status" | ||||
|             active-text="上架" | ||||
|             inactive-text="下架" | ||||
|             :active-value="1" | ||||
|             :inactive-value="-1" | ||||
|           /> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|       <template #footer> | ||||
|         <div class="dialog-footer"> | ||||
|           <el-button size="small" @click="closeDialog">取 消</el-button> | ||||
|           <el-button size="small" type="primary" @click="enterDialog">确 定</el-button> | ||||
|         </div> | ||||
|       </template> | ||||
|     </el-dialog> | ||||
|   </div> | ||||
| </template> | ||||
| <style scoped lang="scss"> | ||||
|   .e-img{ | ||||
|     width: 150px; | ||||
|     height: 100px; | ||||
|   } | ||||
|   .option-item{ | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     margin-bottom: 10px; | ||||
|   } | ||||
|   .button-box { | ||||
|     padding: 10px 20px; | ||||
|     .el-button { | ||||
|       float: right; | ||||
|     } | ||||
|   } | ||||
|   .warning { | ||||
|     color: #dc143c; | ||||
|   } | ||||
| </style> | ||||
		Reference in New Issue
	
	Block a user