Ver código fonte

提交云课堂PC端的代码

Lijy 4 dias atrás
pai
commit
d0609b870f

+ 14 - 4
fhKeeper/formulahousekeeper/course-pc/src/views/lecturerManagement/index.vue

@@ -221,13 +221,18 @@ export default {
                 cancelButtonText: '取消',
                 type: 'warning'
             }).then(() => {
-                this.http.post('/course-teacher/delete', { id: row.id }, res => {
-                    if (res.data.code === 'ok') {
+                this.http.post('/course-teacher/deleteBatch', { ids: row.id }, res => {
+                    if (res.code === 'ok') {
                         this.$message({
                             type: 'success',
                             message: '删除成功!'
                         });
                         this.getList();
+                    } else {
+                        this.$message({
+                            type: 'warning',
+                            message: res.msg
+                        });
                     }
                 });
             })
@@ -245,14 +250,19 @@ export default {
                 cancelButtonText: '取消',
                 type: 'warning'
             }).then(() => {
-                this.http.post('/course-teacher/batchDelete', { ids: this.selectedIds }, res => {
-                    if (res.data.code === 'ok') {
+                this.http.post('/course-teacher/deleteBatch', { ids: this.selectedIds.join(',') }, res => {
+                    if (res.code === 'ok') {
                         this.$message({
                             type: 'success',
                             message: '批量删除成功!'
                         });
                         this.getList();
                         this.selectedIds = [];
+                    } else {
+                        this.$message({
+                            type: 'warning',
+                            message: res.msg
+                        });
                     }
                 })
             })

+ 209 - 145
fhKeeper/formulahousekeeper/course-pc/src/views/offlineRegistration/registration.vue

@@ -2,16 +2,18 @@
   <section>
     <!-- 工具条 -->
     <el-col :span="24" class="toolbar" style="padding-bottom: 0px;">
-      <el-tabs v-model="activeTab">
+      <el-tabs v-model="activeTab" @tab-click="handleClick">
         <el-tab-pane label="预报名信息" name="pre-registration"></el-tab-pane>
         <el-tab-pane label="报名课程" name="course-registration">
           <div class="registerForCourses">
             <el-form :inline="true" @submit.native.prevent>
               <el-form-item label="姓名">
-                <el-input v-model="listQuery.name" placeholder="请输入姓名" clearable @change="handleFilter" size="small"></el-input>
+                <el-input v-model="listQuery.name" placeholder="请输入姓名" clearable @change="handleFilter"
+                  size="small"></el-input>
               </el-form-item>
               <el-form-item label="手机号">
-                <el-input v-model="listQuery.phone" placeholder="请输入手机号" clearable @change="handleFilter" size="small"></el-input>
+                <el-input v-model="listQuery.phone" placeholder="请输入手机号" clearable @change="handleFilter"
+                  size="small"></el-input>
               </el-form-item>
             </el-form>
 
@@ -26,19 +28,13 @@
 
     <!-- 预报名列表 -->
     <transition name="fade" mode="out-in">
-      <el-table 
-        v-if="activeTab === 'pre-registration'"
-        :data="preRegistrationList" 
-        highlight-current-row 
-        v-loading="listLoading"
-        :height="tableHeight"
-        style="width: 100%;">
+      <el-table v-if="activeTab === 'pre-registration'" :data="preRegistrationList" highlight-current-row
+        v-loading="listLoading" :height="tableHeight" style="width: 100%;">
         <el-table-column label="序号" prop="id" width="80" align="center"></el-table-column>
         <el-table-column label="姓名" prop="name" align="center"></el-table-column>
         <el-table-column label="手机号" prop="phone" align="center"></el-table-column>
         <el-table-column label="操作" width="180" align="center" fixed="right">
           <template slot-scope="scope">
-            <el-button size="small" type="primary" @click="handleEdit(scope.row)">编辑</el-button>
             <el-button size="small" type="danger" @click="handleDelete(scope.row)">删除</el-button>
           </template>
         </el-table-column>
@@ -48,21 +44,17 @@
     <!-- 报名课程列表 -->
     <transition name="fade" mode="out-in">
       <div>
-        <el-table 
-          v-if="activeTab === 'course-registration'"
-          :data="courseRegistrationList" 
-          highlight-current-row 
-          v-loading="listLoading"
-          :height="tableHeight - 58"
-          style="width: 100%;">
+        <el-table v-if="activeTab === 'course-registration'" :data="courseRegistrationList" highlight-current-row
+          v-loading="listLoading" :height="tableHeight - 58" style="width: 100%;">
           <el-table-column label="序号" prop="id" width="80" align="center"></el-table-column>
-          <el-table-column label="姓名" prop="name" align="center"></el-table-column>
-          <el-table-column label="手机号" prop="phone" align="center"></el-table-column>
+          <el-table-column label="姓名" prop="name" width="140" align="center"></el-table-column>
+          <el-table-column label="手机号" prop="phone" width="200" align="center"></el-table-column>
           <el-table-column label="报名课程" prop="course" align="center"></el-table-column>
-          <el-table-column label="操作" width="180" align="center" fixed="right">
+          <el-table-column label="操作" width="260" align="center" fixed="right">
             <template slot-scope="scope">
-              <el-button size="small" type="primary" @click="handleEdit(scope.row)">编辑</el-button>
+              <el-button size="small" type="primary" @click="editCourseRegistration(scope.row)">编辑</el-button>
               <el-button size="small" type="danger" @click="handleDelete(scope.row)">删除</el-button>
+              <el-button size="small" type="primary" @click="openExam(scope.row)">开通考试</el-button>
             </template>
           </el-table-column>
         </el-table>
@@ -73,18 +65,14 @@
     <el-dialog title="线下研修班报名" :visible.sync="dialogVisible" width="30%">
       <el-form :model="registrationForm" label-width="80px">
         <el-form-item label="姓名">
-          <el-input v-model="registrationForm.name"></el-input>
+          <el-input v-model.trim="registrationForm.name" placeholder="请输入姓名"></el-input>
         </el-form-item>
         <el-form-item label="手机">
-          <el-input v-model="registrationForm.phone"></el-input>
+          <el-input v-model.trim="registrationForm.phone" placeholder="请输入姓名"></el-input>
         </el-form-item>
         <el-form-item label="报名课程">
-          <el-select v-model="registrationForm.course" placeholder="请选择课程" style="width: 100%">
-            <el-option 
-              v-for="item in courseOptions"
-              :key="item.value"
-              :label="item.label"
-              :value="item.value">
+          <el-select v-model="registrationForm.course" multiple placeholder="请选择课程" style="width: 100%" clearable>
+            <el-option v-for="item in categoryList" :key="item.value" :label="item.label" :value="item.value">
             </el-option>
           </el-select>
         </el-form-item>
@@ -97,20 +85,15 @@
 
     <!-- 分页 -->
     <el-col :span="24" class="toolbar">
-      <el-pagination
-        :current-page="listQuery.page"
-        :page-size="listQuery.limit"
-        :total="total"
-        layout="total, prev, pager, next, jumper"
-        @current-change="handleCurrentChange"
-        style="float:right;"
-      ></el-pagination>
+      <el-pagination :current-page="pageIndex" :page-size="pageSize" :total="total"
+        layout="total, prev, pager, next, sizes" @current-change="handleCurrentChange" @size-change="handleSizeChange"
+        style="float:right;"></el-pagination>
     </el-col>
 
-    <!-- 分类管理 -->
-    <el-dialog :visible.sync="categoryManageVisible" title="线下课程分类管理" width="600px">
+    <!-- 课程管理 -->
+    <el-dialog :visible.sync="categoryManageVisible" title="线下课程管理" width="600px" :before-close="handleClose">
       <el-table :data="categoryList" style="width: 100%" max-height="400">
-        <el-table-column prop="label" label="分类名称" width="180"></el-table-column>
+        <el-table-column prop="label" label="课程名称" width="180"></el-table-column>
         <el-table-column label="封面" width="180">
           <template slot-scope="scope">
             <img v-if="scope.row.coverImage" :src="scope.row.coverImage" class="category-cover-image" />
@@ -126,8 +109,8 @@
       </el-table>
       <div style="margin-top: 20px;">
         <el-form :inline="true" :model="newCategory" class="demo-form-inline">
-          <el-form-item label="分类名称">
-            <el-input v-model="newCategory.label" placeholder="请输入分类名称"></el-input>
+          <el-form-item label="课程名称">
+            <el-input v-model="newCategory.label" placeholder="请输入课程名称"></el-input>
           </el-form-item>
           <el-form-item>
             <el-button type="primary" @click="addCategory">添加</el-button>
@@ -139,41 +122,52 @@
       </span>
     </el-dialog>
 
-    <!-- 设置分类封面 -->
-    <el-dialog :visible.sync="coverDialogVisible" title="设置分类封面" width="500px">
+    <!-- 设置课程封面 -->
+    <el-dialog :visible.sync="coverDialogVisible" title="设置课程封面" width="500px" :before-close="handleClose">
       <div class="cover-upload-container">
-        <el-upload
-          class="cover-uploader"
-          action="#"
-          :show-file-list="false"
-          :on-change="handleCoverChange"
-          :auto-upload="false"
-          :before-upload="beforeCoverUpload">
+        <el-upload class="cover-uploader" action="#" :show-file-list="false" :on-change="handleCoverChange"
+          :auto-upload="false" :before-upload="beforeCoverUpload">
           <img v-if="coverImageUrl" :src="coverImageUrl" class="cover-image" />
           <i v-else class="el-icon-plus cover-uploader-icon"></i>
         </el-upload>
-        <div class="cover-tip">请上传分类封面图片,建议尺寸 16:9</div>
+        <div class="cover-tip">请上传课程封面图片,建议尺寸 16:9</div>
       </div>
       <span slot="footer" class="dialog-footer">
         <el-button @click="coverDialogVisible = false">取 消</el-button>
         <el-button type="primary" @click="saveCategoryCover">确 定</el-button>
       </span>
     </el-dialog>
+
+    <!-- 开通考试 -->
+    <el-dialog title="开通考试" :visible.sync="openExamDialogVisible" width="600px" top="6.5vh" :before-close="handleClose">
+      <div style="width: 100%;">
+        <el-select v-model="examRow.openExamVal" multiple placeholder="请选择" style="width: 100%;">
+          <el-option v-for="item in (examRow.offlineSignList || [])" :key="item.id" :label="item.courseOfflineName"
+            :value="item.id">
+          </el-option>
+        </el-select>
+      </div>
+      <span slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="openExamDialogVisible = false">取消</el-button>
+        <el-button type="primary" @click="openExamCli()">确 定</el-button>
+      </span>
+    </el-dialog>
   </section>
 </template>
 
 <script>
+import { post, checkAndAddUpload } from '../../api'
 export default {
   name: 'OfflineRegistration',
   data() {
     return {
       activeTab: 'pre-registration',
       listQuery: {
-        page: 1,
-        limit: 10,
         name: '',
         phone: ''
       },
+      pageIndex: 1,
+      pageSize: 20,
       total: 0,
       listLoading: false,
       tableHeight: 0,
@@ -191,7 +185,7 @@ export default {
         { value: 'JavaScript基础', label: 'JavaScript基础' },
         { value: 'Node.js实战', label: 'Node.js实战' }
       ],
-      // 分类管理相关
+      // 课程管理相关
       categoryManageVisible: false,
       categoryList: [],
       newCategory: {
@@ -199,11 +193,15 @@ export default {
         value: '',
         coverImage: ''
       },
-      // 分类封面设置
+      // 课程封面设置
       coverDialogVisible: false,
       currentCategoryIndex: -1,
       coverImageUrl: '',
-      coverImageFile: null
+      coverImageFile: null,
+
+      // 开通考试
+      openExamDialogVisible: false,
+      examRow: {},
     }
   },
   created() {
@@ -216,99 +214,135 @@ export default {
     }
   },
   methods: {
+    handleClick() {
+      this.getList()
+    },
     getList() {
       this.listLoading = true
-      // 模拟数据
-      setTimeout(() => {
-        this.preRegistrationList = [
-          { id: 1, name: '张三', phone: '13800138000' },
-          { id: 2, name: '李四', phone: '13800138001' }
-        ]
-        this.courseRegistrationList = [
-          { id: 1, name: '张三', phone: '13800138000', course: 'Vue高级课程' },
-          { id: 2, name: '李四', phone: '13800138001', course: 'React入门' }
-        ]
-        this.total = 20
-        this.listLoading = false
-      }, 500)
+      if (this.activeTab === 'pre-registration') {
+        // 预报名
+        post(`/user-offline-sign-up/signPageList`, {
+          page: this.pageIndex,
+          size: this.pageSize,
+        }).then((res) => {
+          const { records = [], total = 0 } = res.data
+          this.preRegistrationList = records
+          this.total = total
+        }).finally(() => {
+          this.listLoading = false
+        })
+      }
+
+      // 报名课程
+      if (this.activeTab === 'course-registration') {
+        post(`/course-offline-sign/userSignPageList`, {
+          page: this.pageIndex,
+          size: this.pageSize,
+          ...this.listQuery
+        }).then((res) => {
+          const { records = [], total = 0 } = res.data
+          this.courseRegistrationList = records.map((item) => {
+            return {
+              ...item,
+              course: item.offlineSignList.map(ua => ua.courseOfflineName).join(','),
+              courseIds: item.offlineSignList.map(ua => ua.id).join(','),
+              courseIdList: item.offlineSignList.map(ua => ua.id)
+            }
+          })
+          this.total = total
+        }).finally(() => {
+          this.listLoading = false
+        })
+      }
     },
     handleFilter() {
-      this.listQuery.page = 1
+      this.pageIndex = 1
       this.getList()
     },
     handleCurrentChange(val) {
-      this.listQuery.page = val
+      this.pageIndex = val
       this.getList()
     },
-    handleEdit(row) {
-      console.log(row)
+    handleSizeChange(val) {
+      this.pageIndex = 1
+      this.pageSize = val
+      this.getList()
+    },
+    editCourseRegistration(row) {
+      this.dialogVisible = true
+      this.registrationForm = {
+        id: row.id,
+        name: row.name,
+        phone: row.phone,
+        course: row.courseIdList
+      }
     },
     handleDelete(row) {
-      this.$confirm('确认删除该记录吗?', '提示', {
+      const url = this.activeTab == 'pre-registration' ? '/user-offline-sign-up/deleteSignUp' : '/course-offline-sign/deleteUserSign'
+      const text = `确认删除【${row.name}】吗?`
+      const prompt = this.activeTab == 'pre-registration' ? '删除预报名信息人员' : '删除报名课程人员'
+      this.$confirm(text, prompt, {
         confirmButtonText: '确定',
         cancelButtonText: '取消',
         type: 'warning'
       }).then(() => {
-        this.$message({
-          type: 'success',
-          message: '删除成功!'
-        });
+        post(url, { id: row.id }).then(() => {
+          this.$message({
+            type: 'success',
+            message: '删除成功!'
+          });
+          this.getList()
+        })
       });
     },
     showAddDialog() {
+      this.registrationForm = {
+        name: '',
+        phone: '',
+        course: []
+      }
       this.dialogVisible = true
     },
     submitRegistration() {
       // 这里添加提交逻辑
-      this.courseRegistrationList.push({
-        id: this.courseRegistrationList.length + 1,
-        name: this.registrationForm.name,
-        phone: this.registrationForm.phone,
-        course: this.registrationForm.course
-      });
+      console.log(this.registrationForm, '<==== registrationForm')
       this.$message({
         type: 'success',
         message: '报名成功!'
       });
       this.dialogVisible = false;
-      this.resetForm();
     },
-    resetForm() {
-      this.registrationForm = {
-        name: '',
-        phone: '',
-        course: ''
+    // 课程管理
+    batchManage(flag = true) {
+      if (flag) {
+        this.categoryManageVisible = true;
       }
-    },
-    // 分类管理
-    batchManage() {
-      this.categoryManageVisible = true;
-      // 加载分类数据
-      this.http.post('/course-type/list', {}, res => {
+      // 加载课程数据
+      this.http.post('/course-offline/list', {}, res => {
         if (res.code == "ok") {
           // 将后端返回的数据转换为前端需要的格式
           this.categoryList = res.data.map(item => ({
-            label: item.typeName,
+            label: item.courseName,
             value: item.id,
-            coverImage: item.coverImage || ''
+            coverImage: checkAndAddUpload(item.coverImage || '')
           }));
-          
+
           // 同步更新下拉选项
           this.courseOptions = [...this.categoryList];
         } else {
           this.$message({
-            message: res.msg || '获取分类列表失败',
+            message: res.msg || '获取课程列表失败',
             type: 'error'
           });
         }
       }, error => {
         this.$message({
-          message: error || '获取分类列表失败',
+          message: error || '获取课程列表失败',
           type: 'error'
         });
       });
     },
-    // 设置分类封面
+    // 设置课程封面
     setCategoryCover(index, row) {
       this.currentCategoryIndex = index;
       this.coverImageUrl = row.coverImage || '';
@@ -319,35 +353,35 @@ export default {
       this.coverImageFile = file.raw;
       if (this.coverImageFile) {
         this.coverImageUrl = URL.createObjectURL(this.coverImageFile);
-        
-        // 获取当前分类的ID
+
+        // 获取当前课程的ID
         if (this.currentCategoryIndex >= 0) {
           const categoryId = this.categoryList[this.currentCategoryIndex].value;
-          
+
           // 立即上传封面图片
           this.listLoading = true;
-          
+
           // 创建FormData对象用于上传文件
           const formData = new FormData();
           formData.append('id', categoryId);
           formData.append('coverImage', this.coverImageFile);
-          
+
           // 调用上传图片的API
-          this.http.uploadFile('/course-type/uploadCover', formData, res => {
+          this.http.uploadFile('/course-offline/uploadCover', formData, res => {
             this.listLoading = false;
             if (res.code == "ok") {
               // 上传成功后,获取返回的图片URL
               const imageUrl = res.data && res.data.url ? res.data.url : this.coverImageUrl;
-              
+
               // 更新本地数据
               this.categoryList[this.currentCategoryIndex].coverImage = imageUrl;
-              
-              // 同步更新到分类选项中
+
+              // 同步更新到课程选项中
               const optionIndex = this.courseOptions.findIndex(item => item.value === categoryId);
               if (optionIndex !== -1) {
                 this.courseOptions[optionIndex].coverImage = imageUrl;
               }
-              
+
               this.$message({
                 type: 'success',
                 message: '封面图片上传成功!'
@@ -372,23 +406,23 @@ export default {
     beforeCoverUpload(file) {
       const isImage = file.type.indexOf('image/') === 0;
       const isLt2M = file.size / 1024 / 1024 < 2;
-      
+
       if (!isImage) {
         this.$message.error('上传封面图片只能是图片格式!');
       }
       if (!isLt2M) {
         this.$message.error('上传封面图片大小不能超过 2MB!');
       }
-      
+
       return isImage && isLt2M;
     },
-    // 保存分类封面
+    // 保存课程封面
     saveCategoryCover() {
       if (!this.coverImageUrl) {
         this.$message.warning('请先上传封面图片!');
         return;
       }
-      
+
       // 关闭对话框
       this.coverDialogVisible = false;
       this.$message({
@@ -396,92 +430,118 @@ export default {
         message: '设置封面成功!'
       });
     },
-    // 添加分类
+    // 添加课程
     addCategory() {
       if (!this.newCategory.label || !this.newCategory.label.trim()) {
         this.$message({
           type: 'warning',
-          message: '请输入分类名称!'
+          message: '请输入课程名称!'
         });
         return;
       }
-      
-      // 调用后端API保存课程分类
-      this.http.post('/course-type/saveOrUpdate', {
-        typeName: this.newCategory.label
+
+      // 调用后端API保存课程课程
+      this.http.post('/course-offline/saveOrUpdate', {
+        courseName: this.newCategory.label
       }, res => {
         if (res.code == "ok") {
           // 生成唯一ID作为value,实际项目中应该使用后端返回的ID
           const categoryId = res.data && res.data.id ? res.data.id : 'category_' + Date.now();
           this.newCategory.value = categoryId;
-          
-          // 添加到分类列表
-          this.categoryList.push({...this.newCategory});
-          this.courseOptions.push({...this.newCategory});
-          
+
+          // 添加到课程列表
+          this.categoryList.push({ ...this.newCategory });
+          this.courseOptions.push({ ...this.newCategory });
+
           // 清空输入
           this.newCategory.label = '';
           this.newCategory.value = '';
-          
+
           this.$message({
             type: 'success',
-            message: '添加分类成功!'
+            message: '添加课程成功!'
           });
         } else {
           this.$message({
-            message: res.msg || '添加分类失败',
+            message: res.msg || '添加课程失败',
             type: 'error'
           });
         }
       }, error => {
         this.$message({
-          message: error || '添加分类失败',
+          message: error || '添加课程失败',
           type: 'error'
         });
       });
     },
-    // 删除分类
+    // 删除课程
     deleteCategory(index, row) {
-      this.$confirm('确认删除该分类?', '提示', {
+      this.$confirm('确认删除该线下课程?', '提示', {
         confirmButtonText: '确定',
         cancelButtonText: '取消',
         type: 'warning'
       }).then(() => {
-        // 调用后端API删除课程分类
-        this.http.post('/course-type/delete', {
+        // 调用后端API删除课程课程
+        this.http.post('/course-offline/delete', {
           id: row.value
         }, res => {
           if (res.code == "ok") {
-            // 从分类列表中删除
+            // 从课程列表中删除
             this.categoryList.splice(index, 1);
-            
+
             // 从下拉选项中删除
             const optionIndex = this.courseOptions.findIndex(item => item.value === row.value);
             if (optionIndex !== -1) {
               this.courseOptions.splice(optionIndex, 1);
             }
-            
+
             this.$message({
               type: 'success',
-              message: '删除分类成功!'
+              message: '删除课程成功!'
             });
           } else {
             this.$message({
-              message: res.msg || '删除分类失败',
+              message: res.msg || '删除课程失败',
               type: 'error'
             });
           }
         }, error => {
           this.$message({
-            message: error || '删除分类失败',
+            message: error || '删除课程失败',
             type: 'error'
           });
         });
       });
     },
+    // 打开开通考试弹窗
+    openExam(row) {
+      const obj = { ...row, openExamVal: [] }
+      this.$set(this, 'examRow', obj)
+      this.openExamDialogVisible = true;
+    },
+    // 开通考试
+    openExamCli() {
+      const { id, openExamVal = [] } = this.examRow; 
+      console.log(openExamVal, '<==== openExamVal')
+      post(`/course-offline-sign/openCourseExam`, {
+        userSignId: id,
+        courseOfflineId: openExamVal.join(',')
+      }).then(() => {
+        this.$message({
+          type: 'success',
+          message: '开通考试成功'
+        })
+        this.openExamDialogVisible = false;
+        this.getList()
+      })
+    },
+    handleClose(done) {
+      done()
+    }
   },
   mounted() {
     this.getList()
+    this.batchManage(false)
   }
 }
 </script>
@@ -492,14 +552,18 @@ export default {
   justify-content: space-between;
   align-items: center;
 }
+
 .toolbar {
   padding-bottom: 10px;
 }
 
-.fade-enter-active, .fade-leave-active {
+.fade-enter-active,
+.fade-leave-active {
   transition: opacity .3s ease;
 }
-.fade-enter, .fade-leave-to {
+
+.fade-enter,
+.fade-leave-to {
   opacity: 0;
 }
 </style>