Ver Fonte

新增营期复制功能

zyy há 1 semana atrás
pai
commit
1ba01ffb2e

+ 18 - 0
src/api/course/userCourseCamp.js

@@ -52,3 +52,21 @@ export function getCampListLikeName(query) {
   })
 }
 
+// 通过训练营来筛选营期
+export function getScreeningCampPeriod(query) {
+  return request({
+    url: '/course/trainingCamp/getScreeningCampPeriod',
+    method: 'get',
+    params: query
+  })
+}
+
+// 更新训练营序号
+export function updateCampOrderNumber(params) {
+  return request({
+    url: '/course/trainingCamp/updateOrderNumber',
+    method: 'post',
+    params: params
+  })
+}
+

+ 17 - 0
src/api/course/userCoursePeriod.js

@@ -207,3 +207,20 @@ export function batchSaveRedPacketByCompany(data) {
     data: data
   })
 }
+
+// 批量一键选择小节
+export function batchAddCourseSections(data) {
+  return request({
+    url: '/course/period/batchAddCourseSections',
+    method: 'post',
+    data: data
+  })
+}
+// 批量一键选择小节
+export function copyExistCampPeriod(data) {
+  return request({
+    url: '/course/period/copyExistCampPeriod',
+    method: 'post',
+    data: data
+  })
+}

+ 359 - 2
src/views/course/userCoursePeriod/index.vue

@@ -157,6 +157,16 @@
               :disabled="batchSetRedPacketDisabled"
             >批量设置红包</el-button>
           </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="primary"
+              plain
+              icon="el-icon-plus"
+              size="mini"
+              @click="handleAddExistCampPeriod"
+              v-hasPermi="['course:period:add']"
+            >复制现有营期</el-button>
+          </el-col>
           <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
         </el-row>
 
@@ -610,19 +620,119 @@
     @success="handleBatchRedPacketSuccess"
   />
 
+  <el-dialog
+    :title="addExistCampPeriodName"
+    :visible.sync="addExistCampPeriod"
+    width="1000px"
+    append-to-body
+    @close="handleDialogClose"
+  >
+    <el-form ref="createCampPeriodForm" :model="createCampPeriodForm" :rules="campRules" label-width="500px">
+      <el-form-item label="营期创建方式" prop="campPeriodType">
+        <el-radio-group v-model="createCampPeriodForm.campPeriodType" @change="handlePeriodTypeChange">
+          <el-radio :label="1">从当前训练营复制</el-radio>
+          <el-radio :label="2">从其他训练营复制</el-radio>
+          <el-radio :label="3">我要新建一个训练营</el-radio>
+        </el-radio-group>
+      </el-form-item>
+
+      <!-- 从当前训练营复制 -->
+      <el-form-item
+        v-if="createCampPeriodForm.campPeriodType === 1"
+        label="选择当前营期"
+        prop="periodId"
+      >
+        <el-select
+          v-model="createCampPeriodForm.periodId"
+          placeholder="请选择当前营期"
+          clearable
+        >
+          <el-option
+            v-for="item in currentCampPeriods"
+            :key="item.periodId"
+            :label="item.periodName"
+            :value="item.periodId"
+          />
+        </el-select>
+      </el-form-item>
+
+      <!-- 从其他训练营复制 -->
+      <el-form-item
+        v-if="createCampPeriodForm.campPeriodType === 2"
+        label="选择其他营期"
+        prop="periodId"
+      >
+        <el-select
+          v-model="createCampPeriodForm.trainingCampId"
+          placeholder="请选择训练营"
+          :loading="loadingNew"
+          clearable
+          filterable
+          @change="handleTrainingCampChange"
+        >
+          <el-option
+            v-for="item in trainingCampList"
+            :key="item.trainingCampId"
+            :label="item.trainingCampName"
+            :value="item.trainingCampId"
+          />
+        </el-select>
+
+        <el-select
+          v-model="createCampPeriodForm.periodId"
+          placeholder="请选择营期"
+          :loading="loadingNew"
+          clearable
+          filterable
+        >
+          <el-option
+            v-for="item in otherCampPeriods"
+            :key="item.periodId"
+            :label="item.periodName"
+            :value="item.periodId"
+          />
+        </el-select>
+
+        <div v-if="loadingNew" class="loading-text">
+          <i class="el-icon-loading"></i> 加载中...
+        </div>
+      </el-form-item>
+
+      <!-- 新建营期 -->
+      <el-form-item
+        v-if="createCampPeriodForm.campPeriodType === 3"
+        label="新建营期名称"
+        prop="trainingCampName"
+      >
+        <el-input
+          v-model="createCampPeriodForm.trainingCampName"
+          placeholder="请输入新训练营名称"
+          style="width: 300px"
+          maxlength="50"
+          show-word-limit
+        />
+      </el-form-item>
+    </el-form>
+    <div slot="footer" class="dialog-footer">
+      <el-button type="primary" @click="copySubmitCampForm" :loading="submitLoading">确 定</el-button>
+      <el-button @click="cancelExistCampPeriod" :disabled="submitLoading">取 消</el-button>
+    </div>
+  </el-dialog>
+
   </div>
 </template>
 
 <script>
