瀏覽代碼

Merge remote-tracking branch 'origin/bjcz_his_scrm' into bjcz_his_scrm

吴树波 1 月之前
父節點
當前提交
fc0d28b8a0

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

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

+ 18 - 0
src/api/hisStore/storeCouponUser.js

@@ -51,3 +51,21 @@ export function exportStoreCouponUser(query) {
     params: query
   })
 }
+
+// 立减金退款
+export function refundCashCoupon(data) {
+  return request({
+    url: '/store/storeCouponUser/refundCashCoupon',
+    method: 'post',
+    data: data
+  })
+}
+
+// 审批立减金退款
+export function approveCashCouponRefund(data) {
+  return request({
+    url: '/store/storeCouponUser/approveCashCouponRefund',
+    method: 'post',
+    data: data
+  })
+}

+ 109 - 16
src/views/course/userCoursePeriod/index.vue

@@ -367,14 +367,35 @@
           </el-select>
         </el-form-item>
         <el-form-item label="小节" prop="videoIds">
-          <el-select filterable  v-model="course.form.videoIds" placeholder="请选择小节" :multiple-limit="getDiff(course.row.periodStartingTime, course.row.periodEndTime) - course.total" multiple clearable size="small" style="width: 100%" :value-key="'dictValue'">
-            <el-option
-              v-for="dict in videoList"
-              :key="dict.dictValue"
-              :label="dict.dictLabel"
-              :value="parseInt(dict.dictValue)"
-            />
-          </el-select>
+          <div style="display: flex; align-items: center; gap: 10px; width: 100%;">
+            <el-select 
+              filterable 
+              v-model="course.form.videoIds" 
+              placeholder="请选择小节" 
+              :multiple-limit="getDiff(course.row.periodStartingTime, course.row.periodEndTime) - course.total" 
+              multiple 
+              clearable 
+              size="small" 
+              style="flex: 1" 
+              :value-key="'dictValue'"
+            >
+              <el-option
+                v-for="dict in videoList"
+                :key="dict.dictValue"
+                :label="dict.dictLabel"
+                :value="parseInt(dict.dictValue)"
+              />
+            </el-select>
+            <el-button 
+              type="primary" 
+              size="small" 
+              @click="handleBatchSelectSections"
+              :disabled="!course.form.courseId || !videoList || videoList.length === 0"
+              title="一键选择所有可用小节"
+            >
+              批量选择
+            </el-button>
+          </div>
         </el-form-item>
         <el-form-item label="看课时间" prop="timeRange">
           <el-time-picker
@@ -614,7 +635,7 @@
 </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} from "@/api/course/userCoursePeriod";
 import {getCompanyList} from "@/api/company/company";
 import { listCamp, addCamp, editCamp, delCamp, copyCamp } from "@/api/course/userCourseCamp";
 import { courseList,videoList } from '@/api/course/courseRedPacketLog'
@@ -1519,14 +1540,86 @@ export default {
             this.course.form.startTime = this.course.form.timeRange[0];
             this.course.form.endTime1 = this.course.form.timeRange[1];
           }
