jinxia.mo 1 день назад
Родитель
Сommit
c865e2e68d

+ 9 - 5
back-ui/src/api/dz/cards.js

@@ -151,14 +151,18 @@ export function settleCard(cardIds) {
 }
 
 // 续费
-export function renewCard(cardIds) {
+export function renewCard(cardIds, days) {
+  const params = {
+    action: "Renew",
+    cardIds: Array.isArray(cardIds) ? cardIds.join(",") : cardIds,
+  };
+  if (days != null) {
+    params.days = days;
+  }
   return request({
     url: "/dz/cards/change/renew",
     method: "post",
-    params: {
-      action: "Renew",
-      cardIds: Array.isArray(cardIds) ? cardIds.join(",") : cardIds,
-    },
+    params: params,
   });
 }
 

+ 25 - 6
back-ui/src/views/dz/cards/index.vue

@@ -175,10 +175,10 @@
         <svg-icon icon-class="chart" class="mr-1" style="font-size: 12px" />
         结算
       </CustomButton>
-      <!-- <CustomButton color="#009688" :disabled="batchDisabled" @click="handleRenew">
+      <CustomButton color="#009688" :disabled="batchDisabled" @click="handleRenew">
         <svg-icon icon-class="time" class="mr-1" style="font-size: 14px" />
         续期
-      </CustomButton> -->
+      </CustomButton>
       <CustomButton color="#673AB7" v-hasPermi="['dz:cards:updateuser']"  :disabled="editDisabled" @click="handleEdit">
         <svg-icon icon-class="edit" class="mr-1" style="font-size: 12px" />
         修改
@@ -219,6 +219,7 @@ import RelateDialog from './components/RelateDialog.vue';
 import { listCards, delCards, payCard, closeCard, reopenCard, refundCard, settleCard, renewCard } from '@/api/dz/cards';
 import { CARD_STATUS, EnumCardType } from '@/common/enum';
 import { getCurrentInstance, nextTick } from 'vue';
+import { ElMessageBox } from 'element-plus';
 
 const { proxy } = getCurrentInstance();
 const {
@@ -413,11 +414,29 @@ const handleSettle = () => {
 }
 
 const handleRenew = () => {
-  proxy.$modal.confirm(`是否确认续费所选数据 (${ids.value.length}项) ?`).then(() => {
-    renewCard(ids.value).then(() => {
-      proxy.$modal.msgSuccess('续费成功')
-      getList()
+  // 使用 ElMessageBox.prompt 让用户输入续费天数
+  ElMessageBox.prompt('请输入续费天数', '续费', {
+    confirmButtonText: '确定',
+    cancelButtonText: '取消',
+    inputPattern: /^[1-9]\d*$/,
+    inputErrorMessage: '请输入有效的天数(大于0的整数)',
+    inputPlaceholder: '请输入续费天数,默认30天',
+    inputValue: '30', // 默认值30天
+  }).then(({ value }) => {
+    const days = value ? parseInt(value) : 30; // 如果为空,默认30天
+    if (isNaN(days) || days <= 0) {
+      proxy.$modal.msgError('请输入有效的天数(大于0的整数)');
+      return;
+    }
+    // 确认续费
+    proxy.$modal.confirm(`是否确认续费所选数据 (${ids.value.length}项) ${days}天?`).then(() => {
+      renewCard(ids.value, days).then(() => {
+        proxy.$modal.msgSuccess('续费成功')
+        getList()
+      })
     })
+  }).catch(() => {
+    // 用户取消输入,不做任何操作
   })
 }
 

+ 9 - 9
ie-admin/src/main/java/com/ruoyi/web/controller/dz/DzCardsController.java

@@ -302,45 +302,45 @@ public class DzCardsController extends BaseController
     @PostMapping("/change/pay")
     @ApiOperation("支付")
     public AjaxResult changePay(@ApiParam("卡ID") @RequestParam Long[] cardIds) {
-        return changeCard(CardAction.Pay, cardIds);
+        return changeCard(CardAction.Pay, cardIds, null);
     }
     @Log(title = "续费", businessType = BusinessType.UPDATE)
     @PostMapping("/change/renew")
     @ApiOperation("续费")
-    public AjaxResult changeRenew(@ApiParam("卡ID") @RequestParam Long[] cardIds) {
-        return changeCard(CardAction.Renew, cardIds);
+    public AjaxResult changeRenew(@ApiParam("卡ID") @RequestParam Long[] cardIds, @ApiParam("续费天数") @RequestParam(required = false) Integer days) {
+        return changeCard(CardAction.Renew, cardIds, days);
     }
     @Log(title = "结算", businessType = BusinessType.UPDATE)
     @PostMapping("/change/settlement")
     @ApiOperation("结算")
     public AjaxResult changeSettlement(@ApiParam("卡ID") @RequestParam Long[] cardIds) {
-        return changeCard(CardAction.Settlement, cardIds);
+        return changeCard(CardAction.Settlement, cardIds, null);
     }
     @Log(title = "重卡", businessType = BusinessType.UPDATE)
     @PostMapping("/change/reopen")
     @ApiOperation("重卡")
     public AjaxResult changeReopen(@ApiParam("卡ID") @RequestParam Long[] cardIds) {
-        return changeCard(CardAction.ReOpen, cardIds);
+        return changeCard(CardAction.ReOpen, cardIds, null);
     }
     @Log(title = "退费", businessType = BusinessType.UPDATE)
     @PostMapping("/change/refund")
     @ApiOperation("退费")
     public AjaxResult changeRefund(@ApiParam("卡ID") @RequestParam Long[] cardIds) {
-        return changeCard(CardAction.Refund, cardIds);
+        return changeCard(CardAction.Refund, cardIds, null);
     }
     @Log(title = "关卡", businessType = BusinessType.UPDATE)
     @PostMapping("/change/close")
     @ApiOperation("关卡")
     public AjaxResult changeClose(@ApiParam("卡ID") @RequestParam Long[] cardIds) {
-        return changeCard(CardAction.Close, cardIds);
+        return changeCard(CardAction.Close, cardIds, null);
     }
 
     @Log(title = "修改卡", businessType = BusinessType.UPDATE)
     @PostMapping("/changeCard")
     @ApiOperation("修改卡 重卡/关卡/支付/续费/结算")
-    public AjaxResult changeCard(@ApiParam("操作") @RequestParam CardAction action, @ApiParam("卡ID") @RequestParam Long[] cardIds)
+    public AjaxResult changeCard(@ApiParam("操作") @RequestParam CardAction action, @ApiParam("卡ID") @RequestParam Long[] cardIds, Integer days)
     {
-        dzCardsService.changeCard(action, cardIds);
+        dzCardsService.changeCard(action, cardIds,days);
         if ((CardAction.Close.equals(action) || CardAction.Refund.equals(action)) && ArrayUtils.isNotEmpty(cardIds)) {
             sysLoginService.resetTokens(sysUserService.selectUserByCardIds(Arrays.asList(cardIds)));
         } else if ((CardAction.ReOpen.equals(action) || CardAction.Renew.equals(action)) && ArrayUtils.isNotEmpty(cardIds)) {

+ 8 - 2
ie-admin/src/main/java/com/ruoyi/web/service/SysRegisterService.java

@@ -166,8 +166,8 @@ public class SysRegisterService
         if(CollectionUtils.isEmpty(sysUserList)) {
             throw new ValidationException("卡用户不存在");
         }
-        Long userId = sysUserList.get(0).getUserId();
-
+        SysUser dbUser = sysUserList.get(0);
+        Long userId = dbUser.getUserId();
         SysUser upUser = new SysUser();
         upUser.setUserId(userId);
         upUser.setNickName(cardUserBody.getNickName());
@@ -178,6 +178,12 @@ public class SysRegisterService
         upUser.setSchoolId(cardUserBody.getSchoolId());
         upUser.setClassId(cardUserBody.getClassId());
         upUser.setPhonenumber(cardUserBody.getMobile());
+        //如果手机号有修改,校验userName为手机号时也要跟着一起修改
+        if(null!=dbUser.getPhonenumber()&&!dbUser.getPhonenumber().equals(cardUserBody.getMobile().trim())) {
+            if (dbUser.getPhonenumber().equalsIgnoreCase(dbUser.getUserName())){
+                upUser.setUserName(cardUserBody.getMobile().trim());
+            }
+        }
         upUser.setExamMajor(cardUserBody.getExamMajor());
         upUser.setExamMajorName(cardUserBody.getExamMajorName());
         if (!userService.checkPhoneUnique(upUser)) {

+ 4 - 4
ie-system/src/main/java/com/ruoyi/dz/service/IDzCardsService.java

@@ -118,7 +118,7 @@ public interface IDzCardsService
      * @param action
      * @param cardIds
      */
-    public void changeCard(CardAction action, Long[] cardIds);
+    public void changeCard(CardAction action, Long[] cardIds,Integer days);
 
     /**
      * 分配校区
@@ -129,7 +129,7 @@ public interface IDzCardsService
      * @return
      */
     public Boolean changeCampus(Long campusId, Long campusClassId, String beginNo, String endNo);
-    
+
     /**
      * 通过卡片ID列表分配校区
      * @param campusId
@@ -138,12 +138,12 @@ public interface IDzCardsService
      * @return
      */
     public Boolean changeCampusByCardIds(Long campusId, Long campusClassId, Long[] cardIds);
-    
+
     public List<DzCards> selectCardsByCardIds(List<Long> cardIds);
 
     /**
      * 统计学习卡数据
-     * 
+     *
      * @param params 查询参数(deptId, agentId, openTimeBegin, openTimeEnd)
      * @return 统计结果列表
      */

+ 5 - 2
ie-system/src/main/java/com/ruoyi/dz/service/impl/DzCardsServiceImpl.java

@@ -407,7 +407,7 @@ public class DzCardsServiceImpl implements IDzCardsService
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public void changeCard(CardAction action, Long[] cardIds) {
+    public void changeCard(CardAction action, Long[] cardIds,Integer days) {
         List<DzCards> cards = dzCardsMapper.selectCardsByCardIds(cardIds);
         DzCards up = new DzCards();
         if(CardAction.Pay.equals(action)) {
@@ -448,7 +448,10 @@ public class DzCardsServiceImpl implements IDzCardsService
         for(DzCards card : cards) {
             up.setCardId(card.getCardId());
             if(CardAction.Renew.equals(action)) {
-                up.setOutDate(DateUtils.addYears(card.getOutDate(), 3)); // TODO 暂时都续费三年?
+                if (null==days){
+                    days =30;
+                }
+                up.setOutDate(DateUtils.addDays(card.getOutDate(), days)); // TODO 暂时都续费三年?
             }
             dzCardsMapper.updateDzCards(up);
         }

+ 40 - 27
ie-system/src/main/resources/mapper/learn/LearnStudentMapper.xml

@@ -116,64 +116,70 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     <select id="statisticStudyRecord" parameterType="com.ruoyi.learn.dto.StudyRecordStatisticsDTO" resultType="com.ruoyi.learn.dto.StudyRecordStatisticsDTO">
         WITH T1 AS (
             <!-- 定义查询 1 的聚合结果(做题统计)-->
+            <!-- 优化:从learn_answer开始JOIN,利用索引,避免date()函数 -->
             SELECT
                 a.student_id,
                 COUNT(*) AS num,
                 SUM(IF(a.state = 1, 1, 0)) AS correct,
-                ROUND(SUM(IF(a.state = 1, 1, 0)) * 100 / COUNT(*), 1) AS rate,
+                ROUND(SUM(IF(a.state = 1, 1, 0)) * 100.0 / COUNT(*), 1) AS rate,
                 COUNT(DISTINCT IF(le.paper_type IN (20,30), le.paper_id, null)) paperCount,
-                ROUND(SUM(IF(a.`state` = 1 AND le.paper_type IN (20,30), 1, 0)) * 100 / SUM(IF(le.paper_type IN (20,30), 1, 0)), 1) paperRate
-            FROM `sys_user` u
-            JOIN `dz_cards` dc ON u.card_id = dc.card_id
-            JOIN `learn_examinee` le ON le.student_id = u.user_id AND le.state >= 4
-            JOIN `learn_answer` a ON a.`examinee_id` = le.`examinee_id` AND a.`state` > 0
-            WHERE 1=1
+                ROUND(SUM(IF(a.`state` = 1 AND le.paper_type IN (20,30), 1, 0)) * 100.0 / NULLIF(SUM(IF(le.paper_type IN (20,30), 1, 0)), 0), 1) paperRate
+            FROM `learn_answer` a
+            INNER JOIN `learn_examinee` le ON a.`examinee_id` = le.`examinee_id` AND le.state >= 4
+            INNER JOIN `sys_user` u ON le.student_id = u.user_id
+            INNER JOIN `dz_cards` dc ON u.card_id = dc.card_id
+            WHERE a.`state` > 0
             <if test="studyTimeBegin != null and studyTimeBegin != ''">
-                AND (date(a.create_time) &gt;= date(#{studyTimeBegin}) OR date(le.end_time) &gt;= date(#{studyTimeBegin}))
+                <!-- 优化:去掉date()函数,直接比较datetime,可以使用索引 -->
+                AND (a.create_time &gt;= CONCAT(#{studyTimeBegin}, ' 00:00:00') OR le.end_time &gt;= CONCAT(#{studyTimeBegin}, ' 00:00:00'))
             </if>
             <if test="studyTimeEnd != null and studyTimeEnd != ''">
-                AND (date(a.create_time) &lt;= date(#{studyTimeEnd}) OR date(le.end_time) &lt;= date(#{studyTimeEnd}))
+                <!-- 优化:去掉date()函数,直接比较datetime,可以使用索引 -->
+                AND (a.create_time &lt;= CONCAT(#{studyTimeEnd}, ' 23:59:59') OR le.end_time &lt;= CONCAT(#{studyTimeEnd}, ' 23:59:59'))
             </if>
             GROUP BY a.student_id
         ),
         T2 AS (
             <!-- 定义查询 2 的聚合结果(视频观看统计)-->
+            <!-- 优化:去掉date()函数,直接比较datetime,可以使用索引 -->
             SELECT
                 ls.student_id,
                 COUNT(DISTINCT vw.title) AS total,
                 ROUND(SUM(vw.duration * vw.percent / 100.0)) AS value
             FROM `b_customer_video_watches` vw
-            JOIN `learn_student` ls ON vw.customerCode = ls.student_id
-            WHERE 1=1
-            <if test="studyTimeBegin != null and studyTimeBegin != ''">
-                AND date(vw.time) &gt;= date(#{studyTimeBegin})
-            </if>
-            <if test="studyTimeEnd != null and studyTimeEnd != ''">
-                AND date(vw.time) &lt;= date(#{studyTimeEnd})
-            </if>
+            INNER JOIN `learn_student` ls ON vw.customerCode = ls.student_id
+            <where>
+                <if test="studyTimeBegin != null and studyTimeBegin != ''">
+                    AND vw.time &gt;= CONCAT(#{studyTimeBegin}, ' 00:00:00')
+                </if>
+                <if test="studyTimeEnd != null and studyTimeEnd != ''">
+                    AND vw.time &lt;= CONCAT(#{studyTimeEnd}, ' 23:59:59')
+                </if>
+            </where>
             GROUP BY ls.student_id
         ),
         AllStudents AS (
             <!-- 提取所有涉及的唯一 Student ID-->
+            <!-- 优化:使用UNION ALL代替UNION,如果确定student_id不重复可以提升性能 -->
             SELECT student_id FROM T1
             UNION
             SELECT student_id FROM T2
         ),
         StudentBaseInfo AS (
             <!-- 获取所有涉及学生的基础信息-->
+            <!-- 优化:简化COALESCE,去掉不必要的NULL判断 -->
             SELECT DISTINCT
                 dc.dept_id,
                 asl.student_id,
-                COALESCE(dc.school_id, NULL) AS school_id,
-                COALESCE(dc.class_id, NULL) AS class_id,
-                COALESCE(dc.campus_id, NULL) AS campus_id,
-                COALESCE(dc.campus_class_id, NULL) AS campus_class_id,
-                COALESCE(dc.agent_id, NULL) AS agent_id,
-                COALESCE(dc.leaf_agent_id, NULL) AS leaf_agent_id,
+                dc.school_id,
+                dc.class_id,
+                dc.campus_id,
+                dc.campus_class_id,
+                dc.agent_id,
+                dc.leaf_agent_id,
                 u.nick_name AS nick_name,
-                COALESCE(dc.card_no, NULL) AS card_no
+                dc.card_no
             FROM AllStudents asl
-            <!-- 基础信息主要从 sys_user 和 dz_cards 获取-->
             LEFT JOIN `sys_user` u ON asl.student_id = u.user_id
             LEFT JOIN `dz_cards` dc ON u.card_id = dc.card_id
         )
@@ -214,8 +220,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <where>
             <if test="deptId != null"> AND SBI.dept_id = #{deptId}</if>
             <if test="schoolId != null"> AND SBI.school_id = #{schoolId}</if>
-            <if test="teacherId != null"> AND (SBI.class_id in ( SELECT t.class_id FROM dz_teacher_class t WHERE t.teacher_id = #{teacherId} and now() &lt; t.out_date)
-                 or SBI.campus_class_id in ( SELECT t.class_id FROM dz_teacher_class t WHERE t.teacher_id = #{teacherId} and now() &lt; t.out_date))</if>
+            <if test="teacherId != null">
+                <!-- 优化:将子查询改为EXISTS,性能更好 -->
+                AND EXISTS (
+                    SELECT 1 FROM dz_teacher_class t
+                    WHERE t.teacher_id = #{teacherId}
+                    AND NOW() &lt; t.out_date
+                    AND (t.class_id = SBI.class_id OR t.class_id = SBI.campus_class_id)
+                )
+            </if>
             <if test="classId != null"> AND SBI.class_id = #{classId}</if>
             <if test="campusId != null"> AND SBI.campus_id = #{campusId}</if>
             <if test="campusClassId != null"> AND SBI.campus_class_id = #{campusClassId}</if>