-import {addPeriod, delPeriod, exportPeriod, getPeriod, pagePeriod, updatePeriod, getDays, addCourse,delPeriodDay,  updateCourseTime, updateCourseDate, updateListCourseData, periodCourseMove, closePeriod} from "@/api/course/userCoursePeriod";
+import {addPeriod, delPeriod, exportPeriod, getPeriod, pagePeriod, updatePeriod, getDays, addCourse,delPeriodDay,  updateCourseTime, updateCourseDate, updateListCourseData, periodCourseMove, closePeriod, batchAddCourseSections,copyExistCampPeriod, updateOrderNumber} from "@/api/course/userCoursePeriod";
 import {getCompanyList} from "@/api/company/company";
-import { listCamp, addCamp, editCamp, delCamp, copyCamp } from "@/api/course/userCourseCamp";
+import { listCamp, addCamp, editCamp, delCamp, copyCamp, getScreeningCampPeriod, updateCampOrderNumber} from "@/api/course/userCourseCamp";
 import { courseList,videoList } from '@/api/course/courseRedPacketLog'
 import RedPacket from './redPacket.vue'
 import BatchRedPacket from './batchRedPacket.vue'
 import CourseStatistics from './statistics.vue'
 import Da from "element-ui/src/locale/lang/da";
 import { getConfigByKey } from '@/api/system/config'