-          // 提交数据
-          addCourse(this.course.form).then(response => {
-            this.$message.success('添加成功');
-            this.course.addOpen = false;
-            // 重新加载训练营列表
-            this.getCourseList();
-          });
+          
+          // 检查是否有选择的小节
+          if (!this.course.form.videoIds || this.course.form.videoIds.length === 0) {
+            this.$message.warning('请选择至少一个小节');
+            return;
+          }
+          
+          // 如果选择了多个小节,使用批量添加接口
+          if (this.course.form.videoIds.length > 1) {
+            const batchData = {
+              periodId: this.course.form.periodId,
+              courseId: this.course.form.courseId,
+              videoIds: this.course.form.videoIds,
+              startTime: this.course.form.startTime,
+              endTime1: this.course.form.endTime1,
+              endDateTime: this.course.form.endTime1, // 添加endDateTime参数
+              joinTime: this.course.form.joinTime
+            };
+            
+            // 调用批量添加小节接口
+            batchAddCourseSections(batchData).then(response => {
+              if (response.code === 200) {
+                this.$message.success('批量添加课程成功');
+                this.course.addOpen = false;
+                this.getCourseList();
+              } else {
+                this.$message.error(response.msg || '批量添加课程失败');
+              }
+            }).catch(error => {
+              this.$message.error('批量添加课程失败:' + (error.message || '未知错误'));
+            });
+          } else {
+            // 单个小节,使用原来的接口
+            addCourse(this.course.form).then(response => {
+              this.$message.success('添加成功');
+              this.course.addOpen = false;
+              this.getCourseList();
+            }).catch(error => {
+              this.$message.error('添加失败:' + (error.message || '未知错误'));
+            });
+          }
+        }
+      });
+    },
+    /** 批量选择小节 */
+    handleBatchSelectSections() {
+      if (!this.course.form.courseId) {
+        this.$message.warning('请先选择课程');
+        return;
+      }
+      
+      if (!this.videoList || this.videoList.length === 0) {
+        this.$message.warning('该课程下暂无可选择的小节');
+        return;
+      }
+      
+      this.$confirm('确认要批量选择所有小节吗?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'info'
+      }).then(() => {
+        // 获取所有可用的小节ID
+        const allVideoIds = this.videoList.map(video => parseInt(video.dictValue));
+        
+        // 获取剩余可选择数量
+        const remainingLimit = this.getDiff(this.course.row.periodStartingTime, this.course.row.periodEndTime) - this.course.total;
+        
+        // 只选择剩余数量内的小节
+        const selectedVideoIds = allVideoIds.slice(0, remainingLimit);
+        
+        if (selectedVideoIds.length === 0) {
+          this.$message.warning('已达到营期天数限制,无法添加更多小节');
+          return;
         }
+        
+        // 将选中的小节ID设置到表单中(只是选择,不调用API)
+        this.course.form.videoIds = selectedVideoIds;
+        this.$message.success(`批量选择成功,已选择 ${selectedVideoIds.length} 个小节`);
+      }).catch(() => {
+        this.$message.info('已取消批量选择');
       });
     },
     submitUpdateCourseForm(){

+ 168 - 4
src/views/hisStore/storeInstantDiscountUser/index.vue

@@ -59,11 +59,11 @@
       <el-table-column label="立减金名称" align="center" prop="couponTitle" />
       <el-table-column label="立减金面值" align="center" prop="couponPrice" />
       <el-table-column label="最低消费" align="center" prop="useMinPrice" />
-      <el-table-column label="立减金结束时间" align="center" prop="limitTime" width="180">
+      <!-- <el-table-column label="立减金结束时间" align="center" prop="limitTime" width="180">
         <template slot-scope="scope">
           <span>{{ parseTime(scope.row.limitTime, '{y}-{m}-{d}') }}</span>
         </template>
-      </el-table-column>
+      </el-table-column> -->
       <el-table-column label="领取时间" align="center" prop="createTime" width="180">
         <template slot-scope="scope">
           <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
@@ -82,6 +82,32 @@
       <el-table-column label="状态" align="center" prop="status">
         <template slot-scope="scope">
           <dict-tag :options="statusOptions" :value="scope.row.status"/>
+          <!-- 如果字典中没有定义,则显示默认文本 -->
+          <span v-if="!getStatusLabel(scope.row.status)">
+            {{ getDefaultStatusText(scope.row.status) }}
+          </span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <!-- 状态为0(未使用)和1(已使用)时显示退款按钮 -->
+          <el-button
+            v-if="scope.row.status == 0 || scope.row.status == 1"
+            size="mini"
+            type="text"
+            icon="el-icon-refresh-left"
+            @click="handleRefund(scope.row)"
+            v-hasPermi="['store:storeInstantDiscountUser:refund']"
+          >退款</el-button>
+          <!-- 所有状态都显示审核按钮 -->
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-check"
+            @click="handleApprove(scope.row)"
+            v-hasPermi="['store:storeInstantDiscountUser:approve']"
+            style="color: #67C23A;"
+          >审核</el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -93,18 +119,51 @@
       :limit.sync="queryParams.pageSize"
       @pagination="getList"
     />
+
+    <!-- 审核对话框 -->
+    <el-dialog title="审核立减金退款" :visible.sync="approveDialogVisible" width="500px" append-to-body>
+      <el-form ref="approveForm" :model="approveForm" :rules="approveRules" label-width="100px">
+        <el-form-item label="审核结果" prop="approvalStatus">
+          <el-radio-group v-model="approveForm.approvalStatus">
+            <el-radio :label="1">通过</el-radio>
+            <el-radio :label="2">拒绝</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="审核备注" prop="approvalRemark">
+          <el-input
+            v-model="approveForm.approvalRemark"
+            type="textarea"
+            :rows="4"
+            placeholder="请输入审核意见"
+            maxlength="500"
+            show-word-limit
+          />
+        </el-form-item>
+        <el-form-item label="审核人" prop="approver">
+          <el-input
+            v-model="approveForm.approver"
+            placeholder="请输入审核人"
+            :disabled="true"
+          />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="cancelApprove">取消</el-button>
+        <el-button type="primary" @click="confirmApprove">确定</el-button>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
 <script>
-import { listStoreCouponUser, getStoreCouponUser, delStoreCouponUser, addStoreCouponUser, updateStoreCouponUser, exportStoreCouponUser } from "@/api/hisStore/storeCouponUser";
+import { listStoreCouponUser, getStoreCouponUser, delStoreCouponUser, addStoreCouponUser, updateStoreCouponUser, exportStoreCouponUser, refundCashCoupon, approveCashCouponRefund } from "@/api/hisStore/storeCouponUser";
 
 export default {
   name: "HisStoreInstantDiscountUser",
   data() {
     return {
       statusOptions: [],
-      // 遮罩层
+      // 罩层
       loading: true,
       // 选中数组
       ids: [],
@@ -123,6 +182,30 @@ export default {
       title: "",
       // 是否显示弹出层
       open: false,
+      // 审核对话框显示状态
+      approveDialogVisible: false,
+      // 审核表单数据
+      approveForm: {
+        id: null,
+        couponId: null,
+        userId: null,
+        couponType: 3,
+        approvalStatus: 1,
+        approvalRemark: '',
+        approver: ''
+      },
+      // 审核表单校验
+      approveRules: {
+        approvalStatus: [
+          { required: true, message: "请选择审核结果", trigger: "change" }
+        ],
+        approvalRemark: [
+          { required: true, message: "请输入审核备注", trigger: "blur" }
+        ],
+        approver: [
+          { required: true, message: "审核人不能为空", trigger: "blur" }
+        ]
+      },
       // 查询参数
       queryParams: {
         pageNum: 1,
@@ -182,6 +265,8 @@ export default {
     this.getDicts("store_coupon_user_status").then((response) => {
       this.statusOptions = response.data;
     });
+    // 初始化审核人信息(可以从用户信息中获取)
+    this.approveForm.approver = this.$store.getters.name || '';
     this.getList();
   },
   methods: {
@@ -304,6 +389,85 @@ export default {
         }).then(response => {
           this.download(response.msg);
         }).catch(function() {});
+    },
+    /** 退款按钮操作 */
+    handleRefund(row) {
+      const refundData = {
+        id: row.id,
+        couponId: row.couponId,
+        userId: row.userId,
+        couponType: 3
+      };
+      
+      this.$confirm('是否确认退款该立减金?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        return refundCashCoupon(refundData);
+      }).then(response => {
+        if (response.code === 200) {
+          this.msgSuccess("退款成功");
+          this.getList();
+        } else {
+          this.msgError(response.msg || "退款失败");
+        }
+      }).catch(() => {
+        this.msgInfo("已取消退款操作");
+      });
+    },
+    /** 审核退款按钮操作 */
+    handleApprove(row) {
+      // 重置审核表单
+      this.approveForm = {
+        id: row.id,
+        couponId: row.couponId,
+        userId: row.userId,
+        couponType: 3,
+        approvalStatus: 1,
+        approvalRemark: '',
+        approver: this.$store.getters.name || ''
+      };
+      this.approveDialogVisible = true;
+    },
+    /** 取消审核 */
+    cancelApprove() {
+      this.approveDialogVisible = false;
+      this.$refs.approveForm.resetFields();
+    },
+    /** 确认审核 */
+    confirmApprove() {
+      this.$refs.approveForm.validate(valid => {
+        if (valid) {
+          approveCashCouponRefund(this.approveForm).then(response => {
+            if (response.code === 200) {
+              this.msgSuccess("审核成功");
+              this.approveDialogVisible = false;
+              this.getList();
+            } else {
+              this.msgError(response.msg || "审核失败");
+            }
+          }).catch(() => {
+            this.msgError("审核操作失败");
+          });
+        }
+      });
+    },
+    /** 获取字典中的状态标签 */
+    getStatusLabel(status) {
+      const option = this.statusOptions.find(item => item.dictValue == status);
+      return option ? option.dictLabel : null;
+    },
+    /** 获取默认状态文本 */
+    getDefaultStatusText(status) {
+      const statusMap = {
+        0: '未使用',
+        1: '已使用',
+        2: '已过期',
+        3: '已退款',
+        4: '退款中'
+      };
+      return statusMap[status] || '未知状态';
     }
   }
 };