+import {listUserCourse} from "@/api/course/userCourse";
 export default {
   name: "Period",
   components: {
@@ -842,6 +952,26 @@ export default {
       batchSetRedPacketDisabled: true,
       // 批量设置红包弹出框
       batchRedPacketVisible: false,
+      //课程选择
+      courseSelection: [],
+      courseSelectionIsAdd: true, // 默认新增状态,编辑时会设为false
+      // 训练营对话框是否显示
+      addExistCampPeriod: false,
+      addExistCampPeriodName: "新增已存在营期",
+      loadingNew: false,
+      submitLoading: false,
+      // 表单数据
+      createCampPeriodForm: {
+        campPeriodType: 1,
+        periodId: null,
+        trainingCampName: null,
+      },
+      // 数据列表
+      currentCampPeriods: [],    // 当前训练营的期数列表
+      otherCampPeriods: [],      // 其他训练营的期数列表
+      // 缓存数据避免重复请求
+      periodDataCache: new Map(),
+      trainingCampList:[],
     };
   },
   created() {
@@ -852,6 +982,10 @@ export default {
     // this.getList();
     this.getLeftList();
     this.getCompanyList();
+    /** 获取课程下拉框*/
+    listUserCourse().then(response => {
+      this.courseSelection = response.rows;
+    });
 
   },
   methods: {
@@ -1286,6 +1420,7 @@ export default {
       // 加载对应的训练营营期数据
       const selectedCamp = this.campList[index];
       this.queryParams.trainingCampId = selectedCamp.trainingCampId;
+      this.trainingCampIdValue=selectedCamp.trainingCampId;
       this.getList();
     },
     /** 处理滚动事件,实现滚动到底部加载更多 */
@@ -1735,6 +1870,228 @@ export default {
       // 强制更新组件以刷新领取红包时间的可选范围
       this.$forceUpdate();
     },
+    /** 新建存在训练营按钮操作 */
+    handleAddExistCampPeriod() {
+      this.resetForm();
+      this.addExistCampPeriod = true;
+      // 初始化当前训练营的期数列表
+      this.initCurrentCampPeriods();
+    },
+    /** 初始化当前训练营期数列表 */
+    initCurrentCampPeriods() {
+      // 对当前营期列表按照创建时间倒序排序(最新的在前面)
+      this.currentCampPeriods = [...(this.periodList || [])].sort((a, b) => {
+        // 如果没有创建时间,按原始顺序
+        if (!a.createTime || !b.createTime) return 0;
+
+        // 将时间字符串转换为时间戳进行比较
+        const timeA = new Date(a.createTime).getTime();
+        const timeB = new Date(b.createTime).getTime();
+
+        // 按创建时间倒序排列(最新的在前面)
+        return timeB - timeA;
+      });
+    },
+    /** 处理创建方式变更 */
+    async handlePeriodTypeChange(value) {
+      this.createCampPeriodForm.periodId = null;
+      this.createCampPeriodForm.trainingCampName = null;
+      if (value === 1) {
+        // 从当前训练营复制 - 使用本地数据
+        this.initCurrentCampPeriods();
+      } else if (value === 2) {
+        // 从其他训练营复制 - 需要请求接口
+        await this.loadOtherCampPeriods();
+      }
+    },
+    /** 加载其他训练营期数列表 */
+    async loadOtherCampPeriods() {
+      // 清空营期数据和选中项,避免显示旧数据
+      this.otherCampPeriods = [];
+      this.createCampPeriodForm.periodId = ''; // 清空已选营期
+      this.createCampPeriodForm.trainingCampId = ''; // 清空已选训练营
+
+      // 检查缓存 - 使用固定键名,因为训练营列表不依赖当前训练营ID
+      // const cacheKey = 'trainingCampList';
+      // if (this.periodDataCache.has(cacheKey)) {
+      //   this.trainingCampList = this.periodDataCache.get(cacheKey);
+      //   return;
+      // }
+
+      this.loadingNew = true;
+      try {
+        const requestParams = {
+          periodId: this.trainingCampIdValue,
+          campPeriodType: this.createCampPeriodForm.campPeriodType
+        };
+        const response = await getScreeningCampPeriod(requestParams);
+        if (response && Array.isArray(response.resultList)) {
+          this.trainingCampList = response.resultList;
+          // 缓存数据 - 使用固定键名
+          //this.periodDataCache.set(cacheKey, response.resultList);
+        } else {
+          console.warn('接口返回格式异常:', response);
+          this.trainingCampList = [];
+        }
+      } catch (error) {
+        console.error('接口请求失败:', error);
+        this.$message.error('查询失败,请重试');
+        this.trainingCampList = [];
+      } finally {
+        this.loadingNew = false;
+      }
+    },
+    /** 对话框关闭事件 */
+    handleDialogClose() {
+      this.resetForm();
+    },
+    /** 重置表单 */
+    resetForm() {
+      this.createCampPeriodForm = {
+        campPeriodType: 1,
+        periodId: null,
+        trainingCampName: null,
+      };
+
+      this.currentCampPeriods = [];
+      this.otherCampPeriods = [];
+      this.trainingCampList=[]
+      this.loading = false;
+      this.submitLoading = false;
+
+      // 清除表单验证
+      if (this.$refs.createCampPeriodForm) {
+        this.$refs.createCampPeriodForm.clearValidate();
+      }
+    },
+    handleTrainingCampChange(trainingCampId){
+      this.otherCampPeriods = [];
+      this.createCampPeriodForm.periodId = '';
+      const params = {
+        ...this.queryParams,
+        trainingCampId: trainingCampId  // 更新训练营ID
+      };
+      pagePeriod(params).then(response => {
+        if (response.code === 200) {
+          this.otherCampPeriods = response.rows;
+        } else {
+          this.$message.error(response.msg || '查询营期失败');
+        }
+      }).catch(error => {
+        this.$message.error('查询营期失败: ' + (error.message || '查询营期失败'));
+      });
+    },
+    /** 提交表单 */
+    copySubmitCampForm() {
+      try {
+        // 表单验证
+        const valid =  this.$refs.createCampPeriodForm.validate();
+        if (!valid) return ;
+        this.submitLoading = true;
+        const submitData = this.buildSubmitData();
+        if (submitData.campPeriodType===3){
+          // 新增训练营
+          addCamp(submitData).then(response => {
+            if (response.code === 200) {
+              this.$message.success('新建训练营成功');
+              this.addExistCampPeriod = false;
+              // 重新加载训练营列表
+              this.getLeftList();
+            } else {
+              this.$message.error(response.msg || '新建训练营失败');
+            }
+          }).catch(error => {
+            this.$message.error('新建训练营失败: ' + (error.message || '未知错误'));
+          });
+        }else {
+          // 显示全屏加载圈和遮蔽层
+          const loadingInstance = this.$loading({
+            lock: true,
+            text: '复制营期中,请耐心等待...',
+            spinner: 'el-icon-loading',
+            background: 'rgba(0, 0, 0, 0.7)'
+          });
+          // 调用批量添加小节接口
+          copyExistCampPeriod(submitData).then(response => {
+            if (response.code === 200) {
+              this.$message.success('复制营期成功');
+              this.course.addOpen = false;
+              this.addExistCampPeriod = false;
+              // 重新加载训练营列表
+              this.getList();
+            } else {
+              this.$message.error(response.msg || '复制营期失败');
+            }
+          }).catch(error => {
+            this.$message.error('复制营期失败:' + (error.message || '未知错误'));
+          }).finally(() => {
+            loadingInstance.close();   // 关闭加载圈
+          });
+        }
+      } catch (error) {
+        this.$message.error('提交失败:' + (error.message || '未知错误'));
+      } finally {
+        this.submitLoading = false;
+      }
+    },
+    /** 组装提交数据 */
+    buildSubmitData() {
+      const { campPeriodType, periodId, trainingCampName } = this.createCampPeriodForm;
+      const baseData = {
+        campPeriodType,
+        trainingCampId: this.trainingCampIdValue  // 这里已经正确添加了 trainingCampId
+      };
+      switch (campPeriodType) {
+        case 1: // 从当前训练营复制
+        case 2: // 从其他训练营复制
+          if (!periodId) {
+            throw new Error('请选择要复制的营期');
+          }
+          return { ...baseData, periodId };
+        case 3: // 新建营期
+          if (!trainingCampName?.trim()) {
+            throw new Error('请输入营期名称');
+          }
+          return { ...baseData, trainingCampName: trainingCampName.trim() };
+        default:
+          throw new Error('未知的创建方式');
+      }
+    },
+    /** 取消新建存在训练营 */
+    cancelExistCampPeriod() {
+      this.addExistCampPeriod = false;
+      this.resetForm();
+    },
+    /** 更新训练营序号 */
+    updateCampOrderNumber(item) {
+      // 校验序号值
+      if (!item.orderNumber || item.orderNumber < 1 || item.orderNumber > 9999) {
+        this.$message.warning('请输入有效的序号(1-9999)');
+        return;
+      }
+
+      // 调用接口更新序号,使用params传参
+      const params = {
+        trainingCampId: item.trainingCampId,
+        orderNumber: item.orderNumber
+      };
+
+      updateCampOrderNumber(params).then(response => {
+        if (response.code === 200) {
+          this.$message.success('训练营序号更新成功');
+          // 刷新训练营列表以保持排序一致(序号越大排在越前面)
+          this.getLeftList();
+        } else {
+          this.$message.error(response.msg || '训练营序号更新失败');
+          // 更新失败时刷新列表,恢复原值
+          this.getLeftList();
+        }
+      }).catch(error => {
+        this.$message.error('训练营序号更新失败:' + (error.message || '未知错误'));
+        // 更新失败时刷新列表,恢复原值
+        this.getLeftList();
+      });
+    },
   },
 };
 </script>